1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------ 2e5c31af7Sopenharmony_ci* Vulkan Conformance Tests 3e5c31af7Sopenharmony_ci* ------------------------ 4e5c31af7Sopenharmony_ci* 5e5c31af7Sopenharmony_ci* Copyright (c) 2016 The Khronos Group Inc. 6e5c31af7Sopenharmony_ci* Copyright (c) 2023 LunarG, Inc. 7e5c31af7Sopenharmony_ci* Copyright (c) 2023 Nintendo 8e5c31af7Sopenharmony_ci* 9e5c31af7Sopenharmony_ci* Licensed under the Apache License, Version 2.0 (the "License"); 10e5c31af7Sopenharmony_ci* you may not use this file except in compliance with the License. 11e5c31af7Sopenharmony_ci* You may obtain a copy of the License at 12e5c31af7Sopenharmony_ci* 13e5c31af7Sopenharmony_ci* http://www.apache.org/licenses/LICENSE-2.0 14e5c31af7Sopenharmony_ci* 15e5c31af7Sopenharmony_ci* Unless required by applicable law or agreed to in writing, software 16e5c31af7Sopenharmony_ci* distributed under the License is distributed on an "AS IS" BASIS, 17e5c31af7Sopenharmony_ci* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18e5c31af7Sopenharmony_ci* See the License for the specific language governing permissions and 19e5c31af7Sopenharmony_ci* limitations under the License. 20e5c31af7Sopenharmony_ci* 21e5c31af7Sopenharmony_ci*//* 22e5c31af7Sopenharmony_ci* \file vktPipelineMultisampleShaderBuiltInTests.cpp 23e5c31af7Sopenharmony_ci* \brief Multisample Shader BuiltIn Tests 24e5c31af7Sopenharmony_ci*//*--------------------------------------------------------------------*/ 25e5c31af7Sopenharmony_ci 26e5c31af7Sopenharmony_ci#include "vktPipelineMultisampleShaderBuiltInTests.hpp" 27e5c31af7Sopenharmony_ci#include "vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp" 28e5c31af7Sopenharmony_ci#include "vktPipelineMakeUtil.hpp" 29e5c31af7Sopenharmony_ci 30e5c31af7Sopenharmony_ci#include "vkBuilderUtil.hpp" 31e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp" 32e5c31af7Sopenharmony_ci#include "vkObjUtil.hpp" 33e5c31af7Sopenharmony_ci#include "vkImageWithMemory.hpp" 34e5c31af7Sopenharmony_ci#include "vkBufferWithMemory.hpp" 35e5c31af7Sopenharmony_ci#include "vkBarrierUtil.hpp" 36e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp" 37e5c31af7Sopenharmony_ci#include "vkTypeUtil.hpp" 38e5c31af7Sopenharmony_ci 39e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp" 40e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 41e5c31af7Sopenharmony_ci 42e5c31af7Sopenharmony_ci#include <set> 43e5c31af7Sopenharmony_ci#include <cmath> 44e5c31af7Sopenharmony_ci 45e5c31af7Sopenharmony_ciusing std::set; 46e5c31af7Sopenharmony_ci 47e5c31af7Sopenharmony_cinamespace vkt 48e5c31af7Sopenharmony_ci{ 49e5c31af7Sopenharmony_cinamespace pipeline 50e5c31af7Sopenharmony_ci{ 51e5c31af7Sopenharmony_cinamespace multisample 52e5c31af7Sopenharmony_ci{ 53e5c31af7Sopenharmony_ci 54e5c31af7Sopenharmony_ciusing namespace vk; 55e5c31af7Sopenharmony_ci 56e5c31af7Sopenharmony_cistruct VertexDataNdc 57e5c31af7Sopenharmony_ci{ 58e5c31af7Sopenharmony_ci VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {} 59e5c31af7Sopenharmony_ci 60e5c31af7Sopenharmony_ci tcu::Vec4 positionNdc; 61e5c31af7Sopenharmony_ci}; 62e5c31af7Sopenharmony_ci 63e5c31af7Sopenharmony_ciMultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdc (void) 64e5c31af7Sopenharmony_ci{ 65e5c31af7Sopenharmony_ci MultisampleInstanceBase::VertexDataDesc vertexDataDesc; 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_ci vertexDataDesc.verticesCount = 4u; 68e5c31af7Sopenharmony_ci vertexDataDesc.dataStride = sizeof(VertexDataNdc); 69e5c31af7Sopenharmony_ci vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; 70e5c31af7Sopenharmony_ci vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; 71e5c31af7Sopenharmony_ci 72e5c31af7Sopenharmony_ci const VkVertexInputAttributeDescription vertexAttribPositionNdc = 73e5c31af7Sopenharmony_ci { 74e5c31af7Sopenharmony_ci 0u, // deUint32 location; 75e5c31af7Sopenharmony_ci 0u, // deUint32 binding; 76e5c31af7Sopenharmony_ci VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 77e5c31af7Sopenharmony_ci DE_OFFSET_OF(VertexDataNdc, positionNdc), // deUint32 offset; 78e5c31af7Sopenharmony_ci }; 79e5c31af7Sopenharmony_ci 80e5c31af7Sopenharmony_ci vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); 81e5c31af7Sopenharmony_ci 82e5c31af7Sopenharmony_ci return vertexDataDesc; 83e5c31af7Sopenharmony_ci} 84e5c31af7Sopenharmony_ci 85e5c31af7Sopenharmony_civoid uploadVertexDataNdc (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton) 86e5c31af7Sopenharmony_ci{ 87e5c31af7Sopenharmony_ci std::vector<VertexDataNdc> vertices; 88e5c31af7Sopenharmony_ci 89e5c31af7Sopenharmony_ci vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f))); 90e5c31af7Sopenharmony_ci vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f))); 91e5c31af7Sopenharmony_ci vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f))); 92e5c31af7Sopenharmony_ci vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f))); 93e5c31af7Sopenharmony_ci 94e5c31af7Sopenharmony_ci deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize)); 95e5c31af7Sopenharmony_ci} 96e5c31af7Sopenharmony_ci 97e5c31af7Sopenharmony_cistruct VertexDataNdcScreen 98e5c31af7Sopenharmony_ci{ 99e5c31af7Sopenharmony_ci VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {} 100e5c31af7Sopenharmony_ci 101e5c31af7Sopenharmony_ci tcu::Vec4 positionNdc; 102e5c31af7Sopenharmony_ci tcu::Vec2 positionScreen; 103e5c31af7Sopenharmony_ci}; 104e5c31af7Sopenharmony_ci 105e5c31af7Sopenharmony_ciMultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdcScreen (void) 106e5c31af7Sopenharmony_ci{ 107e5c31af7Sopenharmony_ci MultisampleInstanceBase::VertexDataDesc vertexDataDesc; 108e5c31af7Sopenharmony_ci 109e5c31af7Sopenharmony_ci vertexDataDesc.verticesCount = 4u; 110e5c31af7Sopenharmony_ci vertexDataDesc.dataStride = sizeof(VertexDataNdcScreen); 111e5c31af7Sopenharmony_ci vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; 112e5c31af7Sopenharmony_ci vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; 113e5c31af7Sopenharmony_ci 114e5c31af7Sopenharmony_ci const VkVertexInputAttributeDescription vertexAttribPositionNdc = 115e5c31af7Sopenharmony_ci { 116e5c31af7Sopenharmony_ci 0u, // deUint32 location; 117e5c31af7Sopenharmony_ci 0u, // deUint32 binding; 118e5c31af7Sopenharmony_ci VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 119e5c31af7Sopenharmony_ci DE_OFFSET_OF(VertexDataNdcScreen, positionNdc), // deUint32 offset; 120e5c31af7Sopenharmony_ci }; 121e5c31af7Sopenharmony_ci 122e5c31af7Sopenharmony_ci vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); 123e5c31af7Sopenharmony_ci 124e5c31af7Sopenharmony_ci const VkVertexInputAttributeDescription vertexAttribPositionScreen = 125e5c31af7Sopenharmony_ci { 126e5c31af7Sopenharmony_ci 1u, // deUint32 location; 127e5c31af7Sopenharmony_ci 0u, // deUint32 binding; 128e5c31af7Sopenharmony_ci VK_FORMAT_R32G32_SFLOAT, // VkFormat format; 129e5c31af7Sopenharmony_ci DE_OFFSET_OF(VertexDataNdcScreen, positionScreen), // deUint32 offset; 130e5c31af7Sopenharmony_ci }; 131e5c31af7Sopenharmony_ci 132e5c31af7Sopenharmony_ci vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen); 133e5c31af7Sopenharmony_ci 134e5c31af7Sopenharmony_ci return vertexDataDesc; 135e5c31af7Sopenharmony_ci} 136e5c31af7Sopenharmony_ci 137e5c31af7Sopenharmony_civoid uploadVertexDataNdcScreen (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton, const tcu::Vec2& screenSize) 138e5c31af7Sopenharmony_ci{ 139e5c31af7Sopenharmony_ci std::vector<VertexDataNdcScreen> vertices; 140e5c31af7Sopenharmony_ci 141e5c31af7Sopenharmony_ci vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f))); 142e5c31af7Sopenharmony_ci vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), 0.0f))); 143e5c31af7Sopenharmony_ci vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSize.y()))); 144e5c31af7Sopenharmony_ci vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), screenSize.y()))); 145e5c31af7Sopenharmony_ci 146e5c31af7Sopenharmony_ci deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize)); 147e5c31af7Sopenharmony_ci} 148e5c31af7Sopenharmony_ci 149e5c31af7Sopenharmony_cibool checkForErrorMS (const vk::VkImageCreateInfo& imageMSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const deUint32 errorCompNdx) 150e5c31af7Sopenharmony_ci{ 151e5c31af7Sopenharmony_ci const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples); 152e5c31af7Sopenharmony_ci 153e5c31af7Sopenharmony_ci for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z) 154e5c31af7Sopenharmony_ci for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y) 155e5c31af7Sopenharmony_ci for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x) 156e5c31af7Sopenharmony_ci { 157e5c31af7Sopenharmony_ci for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 158e5c31af7Sopenharmony_ci { 159e5c31af7Sopenharmony_ci const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[errorCompNdx]; 160e5c31af7Sopenharmony_ci 161e5c31af7Sopenharmony_ci if (errorComponent > 0) 162e5c31af7Sopenharmony_ci return true; 163e5c31af7Sopenharmony_ci } 164e5c31af7Sopenharmony_ci } 165e5c31af7Sopenharmony_ci 166e5c31af7Sopenharmony_ci return false; 167e5c31af7Sopenharmony_ci} 168e5c31af7Sopenharmony_ci 169e5c31af7Sopenharmony_cibool checkForErrorRS (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx) 170e5c31af7Sopenharmony_ci{ 171e5c31af7Sopenharmony_ci for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) 172e5c31af7Sopenharmony_ci for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) 173e5c31af7Sopenharmony_ci for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) 174e5c31af7Sopenharmony_ci { 175e5c31af7Sopenharmony_ci const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx]; 176e5c31af7Sopenharmony_ci 177e5c31af7Sopenharmony_ci if (errorComponent > 0) 178e5c31af7Sopenharmony_ci return true; 179e5c31af7Sopenharmony_ci } 180e5c31af7Sopenharmony_ci 181e5c31af7Sopenharmony_ci return false; 182e5c31af7Sopenharmony_ci} 183e5c31af7Sopenharmony_ci 184e5c31af7Sopenharmony_citemplate <typename CaseClassName> 185e5c31af7Sopenharmony_ciclass MSCase : public MSCaseBaseResolveAndPerSampleFetch 186e5c31af7Sopenharmony_ci{ 187e5c31af7Sopenharmony_cipublic: 188e5c31af7Sopenharmony_ci MSCase (tcu::TestContext& testCtx, 189e5c31af7Sopenharmony_ci const std::string& name, 190e5c31af7Sopenharmony_ci const ImageMSParams& imageMSParams) 191e5c31af7Sopenharmony_ci : MSCaseBaseResolveAndPerSampleFetch(testCtx, name, imageMSParams) {} 192e5c31af7Sopenharmony_ci 193e5c31af7Sopenharmony_ci virtual void checkSupport (Context& context) const; 194e5c31af7Sopenharmony_ci void init (void); 195e5c31af7Sopenharmony_ci void initPrograms (vk::SourceCollections& programCollection) const; 196e5c31af7Sopenharmony_ci TestInstance* createInstance (Context& context) const; 197e5c31af7Sopenharmony_ci static MultisampleCaseBase* createCase (tcu::TestContext& testCtx, 198e5c31af7Sopenharmony_ci const std::string& name, 199e5c31af7Sopenharmony_ci const ImageMSParams& imageMSParams); 200e5c31af7Sopenharmony_ci}; 201e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC 202e5c31af7Sopenharmony_citemplate <typename CaseClassName> 203e5c31af7Sopenharmony_civoid MSCase<CaseClassName>::checkSupport(Context& context) const 204e5c31af7Sopenharmony_ci{ 205e5c31af7Sopenharmony_ci checkGraphicsPipelineLibrarySupport(context); 206e5c31af7Sopenharmony_ci} 207e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC 208e5c31af7Sopenharmony_ci 209e5c31af7Sopenharmony_citemplate <typename CaseClassName> 210e5c31af7Sopenharmony_ciMultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) 211e5c31af7Sopenharmony_ci{ 212e5c31af7Sopenharmony_ci return new MSCase<CaseClassName>(testCtx, name, imageMSParams); 213e5c31af7Sopenharmony_ci} 214e5c31af7Sopenharmony_ci 215e5c31af7Sopenharmony_citemplate <typename InstanceClassName> 216e5c31af7Sopenharmony_ciclass MSInstance : public MSInstanceBaseResolveAndPerSampleFetch 217e5c31af7Sopenharmony_ci{ 218e5c31af7Sopenharmony_cipublic: 219e5c31af7Sopenharmony_ci MSInstance (Context& context, 220e5c31af7Sopenharmony_ci const ImageMSParams& imageMSParams) 221e5c31af7Sopenharmony_ci : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams) {} 222e5c31af7Sopenharmony_ci 223e5c31af7Sopenharmony_ci VertexDataDesc getVertexDataDescripton (void) const; 224e5c31af7Sopenharmony_ci void uploadVertexData (const Allocation& vertexBufferAllocation, 225e5c31af7Sopenharmony_ci const VertexDataDesc& vertexDataDescripton) const; 226e5c31af7Sopenharmony_ci 227e5c31af7Sopenharmony_ci tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 228e5c31af7Sopenharmony_ci const vk::VkImageCreateInfo& imageRSInfo, 229e5c31af7Sopenharmony_ci const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 230e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& dataRS) const; 231e5c31af7Sopenharmony_ci 232e5c31af7Sopenharmony_ci virtual VkPipelineMultisampleStateCreateInfo getMSStateCreateInfo (const ImageMSParams& imageMSParams) const 233e5c31af7Sopenharmony_ci { 234e5c31af7Sopenharmony_ci return MSInstanceBaseResolveAndPerSampleFetch::getMSStateCreateInfo(imageMSParams); 235e5c31af7Sopenharmony_ci } 236e5c31af7Sopenharmony_ci}; 237e5c31af7Sopenharmony_ci 238e5c31af7Sopenharmony_ciclass MSInstanceSampleID; 239e5c31af7Sopenharmony_ci 240e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleID>::getVertexDataDescripton (void) const 241e5c31af7Sopenharmony_ci{ 242e5c31af7Sopenharmony_ci return getVertexDataDescriptonNdc(); 243e5c31af7Sopenharmony_ci} 244e5c31af7Sopenharmony_ci 245e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceSampleID>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 246e5c31af7Sopenharmony_ci{ 247e5c31af7Sopenharmony_ci uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); 248e5c31af7Sopenharmony_ci} 249e5c31af7Sopenharmony_ci 250e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceSampleID>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 251e5c31af7Sopenharmony_ci const vk::VkImageCreateInfo& imageRSInfo, 252e5c31af7Sopenharmony_ci const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 253e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& dataRS) const 254e5c31af7Sopenharmony_ci{ 255e5c31af7Sopenharmony_ci DE_UNREF(imageRSInfo); 256e5c31af7Sopenharmony_ci DE_UNREF(dataRS); 257e5c31af7Sopenharmony_ci 258e5c31af7Sopenharmony_ci const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples); 259e5c31af7Sopenharmony_ci 260e5c31af7Sopenharmony_ci for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 261e5c31af7Sopenharmony_ci { 262e5c31af7Sopenharmony_ci for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z) 263e5c31af7Sopenharmony_ci for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y) 264e5c31af7Sopenharmony_ci for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x) 265e5c31af7Sopenharmony_ci { 266e5c31af7Sopenharmony_ci const deUint32 sampleID = dataPerSample[sampleNdx].getPixelUint(x, y, z).x(); 267e5c31af7Sopenharmony_ci 268e5c31af7Sopenharmony_ci if (sampleID != sampleNdx) 269e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("gl_SampleID does not have correct value"); 270e5c31af7Sopenharmony_ci } 271e5c31af7Sopenharmony_ci } 272e5c31af7Sopenharmony_ci 273e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Passed"); 274e5c31af7Sopenharmony_ci} 275e5c31af7Sopenharmony_ci 276e5c31af7Sopenharmony_ciclass MSCaseSampleID; 277e5c31af7Sopenharmony_ci 278e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleID>::checkSupport (Context& context) const 279e5c31af7Sopenharmony_ci{ 280e5c31af7Sopenharmony_ci checkGraphicsPipelineLibrarySupport(context); 281e5c31af7Sopenharmony_ci context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 282e5c31af7Sopenharmony_ci} 283e5c31af7Sopenharmony_ci 284e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleID>::init (void) 285e5c31af7Sopenharmony_ci{ 286e5c31af7Sopenharmony_ci m_testCtx.getLog() 287e5c31af7Sopenharmony_ci << tcu::TestLog::Message 288e5c31af7Sopenharmony_ci << "Writing gl_SampleID to the red channel of the texture and verifying texture values.\n" 289e5c31af7Sopenharmony_ci << "Expecting value N at sample index N of a multisample texture.\n" 290e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 291e5c31af7Sopenharmony_ci 292e5c31af7Sopenharmony_ci MultisampleCaseBase::init(); 293e5c31af7Sopenharmony_ci} 294e5c31af7Sopenharmony_ci 295e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleID>::initPrograms (vk::SourceCollections& programCollection) const 296e5c31af7Sopenharmony_ci{ 297e5c31af7Sopenharmony_ci MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 298e5c31af7Sopenharmony_ci 299e5c31af7Sopenharmony_ci // Create vertex shader 300e5c31af7Sopenharmony_ci std::ostringstream vs; 301e5c31af7Sopenharmony_ci 302e5c31af7Sopenharmony_ci vs << "#version 440\n" 303e5c31af7Sopenharmony_ci << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 304e5c31af7Sopenharmony_ci << "\n" 305e5c31af7Sopenharmony_ci << "out gl_PerVertex {\n" 306e5c31af7Sopenharmony_ci << " vec4 gl_Position;\n" 307e5c31af7Sopenharmony_ci << "};\n" 308e5c31af7Sopenharmony_ci << "void main (void)\n" 309e5c31af7Sopenharmony_ci << "{\n" 310e5c31af7Sopenharmony_ci << " gl_Position = vs_in_position_ndc;\n" 311e5c31af7Sopenharmony_ci << "}\n"; 312e5c31af7Sopenharmony_ci 313e5c31af7Sopenharmony_ci programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 314e5c31af7Sopenharmony_ci 315e5c31af7Sopenharmony_ci // Create fragment shader 316e5c31af7Sopenharmony_ci std::ostringstream fs; 317e5c31af7Sopenharmony_ci 318e5c31af7Sopenharmony_ci fs << "#version 440\n" 319e5c31af7Sopenharmony_ci << "\n" 320e5c31af7Sopenharmony_ci << "layout(location = 0) out vec4 fs_out_color;\n" 321e5c31af7Sopenharmony_ci << "\n" 322e5c31af7Sopenharmony_ci << "void main (void)\n" 323e5c31af7Sopenharmony_ci << "{\n" 324e5c31af7Sopenharmony_ci << " fs_out_color = vec4(float(gl_SampleID) / float(255), 0.0, 0.0, 1.0);\n" 325e5c31af7Sopenharmony_ci << "}\n"; 326e5c31af7Sopenharmony_ci 327e5c31af7Sopenharmony_ci programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 328e5c31af7Sopenharmony_ci} 329e5c31af7Sopenharmony_ci 330e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSampleID>::createInstance (Context& context) const 331e5c31af7Sopenharmony_ci{ 332e5c31af7Sopenharmony_ci return new MSInstance<MSInstanceSampleID>(context, m_imageMSParams); 333e5c31af7Sopenharmony_ci} 334e5c31af7Sopenharmony_ci 335e5c31af7Sopenharmony_ciclass MSInstanceSamplePosDistribution; 336e5c31af7Sopenharmony_ci 337e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosDistribution>::getVertexDataDescripton (void) const 338e5c31af7Sopenharmony_ci{ 339e5c31af7Sopenharmony_ci return getVertexDataDescriptonNdc(); 340e5c31af7Sopenharmony_ci} 341e5c31af7Sopenharmony_ci 342e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceSamplePosDistribution>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 343e5c31af7Sopenharmony_ci{ 344e5c31af7Sopenharmony_ci uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); 345e5c31af7Sopenharmony_ci} 346e5c31af7Sopenharmony_ci 347e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceSamplePosDistribution>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 348e5c31af7Sopenharmony_ci const vk::VkImageCreateInfo& imageRSInfo, 349e5c31af7Sopenharmony_ci const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 350e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& dataRS) const 351e5c31af7Sopenharmony_ci{ 352e5c31af7Sopenharmony_ci const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples); 353e5c31af7Sopenharmony_ci 354e5c31af7Sopenharmony_ci // approximate Bates distribution as normal 355e5c31af7Sopenharmony_ci const float variance = (1.0f / (12.0f * (float)numSamples)); 356e5c31af7Sopenharmony_ci const float standardDeviation = deFloatSqrt(variance); 357e5c31af7Sopenharmony_ci 358e5c31af7Sopenharmony_ci // 95% of means of sample positions are within 2 standard deviations if 359e5c31af7Sopenharmony_ci // they were randomly assigned. Sample patterns are expected to be more 360e5c31af7Sopenharmony_ci // uniform than a random pattern. 361e5c31af7Sopenharmony_ci const float distanceThreshold = 2.0f * standardDeviation; 362e5c31af7Sopenharmony_ci 363e5c31af7Sopenharmony_ci for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) 364e5c31af7Sopenharmony_ci for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) 365e5c31af7Sopenharmony_ci for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) 366e5c31af7Sopenharmony_ci { 367e5c31af7Sopenharmony_ci const deUint32 errorComponent = dataRS.getPixelUint(x, y, z).z(); 368e5c31af7Sopenharmony_ci 369e5c31af7Sopenharmony_ci if (errorComponent > 0) 370e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]"); 371e5c31af7Sopenharmony_ci 372e5c31af7Sopenharmony_ci if (numSamples >= VK_SAMPLE_COUNT_4_BIT) 373e5c31af7Sopenharmony_ci { 374e5c31af7Sopenharmony_ci const tcu::Vec2 averageSamplePos = tcu::Vec2((float)dataRS.getPixelUint(x, y, z).x() / 255.0f, (float)dataRS.getPixelUint(x, y, z).y() / 255.0f); 375e5c31af7Sopenharmony_ci const tcu::Vec2 distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f)); 376e5c31af7Sopenharmony_ci 377e5c31af7Sopenharmony_ci if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold) 378e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel"); 379e5c31af7Sopenharmony_ci } 380e5c31af7Sopenharmony_ci } 381e5c31af7Sopenharmony_ci 382e5c31af7Sopenharmony_ci for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z) 383e5c31af7Sopenharmony_ci for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y) 384e5c31af7Sopenharmony_ci for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x) 385e5c31af7Sopenharmony_ci { 386e5c31af7Sopenharmony_ci std::vector<tcu::Vec2> samplePositions(numSamples); 387e5c31af7Sopenharmony_ci 388e5c31af7Sopenharmony_ci for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 389e5c31af7Sopenharmony_ci { 390e5c31af7Sopenharmony_ci const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z).z(); 391e5c31af7Sopenharmony_ci 392e5c31af7Sopenharmony_ci if (errorComponent > 0) 393e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]"); 394e5c31af7Sopenharmony_ci 395e5c31af7Sopenharmony_ci samplePositions[sampleNdx] = tcu::Vec2( (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).x() / 255.0f, 396e5c31af7Sopenharmony_ci (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).y() / 255.0f); 397e5c31af7Sopenharmony_ci } 398e5c31af7Sopenharmony_ci 399e5c31af7Sopenharmony_ci for (deUint32 sampleNdxA = 0u; sampleNdxA < numSamples; ++sampleNdxA) 400e5c31af7Sopenharmony_ci for (deUint32 sampleNdxB = sampleNdxA + 1u; sampleNdxB < numSamples; ++sampleNdxB) 401e5c31af7Sopenharmony_ci { 402e5c31af7Sopenharmony_ci if (samplePositions[sampleNdxA] == samplePositions[sampleNdxB]) 403e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Two samples have the same position"); 404e5c31af7Sopenharmony_ci } 405e5c31af7Sopenharmony_ci 406e5c31af7Sopenharmony_ci if (numSamples >= VK_SAMPLE_COUNT_4_BIT) 407e5c31af7Sopenharmony_ci { 408e5c31af7Sopenharmony_ci tcu::Vec2 averageSamplePos(0.0f, 0.0f); 409e5c31af7Sopenharmony_ci 410e5c31af7Sopenharmony_ci for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 411e5c31af7Sopenharmony_ci { 412e5c31af7Sopenharmony_ci averageSamplePos.x() += samplePositions[sampleNdx].x(); 413e5c31af7Sopenharmony_ci averageSamplePos.y() += samplePositions[sampleNdx].y(); 414e5c31af7Sopenharmony_ci } 415e5c31af7Sopenharmony_ci 416e5c31af7Sopenharmony_ci averageSamplePos.x() /= (float)numSamples; 417e5c31af7Sopenharmony_ci averageSamplePos.y() /= (float)numSamples; 418e5c31af7Sopenharmony_ci 419e5c31af7Sopenharmony_ci const tcu::Vec2 distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f)); 420e5c31af7Sopenharmony_ci 421e5c31af7Sopenharmony_ci if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold) 422e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel"); 423e5c31af7Sopenharmony_ci } 424e5c31af7Sopenharmony_ci } 425e5c31af7Sopenharmony_ci 426e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Passed"); 427e5c31af7Sopenharmony_ci} 428e5c31af7Sopenharmony_ci 429e5c31af7Sopenharmony_ciclass MSCaseSamplePosDistribution; 430e5c31af7Sopenharmony_ci 431e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSamplePosDistribution>::checkSupport (Context& context) const 432e5c31af7Sopenharmony_ci{ 433e5c31af7Sopenharmony_ci checkGraphicsPipelineLibrarySupport(context); 434e5c31af7Sopenharmony_ci context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 435e5c31af7Sopenharmony_ci} 436e5c31af7Sopenharmony_ci 437e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSamplePosDistribution>::init (void) 438e5c31af7Sopenharmony_ci{ 439e5c31af7Sopenharmony_ci m_testCtx.getLog() 440e5c31af7Sopenharmony_ci << tcu::TestLog::Message 441e5c31af7Sopenharmony_ci << "Verifying gl_SamplePosition value with multisample targets:\n" 442e5c31af7Sopenharmony_ci << " a) Expect legal sample position.\n" 443e5c31af7Sopenharmony_ci << " b) Sample position is unique within the set of all sample positions of a pixel.\n" 444e5c31af7Sopenharmony_ci << " c) Sample position distribution is uniform or almost uniform.\n" 445e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 446e5c31af7Sopenharmony_ci 447e5c31af7Sopenharmony_ci MultisampleCaseBase::init(); 448e5c31af7Sopenharmony_ci} 449e5c31af7Sopenharmony_ci 450e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSamplePosDistribution>::initPrograms (vk::SourceCollections& programCollection) const 451e5c31af7Sopenharmony_ci{ 452e5c31af7Sopenharmony_ci MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 453e5c31af7Sopenharmony_ci 454e5c31af7Sopenharmony_ci // Create vertex shader 455e5c31af7Sopenharmony_ci std::ostringstream vs; 456e5c31af7Sopenharmony_ci 457e5c31af7Sopenharmony_ci vs << "#version 440\n" 458e5c31af7Sopenharmony_ci << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 459e5c31af7Sopenharmony_ci << "\n" 460e5c31af7Sopenharmony_ci << "out gl_PerVertex {\n" 461e5c31af7Sopenharmony_ci << " vec4 gl_Position;\n" 462e5c31af7Sopenharmony_ci << "};\n" 463e5c31af7Sopenharmony_ci << "void main (void)\n" 464e5c31af7Sopenharmony_ci << "{\n" 465e5c31af7Sopenharmony_ci << " gl_Position = vs_in_position_ndc;\n" 466e5c31af7Sopenharmony_ci << "}\n"; 467e5c31af7Sopenharmony_ci 468e5c31af7Sopenharmony_ci programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 469e5c31af7Sopenharmony_ci 470e5c31af7Sopenharmony_ci // Create fragment shader 471e5c31af7Sopenharmony_ci std::ostringstream fs; 472e5c31af7Sopenharmony_ci 473e5c31af7Sopenharmony_ci fs << "#version 440\n" 474e5c31af7Sopenharmony_ci << "\n" 475e5c31af7Sopenharmony_ci << "layout(location = 0) out vec4 fs_out_color;\n" 476e5c31af7Sopenharmony_ci << "\n" 477e5c31af7Sopenharmony_ci << "void main (void)\n" 478e5c31af7Sopenharmony_ci << "{\n" 479e5c31af7Sopenharmony_ci << " if (gl_SamplePosition.x < 0.0 || gl_SamplePosition.x > 1.0 || gl_SamplePosition.y < 0.0 || gl_SamplePosition.y > 1.0)\n" 480e5c31af7Sopenharmony_ci " fs_out_color = vec4(0.0, 0.0, 1.0, 1.0);\n" 481e5c31af7Sopenharmony_ci " else\n" 482e5c31af7Sopenharmony_ci " fs_out_color = vec4(gl_SamplePosition.x, gl_SamplePosition.y, 0.0, 1.0);\n" 483e5c31af7Sopenharmony_ci "}\n"; 484e5c31af7Sopenharmony_ci 485e5c31af7Sopenharmony_ci programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 486e5c31af7Sopenharmony_ci} 487e5c31af7Sopenharmony_ci 488e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSamplePosDistribution>::createInstance (Context& context) const 489e5c31af7Sopenharmony_ci{ 490e5c31af7Sopenharmony_ci return new MSInstance<MSInstanceSamplePosDistribution>(context, m_imageMSParams); 491e5c31af7Sopenharmony_ci} 492e5c31af7Sopenharmony_ci 493e5c31af7Sopenharmony_ciclass MSInstanceSamplePosCorrectness; 494e5c31af7Sopenharmony_ci 495e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosCorrectness>::getVertexDataDescripton (void) const 496e5c31af7Sopenharmony_ci{ 497e5c31af7Sopenharmony_ci return getVertexDataDescriptonNdcScreen(); 498e5c31af7Sopenharmony_ci} 499e5c31af7Sopenharmony_ci 500e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceSamplePosCorrectness>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 501e5c31af7Sopenharmony_ci{ 502e5c31af7Sopenharmony_ci const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize); 503e5c31af7Sopenharmony_ci 504e5c31af7Sopenharmony_ci uploadVertexDataNdcScreen(vertexBufferAllocation, vertexDataDescripton, tcu::Vec2(static_cast<float>(layerSize.x()), static_cast<float>(layerSize.y()))); 505e5c31af7Sopenharmony_ci} 506e5c31af7Sopenharmony_ci 507e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceSamplePosCorrectness>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 508e5c31af7Sopenharmony_ci const vk::VkImageCreateInfo& imageRSInfo, 509e5c31af7Sopenharmony_ci const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 510e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& dataRS) const 511e5c31af7Sopenharmony_ci{ 512e5c31af7Sopenharmony_ci if (checkForErrorMS(imageMSInfo, dataPerSample, 0)) 513e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition"); 514e5c31af7Sopenharmony_ci 515e5c31af7Sopenharmony_ci if (checkForErrorRS(imageRSInfo, dataRS, 0)) 516e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition"); 517e5c31af7Sopenharmony_ci 518e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Passed"); 519e5c31af7Sopenharmony_ci} 520e5c31af7Sopenharmony_ci 521e5c31af7Sopenharmony_ciclass MSCaseSamplePosCorrectness; 522e5c31af7Sopenharmony_ci 523e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSamplePosCorrectness>::checkSupport (Context& context) const 524e5c31af7Sopenharmony_ci{ 525e5c31af7Sopenharmony_ci checkGraphicsPipelineLibrarySupport(context); 526e5c31af7Sopenharmony_ci context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 527e5c31af7Sopenharmony_ci} 528e5c31af7Sopenharmony_ci 529e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSamplePosCorrectness>::init (void) 530e5c31af7Sopenharmony_ci{ 531e5c31af7Sopenharmony_ci m_testCtx.getLog() 532e5c31af7Sopenharmony_ci << tcu::TestLog::Message 533e5c31af7Sopenharmony_ci << "Verifying gl_SamplePosition correctness:\n" 534e5c31af7Sopenharmony_ci << " 1) Varying values should be sampled at the sample position.\n" 535e5c31af7Sopenharmony_ci << " => fract(position_screen) == gl_SamplePosition\n" 536e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 537e5c31af7Sopenharmony_ci 538e5c31af7Sopenharmony_ci MultisampleCaseBase::init(); 539e5c31af7Sopenharmony_ci} 540e5c31af7Sopenharmony_ci 541e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSamplePosCorrectness>::initPrograms (vk::SourceCollections& programCollection) const 542e5c31af7Sopenharmony_ci{ 543e5c31af7Sopenharmony_ci MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 544e5c31af7Sopenharmony_ci 545e5c31af7Sopenharmony_ci // Create vertex shaders 546e5c31af7Sopenharmony_ci std::ostringstream vs; 547e5c31af7Sopenharmony_ci 548e5c31af7Sopenharmony_ci vs << "#version 440\n" 549e5c31af7Sopenharmony_ci << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 550e5c31af7Sopenharmony_ci << "layout(location = 1) in vec2 vs_in_position_screen;\n" 551e5c31af7Sopenharmony_ci << "\n" 552e5c31af7Sopenharmony_ci << "layout(location = 0) sample out vec2 vs_out_position_screen;\n" 553e5c31af7Sopenharmony_ci << "\n" 554e5c31af7Sopenharmony_ci << "out gl_PerVertex {\n" 555e5c31af7Sopenharmony_ci << " vec4 gl_Position;\n" 556e5c31af7Sopenharmony_ci << "};\n" 557e5c31af7Sopenharmony_ci << "void main (void)\n" 558e5c31af7Sopenharmony_ci << "{\n" 559e5c31af7Sopenharmony_ci << " gl_Position = vs_in_position_ndc;\n" 560e5c31af7Sopenharmony_ci << " vs_out_position_screen = vs_in_position_screen;\n" 561e5c31af7Sopenharmony_ci << "}\n"; 562e5c31af7Sopenharmony_ci 563e5c31af7Sopenharmony_ci programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 564e5c31af7Sopenharmony_ci 565e5c31af7Sopenharmony_ci // Create fragment shader 566e5c31af7Sopenharmony_ci std::ostringstream fs; 567e5c31af7Sopenharmony_ci 568e5c31af7Sopenharmony_ci fs << "#version 440\n" 569e5c31af7Sopenharmony_ci << "layout(location = 0) sample in vec2 fs_in_position_screen;\n" 570e5c31af7Sopenharmony_ci << "\n" 571e5c31af7Sopenharmony_ci << "layout(location = 0) out vec4 fs_out_color;\n" 572e5c31af7Sopenharmony_ci << "\n" 573e5c31af7Sopenharmony_ci << "void main (void)\n" 574e5c31af7Sopenharmony_ci << "{\n" 575e5c31af7Sopenharmony_ci << " const float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" 576e5c31af7Sopenharmony_ci << " const ivec2 nearby_pixel = ivec2(floor(fs_in_position_screen));\n" 577e5c31af7Sopenharmony_ci << " bool ok = false;\n" 578e5c31af7Sopenharmony_ci << "\n" 579e5c31af7Sopenharmony_ci << " // sample at edge + inaccuaries may cause us to round to any neighboring pixel\n" 580e5c31af7Sopenharmony_ci << " // check all neighbors for any match\n" 581e5c31af7Sopenharmony_ci << " for (int dy = -1; dy <= 1; ++dy)\n" 582e5c31af7Sopenharmony_ci << " for (int dx = -1; dx <= 1; ++dx)\n" 583e5c31af7Sopenharmony_ci << " {\n" 584e5c31af7Sopenharmony_ci << " ivec2 current_pixel = nearby_pixel + ivec2(dx, dy);\n" 585e5c31af7Sopenharmony_ci << " vec2 position_inside_pixel = vec2(current_pixel) + gl_SamplePosition;\n" 586e5c31af7Sopenharmony_ci << " vec2 position_diff = abs(position_inside_pixel - fs_in_position_screen);\n" 587e5c31af7Sopenharmony_ci << "\n" 588e5c31af7Sopenharmony_ci << " if (all(lessThan(position_diff, vec2(threshold))))\n" 589e5c31af7Sopenharmony_ci << " ok = true;\n" 590e5c31af7Sopenharmony_ci << " }\n" 591e5c31af7Sopenharmony_ci << "\n" 592e5c31af7Sopenharmony_ci << " if (ok)\n" 593e5c31af7Sopenharmony_ci << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 594e5c31af7Sopenharmony_ci << " else\n" 595e5c31af7Sopenharmony_ci << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 596e5c31af7Sopenharmony_ci << "}\n"; 597e5c31af7Sopenharmony_ci 598e5c31af7Sopenharmony_ci programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 599e5c31af7Sopenharmony_ci} 600e5c31af7Sopenharmony_ci 601e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSamplePosCorrectness>::createInstance (Context& context) const 602e5c31af7Sopenharmony_ci{ 603e5c31af7Sopenharmony_ci return new MSInstance<MSInstanceSamplePosCorrectness>(context, m_imageMSParams); 604e5c31af7Sopenharmony_ci} 605e5c31af7Sopenharmony_ci 606e5c31af7Sopenharmony_ciclass MSInstanceSampleMaskPattern : public MSInstanceBaseResolveAndPerSampleFetch 607e5c31af7Sopenharmony_ci{ 608e5c31af7Sopenharmony_cipublic: 609e5c31af7Sopenharmony_ci MSInstanceSampleMaskPattern (Context& context, 610e5c31af7Sopenharmony_ci const ImageMSParams& imageMSParams); 611e5c31af7Sopenharmony_ci 612e5c31af7Sopenharmony_ci VkPipelineMultisampleStateCreateInfo getMSStateCreateInfo (const ImageMSParams& imageMSParams) const; 613e5c31af7Sopenharmony_ci 614e5c31af7Sopenharmony_ci const VkDescriptorSetLayout* createMSPassDescSetLayout (const ImageMSParams& imageMSParams); 615e5c31af7Sopenharmony_ci 616e5c31af7Sopenharmony_ci const VkDescriptorSet* createMSPassDescSet (const ImageMSParams& imageMSParams, 617e5c31af7Sopenharmony_ci const VkDescriptorSetLayout* descSetLayout); 618e5c31af7Sopenharmony_ci 619e5c31af7Sopenharmony_ci VertexDataDesc getVertexDataDescripton (void) const; 620e5c31af7Sopenharmony_ci 621e5c31af7Sopenharmony_ci void uploadVertexData (const Allocation& vertexBufferAllocation, 622e5c31af7Sopenharmony_ci const VertexDataDesc& vertexDataDescripton) const; 623e5c31af7Sopenharmony_ci 624e5c31af7Sopenharmony_ci tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 625e5c31af7Sopenharmony_ci const vk::VkImageCreateInfo& imageRSInfo, 626e5c31af7Sopenharmony_ci const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 627e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& dataRS) const; 628e5c31af7Sopenharmony_ciprotected: 629e5c31af7Sopenharmony_ci 630e5c31af7Sopenharmony_ci VkSampleMask m_sampleMask; 631e5c31af7Sopenharmony_ci Move<VkDescriptorSetLayout> m_descriptorSetLayout; 632e5c31af7Sopenharmony_ci Move<VkDescriptorPool> m_descriptorPool; 633e5c31af7Sopenharmony_ci Move<VkDescriptorSet> m_descriptorSet; 634e5c31af7Sopenharmony_ci de::MovePtr<BufferWithMemory> m_buffer; 635e5c31af7Sopenharmony_ci}; 636e5c31af7Sopenharmony_ci 637e5c31af7Sopenharmony_ciMSInstanceSampleMaskPattern::MSInstanceSampleMaskPattern (Context& context, const ImageMSParams& imageMSParams) : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams) 638e5c31af7Sopenharmony_ci{ 639e5c31af7Sopenharmony_ci m_sampleMask = 0xAAAAAAAAu & ((1u << imageMSParams.numSamples) - 1u); 640e5c31af7Sopenharmony_ci} 641e5c31af7Sopenharmony_ci 642e5c31af7Sopenharmony_ciVkPipelineMultisampleStateCreateInfo MSInstanceSampleMaskPattern::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const 643e5c31af7Sopenharmony_ci{ 644e5c31af7Sopenharmony_ci const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = 645e5c31af7Sopenharmony_ci { 646e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 647e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 648e5c31af7Sopenharmony_ci (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags; 649e5c31af7Sopenharmony_ci imageMSParams.numSamples, // VkSampleCountFlagBits rasterizationSamples; 650e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 sampleShadingEnable; 651e5c31af7Sopenharmony_ci imageMSParams.shadingRate, // float minSampleShading; 652e5c31af7Sopenharmony_ci &m_sampleMask, // const VkSampleMask* pSampleMask; 653e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 alphaToCoverageEnable; 654e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 alphaToOneEnable; 655e5c31af7Sopenharmony_ci }; 656e5c31af7Sopenharmony_ci 657e5c31af7Sopenharmony_ci return multisampleStateInfo; 658e5c31af7Sopenharmony_ci} 659e5c31af7Sopenharmony_ci 660e5c31af7Sopenharmony_ciconst VkDescriptorSetLayout* MSInstanceSampleMaskPattern::createMSPassDescSetLayout (const ImageMSParams& imageMSParams) 661e5c31af7Sopenharmony_ci{ 662e5c31af7Sopenharmony_ci DE_UNREF(imageMSParams); 663e5c31af7Sopenharmony_ci 664e5c31af7Sopenharmony_ci const DeviceInterface& deviceInterface = m_context.getDeviceInterface(); 665e5c31af7Sopenharmony_ci const VkDevice device = m_context.getDevice(); 666e5c31af7Sopenharmony_ci 667e5c31af7Sopenharmony_ci // Create descriptor set layout 668e5c31af7Sopenharmony_ci m_descriptorSetLayout = DescriptorSetLayoutBuilder() 669e5c31af7Sopenharmony_ci .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT) 670e5c31af7Sopenharmony_ci .build(deviceInterface, device); 671e5c31af7Sopenharmony_ci 672e5c31af7Sopenharmony_ci return &m_descriptorSetLayout.get(); 673e5c31af7Sopenharmony_ci} 674e5c31af7Sopenharmony_ci 675e5c31af7Sopenharmony_ciconst VkDescriptorSet* MSInstanceSampleMaskPattern::createMSPassDescSet (const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout) 676e5c31af7Sopenharmony_ci{ 677e5c31af7Sopenharmony_ci DE_UNREF(imageMSParams); 678e5c31af7Sopenharmony_ci 679e5c31af7Sopenharmony_ci const DeviceInterface& deviceInterface = m_context.getDeviceInterface(); 680e5c31af7Sopenharmony_ci const VkDevice device = m_context.getDevice(); 681e5c31af7Sopenharmony_ci Allocator& allocator = m_context.getDefaultAllocator(); 682e5c31af7Sopenharmony_ci 683e5c31af7Sopenharmony_ci // Create descriptor pool 684e5c31af7Sopenharmony_ci m_descriptorPool = DescriptorPoolBuilder() 685e5c31af7Sopenharmony_ci .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u) 686e5c31af7Sopenharmony_ci .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 687e5c31af7Sopenharmony_ci 688e5c31af7Sopenharmony_ci // Create descriptor set 689e5c31af7Sopenharmony_ci m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *descSetLayout); 690e5c31af7Sopenharmony_ci 691e5c31af7Sopenharmony_ci const VkBufferCreateInfo bufferSampleMaskInfo = makeBufferCreateInfo(sizeof(VkSampleMask), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); 692e5c31af7Sopenharmony_ci 693e5c31af7Sopenharmony_ci m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, bufferSampleMaskInfo, MemoryRequirement::HostVisible)); 694e5c31af7Sopenharmony_ci 695e5c31af7Sopenharmony_ci deMemcpy(m_buffer->getAllocation().getHostPtr(), &m_sampleMask, sizeof(VkSampleMask)); 696e5c31af7Sopenharmony_ci 697e5c31af7Sopenharmony_ci flushAlloc(deviceInterface, device, m_buffer->getAllocation()); 698e5c31af7Sopenharmony_ci 699e5c31af7Sopenharmony_ci const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**m_buffer, 0u, sizeof(VkSampleMask)); 700e5c31af7Sopenharmony_ci 701e5c31af7Sopenharmony_ci DescriptorSetUpdateBuilder() 702e5c31af7Sopenharmony_ci .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descBufferInfo) 703e5c31af7Sopenharmony_ci .update(deviceInterface, device); 704e5c31af7Sopenharmony_ci 705e5c31af7Sopenharmony_ci return &m_descriptorSet.get(); 706e5c31af7Sopenharmony_ci} 707e5c31af7Sopenharmony_ci 708e5c31af7Sopenharmony_ciMultisampleInstanceBase::VertexDataDesc MSInstanceSampleMaskPattern::getVertexDataDescripton (void) const 709e5c31af7Sopenharmony_ci{ 710e5c31af7Sopenharmony_ci return getVertexDataDescriptonNdc(); 711e5c31af7Sopenharmony_ci} 712e5c31af7Sopenharmony_ci 713e5c31af7Sopenharmony_civoid MSInstanceSampleMaskPattern::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 714e5c31af7Sopenharmony_ci{ 715e5c31af7Sopenharmony_ci uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); 716e5c31af7Sopenharmony_ci} 717e5c31af7Sopenharmony_ci 718e5c31af7Sopenharmony_citcu::TestStatus MSInstanceSampleMaskPattern::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 719e5c31af7Sopenharmony_ci const vk::VkImageCreateInfo& imageRSInfo, 720e5c31af7Sopenharmony_ci const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 721e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& dataRS) const 722e5c31af7Sopenharmony_ci{ 723e5c31af7Sopenharmony_ci DE_UNREF(imageRSInfo); 724e5c31af7Sopenharmony_ci DE_UNREF(dataRS); 725e5c31af7Sopenharmony_ci 726e5c31af7Sopenharmony_ci if (checkForErrorMS(imageMSInfo, dataPerSample, 0)) 727e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("gl_SampleMaskIn bits have not been killed by pSampleMask state"); 728e5c31af7Sopenharmony_ci 729e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Passed"); 730e5c31af7Sopenharmony_ci} 731e5c31af7Sopenharmony_ci 732e5c31af7Sopenharmony_ciclass MSCaseSampleMaskPattern; 733e5c31af7Sopenharmony_ci 734e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskPattern>::init (void) 735e5c31af7Sopenharmony_ci{ 736e5c31af7Sopenharmony_ci m_testCtx.getLog() 737e5c31af7Sopenharmony_ci << tcu::TestLog::Message 738e5c31af7Sopenharmony_ci << "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" 739e5c31af7Sopenharmony_ci << "Expected result: gl_SampleMaskIn AND ~(pSampleMask) should be zero.\n" 740e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 741e5c31af7Sopenharmony_ci 742e5c31af7Sopenharmony_ci MultisampleCaseBase::init(); 743e5c31af7Sopenharmony_ci} 744e5c31af7Sopenharmony_ci 745e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskPattern>::initPrograms (vk::SourceCollections& programCollection) const 746e5c31af7Sopenharmony_ci{ 747e5c31af7Sopenharmony_ci MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 748e5c31af7Sopenharmony_ci 749e5c31af7Sopenharmony_ci // Create vertex shader 750e5c31af7Sopenharmony_ci std::ostringstream vs; 751e5c31af7Sopenharmony_ci 752e5c31af7Sopenharmony_ci vs << "#version 440\n" 753e5c31af7Sopenharmony_ci << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 754e5c31af7Sopenharmony_ci << "\n" 755e5c31af7Sopenharmony_ci << "out gl_PerVertex {\n" 756e5c31af7Sopenharmony_ci << " vec4 gl_Position;\n" 757e5c31af7Sopenharmony_ci << "};\n" 758e5c31af7Sopenharmony_ci << "void main (void)\n" 759e5c31af7Sopenharmony_ci << "{\n" 760e5c31af7Sopenharmony_ci << " gl_Position = vs_in_position_ndc;\n" 761e5c31af7Sopenharmony_ci << "}\n"; 762e5c31af7Sopenharmony_ci 763e5c31af7Sopenharmony_ci programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 764e5c31af7Sopenharmony_ci 765e5c31af7Sopenharmony_ci // Create fragment shader 766e5c31af7Sopenharmony_ci std::ostringstream fs; 767e5c31af7Sopenharmony_ci 768e5c31af7Sopenharmony_ci fs << "#version 440\n" 769e5c31af7Sopenharmony_ci << "\n" 770e5c31af7Sopenharmony_ci << "layout(location = 0) out vec4 fs_out_color;\n" 771e5c31af7Sopenharmony_ci << "\n" 772e5c31af7Sopenharmony_ci << "layout(set = 0, binding = 0, std140) uniform SampleMaskBlock\n" 773e5c31af7Sopenharmony_ci << "{\n" 774e5c31af7Sopenharmony_ci << " int sampleMaskPattern;\n" 775e5c31af7Sopenharmony_ci << "};" 776e5c31af7Sopenharmony_ci << "\n" 777e5c31af7Sopenharmony_ci << "void main (void)\n" 778e5c31af7Sopenharmony_ci << "{\n" 779e5c31af7Sopenharmony_ci << " if ((gl_SampleMaskIn[0] & ~sampleMaskPattern) != 0)\n" 780e5c31af7Sopenharmony_ci << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 781e5c31af7Sopenharmony_ci << " else\n" 782e5c31af7Sopenharmony_ci << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 783e5c31af7Sopenharmony_ci << "}\n"; 784e5c31af7Sopenharmony_ci 785e5c31af7Sopenharmony_ci programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 786e5c31af7Sopenharmony_ci} 787e5c31af7Sopenharmony_ci 788e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSampleMaskPattern>::createInstance (Context& context) const 789e5c31af7Sopenharmony_ci{ 790e5c31af7Sopenharmony_ci return new MSInstanceSampleMaskPattern(context, m_imageMSParams); 791e5c31af7Sopenharmony_ci} 792e5c31af7Sopenharmony_ci 793e5c31af7Sopenharmony_ciclass MSInstanceSampleMaskBitCount; 794e5c31af7Sopenharmony_ci 795e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskBitCount>::getVertexDataDescripton (void) const 796e5c31af7Sopenharmony_ci{ 797e5c31af7Sopenharmony_ci return getVertexDataDescriptonNdc(); 798e5c31af7Sopenharmony_ci} 799e5c31af7Sopenharmony_ci 800e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceSampleMaskBitCount>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 801e5c31af7Sopenharmony_ci{ 802e5c31af7Sopenharmony_ci uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); 803e5c31af7Sopenharmony_ci} 804e5c31af7Sopenharmony_ci 805e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceSampleMaskBitCount>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 806e5c31af7Sopenharmony_ci const vk::VkImageCreateInfo& imageRSInfo, 807e5c31af7Sopenharmony_ci const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 808e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& dataRS) const 809e5c31af7Sopenharmony_ci{ 810e5c31af7Sopenharmony_ci DE_UNREF(imageRSInfo); 811e5c31af7Sopenharmony_ci DE_UNREF(dataRS); 812e5c31af7Sopenharmony_ci 813e5c31af7Sopenharmony_ci if (checkForErrorMS(imageMSInfo, dataPerSample, 0)) 814e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("gl_SampleMaskIn has an illegal number of bits for some shader invocations"); 815e5c31af7Sopenharmony_ci 816e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Passed"); 817e5c31af7Sopenharmony_ci} 818e5c31af7Sopenharmony_ci 819e5c31af7Sopenharmony_ciclass MSCaseSampleMaskBitCount; 820e5c31af7Sopenharmony_ci 821e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskBitCount>::checkSupport (Context& context) const 822e5c31af7Sopenharmony_ci{ 823e5c31af7Sopenharmony_ci checkGraphicsPipelineLibrarySupport(context); 824e5c31af7Sopenharmony_ci context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 825e5c31af7Sopenharmony_ci} 826e5c31af7Sopenharmony_ci 827e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskBitCount>::init (void) 828e5c31af7Sopenharmony_ci{ 829e5c31af7Sopenharmony_ci m_testCtx.getLog() 830e5c31af7Sopenharmony_ci << tcu::TestLog::Message 831e5c31af7Sopenharmony_ci << "Verifying gl_SampleMaskIn.\n" 832e5c31af7Sopenharmony_ci << " Fragment shader will be invoked numSamples times.\n" 833e5c31af7Sopenharmony_ci << " => gl_SampleMaskIn should have a number of bits that depends on the shading rate.\n" 834e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 835e5c31af7Sopenharmony_ci 836e5c31af7Sopenharmony_ci MultisampleCaseBase::init(); 837e5c31af7Sopenharmony_ci} 838e5c31af7Sopenharmony_ci 839e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskBitCount>::initPrograms (vk::SourceCollections& programCollection) const 840e5c31af7Sopenharmony_ci{ 841e5c31af7Sopenharmony_ci MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 842e5c31af7Sopenharmony_ci 843e5c31af7Sopenharmony_ci // Create vertex shader 844e5c31af7Sopenharmony_ci std::ostringstream vs; 845e5c31af7Sopenharmony_ci 846e5c31af7Sopenharmony_ci vs << "#version 440\n" 847e5c31af7Sopenharmony_ci << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 848e5c31af7Sopenharmony_ci << "\n" 849e5c31af7Sopenharmony_ci << "out gl_PerVertex {\n" 850e5c31af7Sopenharmony_ci << " vec4 gl_Position;\n" 851e5c31af7Sopenharmony_ci << "};\n" 852e5c31af7Sopenharmony_ci << "void main (void)\n" 853e5c31af7Sopenharmony_ci << "{\n" 854e5c31af7Sopenharmony_ci << " gl_Position = vs_in_position_ndc;\n" 855e5c31af7Sopenharmony_ci << "}\n"; 856e5c31af7Sopenharmony_ci 857e5c31af7Sopenharmony_ci programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 858e5c31af7Sopenharmony_ci 859e5c31af7Sopenharmony_ci // Create fragment shader 860e5c31af7Sopenharmony_ci std::ostringstream fs; 861e5c31af7Sopenharmony_ci 862e5c31af7Sopenharmony_ci // The worst case scenario would be all invocations except one covering a single sample, and then one invocation covering the rest. 863e5c31af7Sopenharmony_ci const int minInvocations = static_cast<int>(std::ceil(static_cast<float>(m_imageMSParams.numSamples) * m_imageMSParams.shadingRate)); 864e5c31af7Sopenharmony_ci const int minCount = 1; 865e5c31af7Sopenharmony_ci const int maxCount = m_imageMSParams.numSamples - (minInvocations - 1); 866e5c31af7Sopenharmony_ci 867e5c31af7Sopenharmony_ci fs << "#version 440\n" 868e5c31af7Sopenharmony_ci << "\n" 869e5c31af7Sopenharmony_ci << "layout(location = 0) out vec4 fs_out_color;\n" 870e5c31af7Sopenharmony_ci << "\n" 871e5c31af7Sopenharmony_ci << "void main (void)\n" 872e5c31af7Sopenharmony_ci << "{\n" 873e5c31af7Sopenharmony_ci << " const int maskBitCount = bitCount(gl_SampleMaskIn[0]);\n" 874e5c31af7Sopenharmony_ci << "\n" 875e5c31af7Sopenharmony_ci << " if (maskBitCount < " << minCount << " || maskBitCount > " << maxCount << ")\n" 876e5c31af7Sopenharmony_ci << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 877e5c31af7Sopenharmony_ci << " else\n" 878e5c31af7Sopenharmony_ci << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 879e5c31af7Sopenharmony_ci << "}\n"; 880e5c31af7Sopenharmony_ci 881e5c31af7Sopenharmony_ci programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 882e5c31af7Sopenharmony_ci} 883e5c31af7Sopenharmony_ci 884e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSampleMaskBitCount>::createInstance (Context& context) const 885e5c31af7Sopenharmony_ci{ 886e5c31af7Sopenharmony_ci return new MSInstance<MSInstanceSampleMaskBitCount>(context, m_imageMSParams); 887e5c31af7Sopenharmony_ci} 888e5c31af7Sopenharmony_ci 889e5c31af7Sopenharmony_ciclass MSInstanceSampleMaskCorrectBit; 890e5c31af7Sopenharmony_ci 891e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskCorrectBit>::getVertexDataDescripton (void) const 892e5c31af7Sopenharmony_ci{ 893e5c31af7Sopenharmony_ci return getVertexDataDescriptonNdc(); 894e5c31af7Sopenharmony_ci} 895e5c31af7Sopenharmony_ci 896e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceSampleMaskCorrectBit>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 897e5c31af7Sopenharmony_ci{ 898e5c31af7Sopenharmony_ci uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); 899e5c31af7Sopenharmony_ci} 900e5c31af7Sopenharmony_ci 901e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceSampleMaskCorrectBit>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 902e5c31af7Sopenharmony_ci const vk::VkImageCreateInfo& imageRSInfo, 903e5c31af7Sopenharmony_ci const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 904e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& dataRS) const 905e5c31af7Sopenharmony_ci{ 906e5c31af7Sopenharmony_ci DE_UNREF(imageRSInfo); 907e5c31af7Sopenharmony_ci DE_UNREF(dataRS); 908e5c31af7Sopenharmony_ci 909e5c31af7Sopenharmony_ci if (checkForErrorMS(imageMSInfo, dataPerSample, 0)) 910e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("The bit corresponsing to current gl_SampleID is not set in gl_SampleMaskIn"); 911e5c31af7Sopenharmony_ci 912e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Passed"); 913e5c31af7Sopenharmony_ci} 914e5c31af7Sopenharmony_ci 915e5c31af7Sopenharmony_ciclass MSCaseSampleMaskCorrectBit; 916e5c31af7Sopenharmony_ci 917e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskCorrectBit>::checkSupport (Context& context) const 918e5c31af7Sopenharmony_ci{ 919e5c31af7Sopenharmony_ci checkGraphicsPipelineLibrarySupport(context); 920e5c31af7Sopenharmony_ci context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 921e5c31af7Sopenharmony_ci} 922e5c31af7Sopenharmony_ci 923e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskCorrectBit>::init (void) 924e5c31af7Sopenharmony_ci{ 925e5c31af7Sopenharmony_ci m_testCtx.getLog() 926e5c31af7Sopenharmony_ci << tcu::TestLog::Message 927e5c31af7Sopenharmony_ci << "Verifying gl_SampleMaskIn.\n" 928e5c31af7Sopenharmony_ci << " Fragment shader will be invoked numSamples times.\n" 929e5c31af7Sopenharmony_ci << " => In each invocation gl_SampleMaskIn should have the bit set that corresponds to gl_SampleID.\n" 930e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 931e5c31af7Sopenharmony_ci 932e5c31af7Sopenharmony_ci MultisampleCaseBase::init(); 933e5c31af7Sopenharmony_ci} 934e5c31af7Sopenharmony_ci 935e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskCorrectBit>::initPrograms (vk::SourceCollections& programCollection) const 936e5c31af7Sopenharmony_ci{ 937e5c31af7Sopenharmony_ci MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 938e5c31af7Sopenharmony_ci 939e5c31af7Sopenharmony_ci // Create vertex shader 940e5c31af7Sopenharmony_ci std::ostringstream vs; 941e5c31af7Sopenharmony_ci 942e5c31af7Sopenharmony_ci vs << "#version 440\n" 943e5c31af7Sopenharmony_ci << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 944e5c31af7Sopenharmony_ci << "\n" 945e5c31af7Sopenharmony_ci << "out gl_PerVertex {\n" 946e5c31af7Sopenharmony_ci << " vec4 gl_Position;\n" 947e5c31af7Sopenharmony_ci << "};\n" 948e5c31af7Sopenharmony_ci << "void main (void)\n" 949e5c31af7Sopenharmony_ci << "{\n" 950e5c31af7Sopenharmony_ci << " gl_Position = vs_in_position_ndc;\n" 951e5c31af7Sopenharmony_ci << "}\n"; 952e5c31af7Sopenharmony_ci 953e5c31af7Sopenharmony_ci programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 954e5c31af7Sopenharmony_ci 955e5c31af7Sopenharmony_ci // Create fragment shader 956e5c31af7Sopenharmony_ci std::ostringstream fs; 957e5c31af7Sopenharmony_ci 958e5c31af7Sopenharmony_ci fs << "#version 440\n" 959e5c31af7Sopenharmony_ci << "\n" 960e5c31af7Sopenharmony_ci << "layout(location = 0) out vec4 fs_out_color;\n" 961e5c31af7Sopenharmony_ci << "\n" 962e5c31af7Sopenharmony_ci << "void main (void)\n" 963e5c31af7Sopenharmony_ci << "{\n" 964e5c31af7Sopenharmony_ci << " if (((gl_SampleMaskIn[0] >> gl_SampleID) & 0x01) == 0x01)\n" 965e5c31af7Sopenharmony_ci << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 966e5c31af7Sopenharmony_ci << " else\n" 967e5c31af7Sopenharmony_ci << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 968e5c31af7Sopenharmony_ci << "}\n"; 969e5c31af7Sopenharmony_ci 970e5c31af7Sopenharmony_ci programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 971e5c31af7Sopenharmony_ci} 972e5c31af7Sopenharmony_ci 973e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSampleMaskCorrectBit>::createInstance (Context& context) const 974e5c31af7Sopenharmony_ci{ 975e5c31af7Sopenharmony_ci return new MSInstance<MSInstanceSampleMaskCorrectBit>(context, m_imageMSParams); 976e5c31af7Sopenharmony_ci} 977e5c31af7Sopenharmony_ci 978e5c31af7Sopenharmony_ciclass MSInstanceSampleMaskWrite; 979e5c31af7Sopenharmony_ci 980e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskWrite>::getVertexDataDescripton (void) const 981e5c31af7Sopenharmony_ci{ 982e5c31af7Sopenharmony_ci return getVertexDataDescriptonNdc(); 983e5c31af7Sopenharmony_ci} 984e5c31af7Sopenharmony_ci 985e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceSampleMaskWrite>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 986e5c31af7Sopenharmony_ci{ 987e5c31af7Sopenharmony_ci uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); 988e5c31af7Sopenharmony_ci} 989e5c31af7Sopenharmony_ci 990e5c31af7Sopenharmony_ci//! Creates VkPipelineMultisampleStateCreateInfo with sample shading disabled. 991e5c31af7Sopenharmony_citemplate<> VkPipelineMultisampleStateCreateInfo MSInstance<MSInstanceSampleMaskWrite>::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const 992e5c31af7Sopenharmony_ci{ 993e5c31af7Sopenharmony_ci const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = 994e5c31af7Sopenharmony_ci { 995e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 996e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 997e5c31af7Sopenharmony_ci (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags; 998e5c31af7Sopenharmony_ci imageMSParams.numSamples, // VkSampleCountFlagBits rasterizationSamples; 999e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 sampleShadingEnable; 1000e5c31af7Sopenharmony_ci imageMSParams.shadingRate, // float minSampleShading; 1001e5c31af7Sopenharmony_ci DE_NULL, // const VkSampleMask* pSampleMask; 1002e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 alphaToCoverageEnable; 1003e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 alphaToOneEnable; 1004e5c31af7Sopenharmony_ci }; 1005e5c31af7Sopenharmony_ci 1006e5c31af7Sopenharmony_ci return multisampleStateInfo; 1007e5c31af7Sopenharmony_ci} 1008e5c31af7Sopenharmony_ci 1009e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceSampleMaskWrite>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 1010e5c31af7Sopenharmony_ci const vk::VkImageCreateInfo& imageRSInfo, 1011e5c31af7Sopenharmony_ci const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 1012e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& dataRS) const 1013e5c31af7Sopenharmony_ci{ 1014e5c31af7Sopenharmony_ci const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples); 1015e5c31af7Sopenharmony_ci 1016e5c31af7Sopenharmony_ci for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z) 1017e5c31af7Sopenharmony_ci for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y) 1018e5c31af7Sopenharmony_ci for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x) 1019e5c31af7Sopenharmony_ci { 1020e5c31af7Sopenharmony_ci for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 1021e5c31af7Sopenharmony_ci { 1022e5c31af7Sopenharmony_ci const deUint32 firstComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[0]; 1023e5c31af7Sopenharmony_ci 1024e5c31af7Sopenharmony_ci if (firstComponent != 0u && firstComponent != 255u) 1025e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Expected color to be zero or saturated on the first channel"); 1026e5c31af7Sopenharmony_ci } 1027e5c31af7Sopenharmony_ci } 1028e5c31af7Sopenharmony_ci 1029e5c31af7Sopenharmony_ci for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) 1030e5c31af7Sopenharmony_ci for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) 1031e5c31af7Sopenharmony_ci for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) 1032e5c31af7Sopenharmony_ci { 1033e5c31af7Sopenharmony_ci const float firstComponent = dataRS.getPixel(x, y, z)[0]; 1034e5c31af7Sopenharmony_ci 1035e5c31af7Sopenharmony_ci if (deFloatAbs(firstComponent - 0.5f) > 0.02f) 1036e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Expected resolve color to be half intensity on the first channel"); 1037e5c31af7Sopenharmony_ci } 1038e5c31af7Sopenharmony_ci 1039e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Passed"); 1040e5c31af7Sopenharmony_ci} 1041e5c31af7Sopenharmony_ci 1042e5c31af7Sopenharmony_ciclass MSCaseSampleMaskWrite; 1043e5c31af7Sopenharmony_ci 1044e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskWrite>::init (void) 1045e5c31af7Sopenharmony_ci{ 1046e5c31af7Sopenharmony_ci m_testCtx.getLog() 1047e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1048e5c31af7Sopenharmony_ci << "Discarding half of the samples using gl_SampleMask." 1049e5c31af7Sopenharmony_ci << "Expecting half intensity on multisample targets (numSamples > 1)\n" 1050e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1051e5c31af7Sopenharmony_ci 1052e5c31af7Sopenharmony_ci MultisampleCaseBase::init(); 1053e5c31af7Sopenharmony_ci} 1054e5c31af7Sopenharmony_ci 1055e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskWrite>::initPrograms (vk::SourceCollections& programCollection) const 1056e5c31af7Sopenharmony_ci{ 1057e5c31af7Sopenharmony_ci MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 1058e5c31af7Sopenharmony_ci 1059e5c31af7Sopenharmony_ci // Create vertex shader 1060e5c31af7Sopenharmony_ci std::ostringstream vs; 1061e5c31af7Sopenharmony_ci 1062e5c31af7Sopenharmony_ci vs << "#version 440\n" 1063e5c31af7Sopenharmony_ci << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 1064e5c31af7Sopenharmony_ci << "\n" 1065e5c31af7Sopenharmony_ci << "out gl_PerVertex {\n" 1066e5c31af7Sopenharmony_ci << " vec4 gl_Position;\n" 1067e5c31af7Sopenharmony_ci << "};\n" 1068e5c31af7Sopenharmony_ci << "void main (void)\n" 1069e5c31af7Sopenharmony_ci << "{\n" 1070e5c31af7Sopenharmony_ci << " gl_Position = vs_in_position_ndc;\n" 1071e5c31af7Sopenharmony_ci << "}\n"; 1072e5c31af7Sopenharmony_ci 1073e5c31af7Sopenharmony_ci programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 1074e5c31af7Sopenharmony_ci 1075e5c31af7Sopenharmony_ci // Create fragment shader 1076e5c31af7Sopenharmony_ci std::ostringstream fs; 1077e5c31af7Sopenharmony_ci 1078e5c31af7Sopenharmony_ci fs << "#version 440\n" 1079e5c31af7Sopenharmony_ci << "\n" 1080e5c31af7Sopenharmony_ci << "layout(location = 0) out vec4 fs_out_color;\n" 1081e5c31af7Sopenharmony_ci << "\n" 1082e5c31af7Sopenharmony_ci << "void main (void)\n" 1083e5c31af7Sopenharmony_ci << "{\n" 1084e5c31af7Sopenharmony_ci << " gl_SampleMask[0] = 0xAAAAAAAA;\n" 1085e5c31af7Sopenharmony_ci << "\n" 1086e5c31af7Sopenharmony_ci << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 1087e5c31af7Sopenharmony_ci << "}\n"; 1088e5c31af7Sopenharmony_ci 1089e5c31af7Sopenharmony_ci programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 1090e5c31af7Sopenharmony_ci} 1091e5c31af7Sopenharmony_ci 1092e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSampleMaskWrite>::createInstance (Context& context) const 1093e5c31af7Sopenharmony_ci{ 1094e5c31af7Sopenharmony_ci return new MSInstance<MSInstanceSampleMaskWrite>(context, m_imageMSParams); 1095e5c31af7Sopenharmony_ci} 1096e5c31af7Sopenharmony_ci 1097e5c31af7Sopenharmony_ciconst set<deUint32> kValidSquareSampleCounts = 1098e5c31af7Sopenharmony_ci{ 1099e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_1_BIT, 1100e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_2_BIT, 1101e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_4_BIT, 1102e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_8_BIT, 1103e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_16_BIT, 1104e5c31af7Sopenharmony_ci}; 1105e5c31af7Sopenharmony_ci 1106e5c31af7Sopenharmony_civoid assertSquareSampleCount (deUint32 sampleCount) 1107e5c31af7Sopenharmony_ci{ 1108e5c31af7Sopenharmony_ci DE_ASSERT(kValidSquareSampleCounts.find(sampleCount) != kValidSquareSampleCounts.end()); 1109e5c31af7Sopenharmony_ci DE_UNREF(sampleCount); // for release builds. 1110e5c31af7Sopenharmony_ci} 1111e5c31af7Sopenharmony_ci 1112e5c31af7Sopenharmony_ci// When dealing with N samples, each coordinate (x, y) will be used to decide which samples will be written to, using N/2 bits for 1113e5c31af7Sopenharmony_ci// each of the X and Y values. Take into account this returns 0 for 1 sample. 1114e5c31af7Sopenharmony_cideUint32 bitsPerCoord (deUint32 numSamples) 1115e5c31af7Sopenharmony_ci{ 1116e5c31af7Sopenharmony_ci assertSquareSampleCount(numSamples); 1117e5c31af7Sopenharmony_ci return (numSamples / 2u); 1118e5c31af7Sopenharmony_ci} 1119e5c31af7Sopenharmony_ci 1120e5c31af7Sopenharmony_ci// These tests will try to verify all write or mask bit combinations for the given sample count, and will verify one combination per 1121e5c31af7Sopenharmony_ci// image pixel. This means the following image sizes need to be used: 1122e5c31af7Sopenharmony_ci// - 2 samples: 2x2 1123e5c31af7Sopenharmony_ci// - 4 samples: 4x4 1124e5c31af7Sopenharmony_ci// - 8 samples: 16x16 1125e5c31af7Sopenharmony_ci// - 16 samples: 256x256 1126e5c31af7Sopenharmony_ci// In other words, images will be square with 2^(samples-1) pixels on each side. 1127e5c31af7Sopenharmony_civk::VkExtent2D imageSize (deUint32 sampleCount) 1128e5c31af7Sopenharmony_ci{ 1129e5c31af7Sopenharmony_ci assertSquareSampleCount(sampleCount); 1130e5c31af7Sopenharmony_ci 1131e5c31af7Sopenharmony_ci // Special case: 2x1 image (not actually square). 1132e5c31af7Sopenharmony_ci if (sampleCount == vk::VK_SAMPLE_COUNT_1_BIT) 1133e5c31af7Sopenharmony_ci return vk::VkExtent2D{2u, 1u}; 1134e5c31af7Sopenharmony_ci 1135e5c31af7Sopenharmony_ci // Other cases: square image as described above. 1136e5c31af7Sopenharmony_ci const auto dim = (1u<<(sampleCount>>1u)); 1137e5c31af7Sopenharmony_ci return vk::VkExtent2D{dim, dim}; 1138e5c31af7Sopenharmony_ci} 1139e5c31af7Sopenharmony_ci 1140e5c31af7Sopenharmony_civk::VkExtent3D getExtent3D (deUint32 sampleCount) 1141e5c31af7Sopenharmony_ci{ 1142e5c31af7Sopenharmony_ci const auto size = imageSize(sampleCount); 1143e5c31af7Sopenharmony_ci return vk::VkExtent3D{size.width, size.height, 1u}; 1144e5c31af7Sopenharmony_ci} 1145e5c31af7Sopenharmony_ci 1146e5c31af7Sopenharmony_cistd::string getShaderDecl (const tcu::Vec4& color) 1147e5c31af7Sopenharmony_ci{ 1148e5c31af7Sopenharmony_ci std::ostringstream declaration; 1149e5c31af7Sopenharmony_ci declaration << "vec4(" << color.x() << ", " << color.y() << ", " << color.z() << ", " << color.w() << ")"; 1150e5c31af7Sopenharmony_ci return declaration.str(); 1151e5c31af7Sopenharmony_ci} 1152e5c31af7Sopenharmony_ci 1153e5c31af7Sopenharmony_cistruct WriteSampleParams 1154e5c31af7Sopenharmony_ci{ 1155e5c31af7Sopenharmony_ci vk::PipelineConstructionType pipelineConstructionType; 1156e5c31af7Sopenharmony_ci vk::VkSampleCountFlagBits sampleCount; 1157e5c31af7Sopenharmony_ci}; 1158e5c31af7Sopenharmony_ci 1159e5c31af7Sopenharmony_ciclass WriteSampleTest : public vkt::TestCase 1160e5c31af7Sopenharmony_ci{ 1161e5c31af7Sopenharmony_cipublic: 1162e5c31af7Sopenharmony_ci WriteSampleTest (tcu::TestContext& testCtx, const std::string& name, const WriteSampleParams& params) 1163e5c31af7Sopenharmony_ci : vkt::TestCase(testCtx, name), m_params(params) 1164e5c31af7Sopenharmony_ci {} 1165e5c31af7Sopenharmony_ci virtual ~WriteSampleTest (void) {} 1166e5c31af7Sopenharmony_ci 1167e5c31af7Sopenharmony_ci virtual void initPrograms (vk::SourceCollections& programCollection) const; 1168e5c31af7Sopenharmony_ci virtual vkt::TestInstance* createInstance (Context& context) const; 1169e5c31af7Sopenharmony_ci virtual void checkSupport (Context& context) const; 1170e5c31af7Sopenharmony_ci 1171e5c31af7Sopenharmony_ci static const tcu::Vec4 kClearColor; 1172e5c31af7Sopenharmony_ci static const tcu::Vec4 kBadColor; 1173e5c31af7Sopenharmony_ci static const tcu::Vec4 kGoodColor; 1174e5c31af7Sopenharmony_ci static const tcu::Vec4 kWriteColor; 1175e5c31af7Sopenharmony_ci 1176e5c31af7Sopenharmony_ci static constexpr vk::VkFormat kImageFormat = vk::VK_FORMAT_R8G8B8A8_UNORM; 1177e5c31af7Sopenharmony_ci 1178e5c31af7Sopenharmony_ci // Keep these two in sync. 1179e5c31af7Sopenharmony_ci static constexpr vk::VkImageUsageFlags kUsageFlags = (vk::VK_IMAGE_USAGE_STORAGE_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT); 1180e5c31af7Sopenharmony_ci static constexpr vk::VkFormatFeatureFlags kFeatureFlags = (vk::VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT); 1181e5c31af7Sopenharmony_ci 1182e5c31af7Sopenharmony_ciprivate: 1183e5c31af7Sopenharmony_ci WriteSampleParams m_params; 1184e5c31af7Sopenharmony_ci}; 1185e5c31af7Sopenharmony_ci 1186e5c31af7Sopenharmony_ciconst tcu::Vec4 WriteSampleTest::kClearColor {0.0f, 0.0f, 0.0f, 1.0f}; 1187e5c31af7Sopenharmony_ciconst tcu::Vec4 WriteSampleTest::kBadColor {1.0f, 0.0f, 0.0f, 1.0f}; 1188e5c31af7Sopenharmony_ciconst tcu::Vec4 WriteSampleTest::kGoodColor {0.0f, 1.0f, 0.0f, 1.0f}; 1189e5c31af7Sopenharmony_ciconst tcu::Vec4 WriteSampleTest::kWriteColor {0.0f, 0.0f, 1.0f, 1.0f}; 1190e5c31af7Sopenharmony_ci 1191e5c31af7Sopenharmony_ciclass WriteSampleTestInstance : public vkt::TestInstance 1192e5c31af7Sopenharmony_ci{ 1193e5c31af7Sopenharmony_cipublic: 1194e5c31af7Sopenharmony_ci WriteSampleTestInstance (vkt::Context& context, const WriteSampleParams& params) 1195e5c31af7Sopenharmony_ci : vkt::TestInstance(context), m_params(params) 1196e5c31af7Sopenharmony_ci {} 1197e5c31af7Sopenharmony_ci 1198e5c31af7Sopenharmony_ci virtual ~WriteSampleTestInstance (void) {} 1199e5c31af7Sopenharmony_ci 1200e5c31af7Sopenharmony_ci virtual tcu::TestStatus iterate (void); 1201e5c31af7Sopenharmony_ci 1202e5c31af7Sopenharmony_ciprivate: 1203e5c31af7Sopenharmony_ci WriteSampleParams m_params; 1204e5c31af7Sopenharmony_ci}; 1205e5c31af7Sopenharmony_ci 1206e5c31af7Sopenharmony_civoid WriteSampleTest::checkSupport (Context& context) const 1207e5c31af7Sopenharmony_ci{ 1208e5c31af7Sopenharmony_ci const auto& vki = context.getInstanceInterface(); 1209e5c31af7Sopenharmony_ci const auto physicalDevice = context.getPhysicalDevice(); 1210e5c31af7Sopenharmony_ci 1211e5c31af7Sopenharmony_ci // Check multisample storage images support. 1212e5c31af7Sopenharmony_ci const auto features = vk::getPhysicalDeviceFeatures(vki, physicalDevice); 1213e5c31af7Sopenharmony_ci if (!features.shaderStorageImageMultisample) 1214e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Using multisample images as storage is not supported"); 1215e5c31af7Sopenharmony_ci 1216e5c31af7Sopenharmony_ci // Check the specific image format. 1217e5c31af7Sopenharmony_ci const auto properties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat); 1218e5c31af7Sopenharmony_ci if (!(properties.optimalTilingFeatures & kFeatureFlags)) 1219e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Format does not support the required features"); 1220e5c31af7Sopenharmony_ci 1221e5c31af7Sopenharmony_ci // Check the supported sample count. 1222e5c31af7Sopenharmony_ci const auto imgProps = vk::getPhysicalDeviceImageFormatProperties(vki, physicalDevice, kImageFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, kUsageFlags, 0u); 1223e5c31af7Sopenharmony_ci if (!(imgProps.sampleCounts & m_params.sampleCount)) 1224e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Format does not support the required sample count"); 1225e5c31af7Sopenharmony_ci 1226e5c31af7Sopenharmony_ci checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType); 1227e5c31af7Sopenharmony_ci} 1228e5c31af7Sopenharmony_ci 1229e5c31af7Sopenharmony_civoid WriteSampleTest::initPrograms (vk::SourceCollections& programCollection) const 1230e5c31af7Sopenharmony_ci{ 1231e5c31af7Sopenharmony_ci std::ostringstream writeColorDecl, goodColorDecl, badColorDecl, clearColorDecl, allColorDecl; 1232e5c31af7Sopenharmony_ci 1233e5c31af7Sopenharmony_ci writeColorDecl << " vec4 wcolor = " << getShaderDecl(kWriteColor) << ";\n"; 1234e5c31af7Sopenharmony_ci goodColorDecl << " vec4 bcolor = " << getShaderDecl(kBadColor) << ";\n"; 1235e5c31af7Sopenharmony_ci badColorDecl << " vec4 gcolor = " << getShaderDecl(kGoodColor) << ";\n"; 1236e5c31af7Sopenharmony_ci clearColorDecl << " vec4 ccolor = " << getShaderDecl(kClearColor) << ";\n"; 1237e5c31af7Sopenharmony_ci allColorDecl << writeColorDecl.str() << goodColorDecl.str() << badColorDecl.str() << clearColorDecl.str(); 1238e5c31af7Sopenharmony_ci 1239e5c31af7Sopenharmony_ci std::ostringstream shaderWrite; 1240e5c31af7Sopenharmony_ci 1241e5c31af7Sopenharmony_ci const auto bpc = de::toString(bitsPerCoord(m_params.sampleCount)); 1242e5c31af7Sopenharmony_ci const auto count = de::toString(m_params.sampleCount); 1243e5c31af7Sopenharmony_ci 1244e5c31af7Sopenharmony_ci shaderWrite 1245e5c31af7Sopenharmony_ci << "#version 450\n" 1246e5c31af7Sopenharmony_ci << "\n" 1247e5c31af7Sopenharmony_ci << "layout (rgba8, set=0, binding=0) uniform image2DMS writeImg;\n" 1248e5c31af7Sopenharmony_ci << "layout (rgba8, set=0, binding=1) uniform image2D verificationImg;\n" 1249e5c31af7Sopenharmony_ci << "\n" 1250e5c31af7Sopenharmony_ci << "void main()\n" 1251e5c31af7Sopenharmony_ci << "{\n" 1252e5c31af7Sopenharmony_ci << writeColorDecl.str() 1253e5c31af7Sopenharmony_ci << " uvec2 ucoords = uvec2(gl_GlobalInvocationID.xy);\n" 1254e5c31af7Sopenharmony_ci << " ivec2 icoords = ivec2(ucoords);\n" 1255e5c31af7Sopenharmony_ci << " uint writeMask = ((ucoords.x << " << bpc << ") | ucoords.y);\n" 1256e5c31af7Sopenharmony_ci << " for (uint i = 0; i < " << count << "; ++i)\n" 1257e5c31af7Sopenharmony_ci << " {\n" 1258e5c31af7Sopenharmony_ci << " if ((writeMask & (1 << i)) != 0)\n" 1259e5c31af7Sopenharmony_ci << " imageStore(writeImg, icoords, int(i), wcolor);\n" 1260e5c31af7Sopenharmony_ci << " }\n" 1261e5c31af7Sopenharmony_ci << "}\n" 1262e5c31af7Sopenharmony_ci ; 1263e5c31af7Sopenharmony_ci 1264e5c31af7Sopenharmony_ci std::ostringstream shaderVerify; 1265e5c31af7Sopenharmony_ci 1266e5c31af7Sopenharmony_ci shaderVerify 1267e5c31af7Sopenharmony_ci << "#version 450\n" 1268e5c31af7Sopenharmony_ci << "\n" 1269e5c31af7Sopenharmony_ci << "layout (rgba8, set=0, binding=0) uniform image2DMS writeImg;\n" 1270e5c31af7Sopenharmony_ci << "layout (rgba8, set=0, binding=1) uniform image2D verificationImg;\n" 1271e5c31af7Sopenharmony_ci << "\n" 1272e5c31af7Sopenharmony_ci << "void main()\n" 1273e5c31af7Sopenharmony_ci << "{\n" 1274e5c31af7Sopenharmony_ci << allColorDecl.str() 1275e5c31af7Sopenharmony_ci << " uvec2 ucoords = uvec2(gl_GlobalInvocationID.xy);\n" 1276e5c31af7Sopenharmony_ci << " ivec2 icoords = ivec2(ucoords);\n" 1277e5c31af7Sopenharmony_ci << " uint writeMask = ((ucoords.x << " << bpc << ") | ucoords.y);\n" 1278e5c31af7Sopenharmony_ci << " bool ok = true;\n" 1279e5c31af7Sopenharmony_ci << " for (uint i = 0; i < " << count << "; ++i)\n" 1280e5c31af7Sopenharmony_ci << " {\n" 1281e5c31af7Sopenharmony_ci << " bool expectWrite = ((writeMask & (1 << i)) != 0);\n" 1282e5c31af7Sopenharmony_ci << " vec4 sampleColor = imageLoad(writeImg, icoords, int(i));\n" 1283e5c31af7Sopenharmony_ci << " vec4 wantedColor = (expectWrite ? wcolor : ccolor);\n" 1284e5c31af7Sopenharmony_ci << " ok = ok && (sampleColor == wantedColor);\n" 1285e5c31af7Sopenharmony_ci << " }\n" 1286e5c31af7Sopenharmony_ci << " vec4 resultColor = (ok ? gcolor : bcolor);\n" 1287e5c31af7Sopenharmony_ci << " imageStore(verificationImg, icoords, resultColor);\n" 1288e5c31af7Sopenharmony_ci << "}\n" 1289e5c31af7Sopenharmony_ci ; 1290e5c31af7Sopenharmony_ci 1291e5c31af7Sopenharmony_ci programCollection.glslSources.add("write") << glu::ComputeSource(shaderWrite.str()); 1292e5c31af7Sopenharmony_ci programCollection.glslSources.add("verify") << glu::ComputeSource(shaderVerify.str()); 1293e5c31af7Sopenharmony_ci} 1294e5c31af7Sopenharmony_ci 1295e5c31af7Sopenharmony_civkt::TestInstance* WriteSampleTest::createInstance (Context& context) const 1296e5c31af7Sopenharmony_ci{ 1297e5c31af7Sopenharmony_ci return new WriteSampleTestInstance{context, m_params}; 1298e5c31af7Sopenharmony_ci} 1299e5c31af7Sopenharmony_ci 1300e5c31af7Sopenharmony_citcu::TestStatus WriteSampleTestInstance::iterate (void) 1301e5c31af7Sopenharmony_ci{ 1302e5c31af7Sopenharmony_ci const auto& vkd = m_context.getDeviceInterface(); 1303e5c31af7Sopenharmony_ci const auto device = m_context.getDevice(); 1304e5c31af7Sopenharmony_ci auto& allocator = m_context.getDefaultAllocator(); 1305e5c31af7Sopenharmony_ci const auto queue = m_context.getUniversalQueue(); 1306e5c31af7Sopenharmony_ci const auto queueIndex = m_context.getUniversalQueueFamilyIndex(); 1307e5c31af7Sopenharmony_ci const auto extent3D = getExtent3D(m_params.sampleCount); 1308e5c31af7Sopenharmony_ci 1309e5c31af7Sopenharmony_ci // Create storage image and verification image. 1310e5c31af7Sopenharmony_ci const vk::VkImageCreateInfo storageImageInfo = 1311e5c31af7Sopenharmony_ci { 1312e5c31af7Sopenharmony_ci vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 1313e5c31af7Sopenharmony_ci nullptr, // const void* pNext; 1314e5c31af7Sopenharmony_ci 0u, // VkImageCreateFlags flags; 1315e5c31af7Sopenharmony_ci vk::VK_IMAGE_TYPE_2D, // VkImageType imageType; 1316e5c31af7Sopenharmony_ci WriteSampleTest::kImageFormat, // VkFormat format; 1317e5c31af7Sopenharmony_ci extent3D, // VkExtent3D extent; 1318e5c31af7Sopenharmony_ci 1u, // deUint32 mipLevels; 1319e5c31af7Sopenharmony_ci 1u, // deUint32 arrayLayers; 1320e5c31af7Sopenharmony_ci m_params.sampleCount, // VkSampleCountFlagBits samples; 1321e5c31af7Sopenharmony_ci vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 1322e5c31af7Sopenharmony_ci WriteSampleTest::kUsageFlags, // VkImageUsageFlags usage; 1323e5c31af7Sopenharmony_ci vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1324e5c31af7Sopenharmony_ci 1u, // deUint32 queueFamilyIndexCount; 1325e5c31af7Sopenharmony_ci &queueIndex, // const deUint32* pQueueFamilyIndices; 1326e5c31af7Sopenharmony_ci vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1327e5c31af7Sopenharmony_ci }; 1328e5c31af7Sopenharmony_ci 1329e5c31af7Sopenharmony_ci const vk::VkImageCreateInfo verificationImageInfo = 1330e5c31af7Sopenharmony_ci { 1331e5c31af7Sopenharmony_ci vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 1332e5c31af7Sopenharmony_ci nullptr, // const void* pNext; 1333e5c31af7Sopenharmony_ci 0u, // VkImageCreateFlags flags; 1334e5c31af7Sopenharmony_ci vk::VK_IMAGE_TYPE_2D, // VkImageType imageType; 1335e5c31af7Sopenharmony_ci WriteSampleTest::kImageFormat, // VkFormat format; 1336e5c31af7Sopenharmony_ci extent3D, // VkExtent3D extent; 1337e5c31af7Sopenharmony_ci 1u, // deUint32 mipLevels; 1338e5c31af7Sopenharmony_ci 1u, // deUint32 arrayLayers; 1339e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 1340e5c31af7Sopenharmony_ci vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 1341e5c31af7Sopenharmony_ci WriteSampleTest::kUsageFlags, // VkImageUsageFlags usage; 1342e5c31af7Sopenharmony_ci vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1343e5c31af7Sopenharmony_ci 1u, // deUint32 queueFamilyIndexCount; 1344e5c31af7Sopenharmony_ci &queueIndex, // const deUint32* pQueueFamilyIndices; 1345e5c31af7Sopenharmony_ci vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1346e5c31af7Sopenharmony_ci }; 1347e5c31af7Sopenharmony_ci 1348e5c31af7Sopenharmony_ci vk::ImageWithMemory storageImgPrt {vkd, device, allocator, storageImageInfo, vk::MemoryRequirement::Any}; 1349e5c31af7Sopenharmony_ci vk::ImageWithMemory verificationImgPtr {vkd, device, allocator, verificationImageInfo, vk::MemoryRequirement::Any}; 1350e5c31af7Sopenharmony_ci 1351e5c31af7Sopenharmony_ci const vk::VkImageSubresourceRange kSubresourceRange = 1352e5c31af7Sopenharmony_ci { 1353e5c31af7Sopenharmony_ci vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 1354e5c31af7Sopenharmony_ci 0u, // deUint32 baseMipLevel; 1355e5c31af7Sopenharmony_ci 1u, // deUint32 levelCount; 1356e5c31af7Sopenharmony_ci 0u, // deUint32 baseArrayLayer; 1357e5c31af7Sopenharmony_ci 1u, // deUint32 layerCount; 1358e5c31af7Sopenharmony_ci }; 1359e5c31af7Sopenharmony_ci 1360e5c31af7Sopenharmony_ci auto storageImgViewPtr = vk::makeImageView(vkd, device, storageImgPrt.get(), vk::VK_IMAGE_VIEW_TYPE_2D, WriteSampleTest::kImageFormat, kSubresourceRange); 1361e5c31af7Sopenharmony_ci auto verificationImgViewPtr = vk::makeImageView(vkd, device, verificationImgPtr.get(), vk::VK_IMAGE_VIEW_TYPE_2D, WriteSampleTest::kImageFormat, kSubresourceRange); 1362e5c31af7Sopenharmony_ci 1363e5c31af7Sopenharmony_ci // Prepare a staging buffer to check verification image. 1364e5c31af7Sopenharmony_ci const auto tcuFormat = vk::mapVkFormat(WriteSampleTest::kImageFormat); 1365e5c31af7Sopenharmony_ci const VkDeviceSize bufferSize = extent3D.width * extent3D.height * extent3D.depth * tcu::getPixelSize(tcuFormat); 1366e5c31af7Sopenharmony_ci const auto stagingBufferInfo = vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT); 1367e5c31af7Sopenharmony_ci vk::BufferWithMemory stagingBuffer {vkd, device, allocator, stagingBufferInfo, MemoryRequirement::HostVisible}; 1368e5c31af7Sopenharmony_ci 1369e5c31af7Sopenharmony_ci // Descriptor set layout. 1370e5c31af7Sopenharmony_ci vk::DescriptorSetLayoutBuilder layoutBuilder; 1371e5c31af7Sopenharmony_ci layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT); 1372e5c31af7Sopenharmony_ci layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT); 1373e5c31af7Sopenharmony_ci auto descriptorSetLayout = layoutBuilder.build(vkd, device); 1374e5c31af7Sopenharmony_ci 1375e5c31af7Sopenharmony_ci // Descriptor pool. 1376e5c31af7Sopenharmony_ci vk::DescriptorPoolBuilder poolBuilder; 1377e5c31af7Sopenharmony_ci poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u); 1378e5c31af7Sopenharmony_ci auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 1379e5c31af7Sopenharmony_ci 1380e5c31af7Sopenharmony_ci // Descriptor set. 1381e5c31af7Sopenharmony_ci const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get()); 1382e5c31af7Sopenharmony_ci 1383e5c31af7Sopenharmony_ci // Update descriptor set using the images. 1384e5c31af7Sopenharmony_ci const auto storageImgDescriptorInfo = vk::makeDescriptorImageInfo(DE_NULL, storageImgViewPtr.get(), vk::VK_IMAGE_LAYOUT_GENERAL); 1385e5c31af7Sopenharmony_ci const auto verificationImgDescriptorInfo = vk::makeDescriptorImageInfo(DE_NULL, verificationImgViewPtr.get(), vk::VK_IMAGE_LAYOUT_GENERAL); 1386e5c31af7Sopenharmony_ci 1387e5c31af7Sopenharmony_ci vk::DescriptorSetUpdateBuilder updateBuilder; 1388e5c31af7Sopenharmony_ci updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &storageImgDescriptorInfo); 1389e5c31af7Sopenharmony_ci updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &verificationImgDescriptorInfo); 1390e5c31af7Sopenharmony_ci updateBuilder.update(vkd, device); 1391e5c31af7Sopenharmony_ci 1392e5c31af7Sopenharmony_ci // Create write and verification compute pipelines. 1393e5c31af7Sopenharmony_ci auto shaderWriteModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("write"), 0u); 1394e5c31af7Sopenharmony_ci auto shaderVerifyModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("verify"), 0u); 1395e5c31af7Sopenharmony_ci auto pipelineLayout = vk::makePipelineLayout(vkd, device, descriptorSetLayout.get()); 1396e5c31af7Sopenharmony_ci 1397e5c31af7Sopenharmony_ci const vk::VkComputePipelineCreateInfo writePipelineCreateInfo = 1398e5c31af7Sopenharmony_ci { 1399e5c31af7Sopenharmony_ci vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, 1400e5c31af7Sopenharmony_ci nullptr, 1401e5c31af7Sopenharmony_ci 0u, // flags 1402e5c31af7Sopenharmony_ci { // compute shader 1403e5c31af7Sopenharmony_ci vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 1404e5c31af7Sopenharmony_ci nullptr, // const void* pNext; 1405e5c31af7Sopenharmony_ci 0u, // VkPipelineShaderStageCreateFlags flags; 1406e5c31af7Sopenharmony_ci vk::VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage; 1407e5c31af7Sopenharmony_ci shaderWriteModule.getModule(), // VkShaderModule module; 1408e5c31af7Sopenharmony_ci "main", // const char* pName; 1409e5c31af7Sopenharmony_ci nullptr, // const VkSpecializationInfo* pSpecializationInfo; 1410e5c31af7Sopenharmony_ci }, 1411e5c31af7Sopenharmony_ci pipelineLayout.get(), // layout 1412e5c31af7Sopenharmony_ci DE_NULL, // basePipelineHandle 1413e5c31af7Sopenharmony_ci 0, // basePipelineIndex 1414e5c31af7Sopenharmony_ci }; 1415e5c31af7Sopenharmony_ci 1416e5c31af7Sopenharmony_ci auto verificationPipelineCreateInfo = writePipelineCreateInfo; 1417e5c31af7Sopenharmony_ci verificationPipelineCreateInfo.stage.module = shaderVerifyModule.getModule(); 1418e5c31af7Sopenharmony_ci 1419e5c31af7Sopenharmony_ci auto writePipeline = vk::createComputePipeline(vkd, device, DE_NULL, &writePipelineCreateInfo); 1420e5c31af7Sopenharmony_ci auto verificationPipeline = vk::createComputePipeline(vkd, device, DE_NULL, &verificationPipelineCreateInfo); 1421e5c31af7Sopenharmony_ci 1422e5c31af7Sopenharmony_ci // Transition images to the correct layout and buffers at different stages. 1423e5c31af7Sopenharmony_ci auto storageImgPreClearBarrier = vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, storageImgPrt.get(), kSubresourceRange); 1424e5c31af7Sopenharmony_ci auto storageImgPreShaderBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vk::VK_IMAGE_LAYOUT_GENERAL, storageImgPrt.get(), kSubresourceRange); 1425e5c31af7Sopenharmony_ci auto verificationImgPreShaderBarrier = vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, verificationImgPtr.get(), kSubresourceRange); 1426e5c31af7Sopenharmony_ci auto storageImgPreVerificationBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, storageImgPrt.get(), kSubresourceRange); 1427e5c31af7Sopenharmony_ci auto verificationImgPostBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationImgPtr.get(), kSubresourceRange); 1428e5c31af7Sopenharmony_ci auto bufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, stagingBuffer.get(), 0ull, bufferSize); 1429e5c31af7Sopenharmony_ci 1430e5c31af7Sopenharmony_ci // Command buffer. 1431e5c31af7Sopenharmony_ci auto cmdPool = vk::makeCommandPool(vkd, device, queueIndex); 1432e5c31af7Sopenharmony_ci auto cmdBufferPtr = vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY); 1433e5c31af7Sopenharmony_ci auto cmdBuffer = cmdBufferPtr.get(); 1434e5c31af7Sopenharmony_ci 1435e5c31af7Sopenharmony_ci // Clear color for the storage image. 1436e5c31af7Sopenharmony_ci const auto clearColor = vk::makeClearValueColor(WriteSampleTest::kClearColor); 1437e5c31af7Sopenharmony_ci 1438e5c31af7Sopenharmony_ci const vk::VkBufferImageCopy copyRegion = 1439e5c31af7Sopenharmony_ci { 1440e5c31af7Sopenharmony_ci 0ull, // VkDeviceSize bufferOffset; 1441e5c31af7Sopenharmony_ci extent3D.width, // deUint32 bufferRowLength; 1442e5c31af7Sopenharmony_ci extent3D.height, // deUint32 bufferImageHeight; 1443e5c31af7Sopenharmony_ci { // VkImageSubresourceLayers imageSubresource; 1444e5c31af7Sopenharmony_ci vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 1445e5c31af7Sopenharmony_ci 0u, // deUint32 mipLevel; 1446e5c31af7Sopenharmony_ci 0u, // deUint32 baseArrayLayer; 1447e5c31af7Sopenharmony_ci 1u, // deUint32 layerCount; 1448e5c31af7Sopenharmony_ci }, 1449e5c31af7Sopenharmony_ci { 0, 0, 0 }, // VkOffset3D imageOffset; 1450e5c31af7Sopenharmony_ci extent3D, // VkExtent3D imageExtent; 1451e5c31af7Sopenharmony_ci }; 1452e5c31af7Sopenharmony_ci 1453e5c31af7Sopenharmony_ci // Record and submit commands. 1454e5c31af7Sopenharmony_ci vk::beginCommandBuffer(vkd, cmdBuffer); 1455e5c31af7Sopenharmony_ci // Clear storage image. 1456e5c31af7Sopenharmony_ci vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreClearBarrier); 1457e5c31af7Sopenharmony_ci vkd.cmdClearColorImage(cmdBuffer, storageImgPrt.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor.color, 1u, &kSubresourceRange); 1458e5c31af7Sopenharmony_ci 1459e5c31af7Sopenharmony_ci // Bind write pipeline and descriptor set. 1460e5c31af7Sopenharmony_ci vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, writePipeline.get()); 1461e5c31af7Sopenharmony_ci vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0, 1u, &descriptorSet.get(), 0u, nullptr); 1462e5c31af7Sopenharmony_ci 1463e5c31af7Sopenharmony_ci // Transition images to the appropriate layout before running the shader. 1464e5c31af7Sopenharmony_ci vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreShaderBarrier); 1465e5c31af7Sopenharmony_ci vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &verificationImgPreShaderBarrier); 1466e5c31af7Sopenharmony_ci 1467e5c31af7Sopenharmony_ci // Run shader. 1468e5c31af7Sopenharmony_ci vkd.cmdDispatch(cmdBuffer, extent3D.width, extent3D.height, extent3D.depth); 1469e5c31af7Sopenharmony_ci 1470e5c31af7Sopenharmony_ci // Bind verification pipeline. 1471e5c31af7Sopenharmony_ci vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, verificationPipeline.get()); 1472e5c31af7Sopenharmony_ci 1473e5c31af7Sopenharmony_ci // Make sure writes happen before reads in the second dispatch for the storage image. 1474e5c31af7Sopenharmony_ci vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreVerificationBarrier); 1475e5c31af7Sopenharmony_ci 1476e5c31af7Sopenharmony_ci // Run verification shader. 1477e5c31af7Sopenharmony_ci vkd.cmdDispatch(cmdBuffer, extent3D.width, extent3D.height, extent3D.depth); 1478e5c31af7Sopenharmony_ci 1479e5c31af7Sopenharmony_ci // Change verification image layout to prepare the transfer. 1480e5c31af7Sopenharmony_ci vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &verificationImgPostBarrier); 1481e5c31af7Sopenharmony_ci 1482e5c31af7Sopenharmony_ci // Copy verification image to staging buffer. 1483e5c31af7Sopenharmony_ci vkd.cmdCopyImageToBuffer(cmdBuffer, verificationImgPtr.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer.get(), 1u, ©Region); 1484e5c31af7Sopenharmony_ci vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr); 1485e5c31af7Sopenharmony_ci 1486e5c31af7Sopenharmony_ci vk::endCommandBuffer(vkd, cmdBuffer); 1487e5c31af7Sopenharmony_ci 1488e5c31af7Sopenharmony_ci // Run shaders. 1489e5c31af7Sopenharmony_ci vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer); 1490e5c31af7Sopenharmony_ci 1491e5c31af7Sopenharmony_ci // Read buffer pixels. 1492e5c31af7Sopenharmony_ci const auto& bufferAlloc = stagingBuffer.getAllocation(); 1493e5c31af7Sopenharmony_ci vk::invalidateAlloc(vkd, device, bufferAlloc); 1494e5c31af7Sopenharmony_ci 1495e5c31af7Sopenharmony_ci // Copy buffer data to texture level and verify all pixels have the proper color. 1496e5c31af7Sopenharmony_ci tcu::TextureLevel texture {tcuFormat, static_cast<int>(extent3D.width), static_cast<int>(extent3D.height), static_cast<int>(extent3D.depth)}; 1497e5c31af7Sopenharmony_ci const auto access = texture.getAccess(); 1498e5c31af7Sopenharmony_ci deMemcpy(access.getDataPtr(), reinterpret_cast<char*>(bufferAlloc.getHostPtr()) + bufferAlloc.getOffset(), static_cast<size_t>(bufferSize)); 1499e5c31af7Sopenharmony_ci 1500e5c31af7Sopenharmony_ci for (int i = 0; i < access.getWidth(); ++i) 1501e5c31af7Sopenharmony_ci for (int j = 0; j < access.getHeight(); ++j) 1502e5c31af7Sopenharmony_ci for (int k = 0; k < access.getDepth(); ++k) 1503e5c31af7Sopenharmony_ci { 1504e5c31af7Sopenharmony_ci if (access.getPixel(i, j, k) != WriteSampleTest::kGoodColor) 1505e5c31af7Sopenharmony_ci { 1506e5c31af7Sopenharmony_ci std::ostringstream msg; 1507e5c31af7Sopenharmony_ci msg << "Invalid result at pixel (" << i << ", " << j << ", " << k << "); check error mask for more details"; 1508e5c31af7Sopenharmony_ci m_context.getTestContext().getLog() << tcu::TestLog::Image("ErrorMask", "Indicates which pixels have unexpected values", access); 1509e5c31af7Sopenharmony_ci return tcu::TestStatus::fail(msg.str()); 1510e5c31af7Sopenharmony_ci } 1511e5c31af7Sopenharmony_ci } 1512e5c31af7Sopenharmony_ci 1513e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Pass"); 1514e5c31af7Sopenharmony_ci} 1515e5c31af7Sopenharmony_ci 1516e5c31af7Sopenharmony_ciusing WriteSampleMaskParams = WriteSampleParams; 1517e5c31af7Sopenharmony_ci 1518e5c31af7Sopenharmony_ciclass WriteSampleMaskTestCase : public vkt::TestCase 1519e5c31af7Sopenharmony_ci{ 1520e5c31af7Sopenharmony_cipublic: 1521e5c31af7Sopenharmony_ci WriteSampleMaskTestCase (tcu::TestContext& testCtx, const std::string& name, const WriteSampleMaskParams& params); 1522e5c31af7Sopenharmony_ci virtual ~WriteSampleMaskTestCase (void) {} 1523e5c31af7Sopenharmony_ci 1524e5c31af7Sopenharmony_ci virtual void checkSupport (Context& context) const; 1525e5c31af7Sopenharmony_ci virtual void initPrograms (vk::SourceCollections& programCollection) const; 1526e5c31af7Sopenharmony_ci virtual TestInstance* createInstance (Context& context) const; 1527e5c31af7Sopenharmony_ci static deUint32 getBufferElems (deUint32 sampleCount); 1528e5c31af7Sopenharmony_ci 1529e5c31af7Sopenharmony_ci static const tcu::Vec4 kClearColor; 1530e5c31af7Sopenharmony_ci static const tcu::Vec4 kWriteColor; 1531e5c31af7Sopenharmony_ci 1532e5c31af7Sopenharmony_ci static constexpr vk::VkFormat kImageFormat = vk::VK_FORMAT_R8G8B8A8_UNORM; 1533e5c31af7Sopenharmony_ci static constexpr vk::VkImageUsageFlags kUsageFlags = (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT); 1534e5c31af7Sopenharmony_ci static constexpr vk::VkFormatFeatureFlags kFeatureFlags = (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); 1535e5c31af7Sopenharmony_ci 1536e5c31af7Sopenharmony_ciprivate: 1537e5c31af7Sopenharmony_ci WriteSampleMaskParams m_params; 1538e5c31af7Sopenharmony_ci}; 1539e5c31af7Sopenharmony_ci 1540e5c31af7Sopenharmony_ciconst tcu::Vec4 WriteSampleMaskTestCase::kClearColor {0.0f, 0.0f, 0.0f, 1.0f}; 1541e5c31af7Sopenharmony_ciconst tcu::Vec4 WriteSampleMaskTestCase::kWriteColor {0.0f, 0.0f, 1.0f, 1.0f}; 1542e5c31af7Sopenharmony_ci 1543e5c31af7Sopenharmony_ciclass WriteSampleMaskTestInstance : public vkt::TestInstance 1544e5c31af7Sopenharmony_ci{ 1545e5c31af7Sopenharmony_cipublic: 1546e5c31af7Sopenharmony_ci WriteSampleMaskTestInstance (Context& context, const WriteSampleMaskParams& params); 1547e5c31af7Sopenharmony_ci virtual ~WriteSampleMaskTestInstance (void) {} 1548e5c31af7Sopenharmony_ci 1549e5c31af7Sopenharmony_ci virtual tcu::TestStatus iterate (void); 1550e5c31af7Sopenharmony_ci 1551e5c31af7Sopenharmony_ciprivate: 1552e5c31af7Sopenharmony_ci WriteSampleMaskParams m_params; 1553e5c31af7Sopenharmony_ci}; 1554e5c31af7Sopenharmony_ci 1555e5c31af7Sopenharmony_ciWriteSampleMaskTestCase::WriteSampleMaskTestCase (tcu::TestContext& testCtx, const std::string& name, const WriteSampleMaskParams& params) 1556e5c31af7Sopenharmony_ci : vkt::TestCase (testCtx, name) 1557e5c31af7Sopenharmony_ci , m_params (params) 1558e5c31af7Sopenharmony_ci{} 1559e5c31af7Sopenharmony_ci 1560e5c31af7Sopenharmony_civoid WriteSampleMaskTestCase::checkSupport (Context& context) const 1561e5c31af7Sopenharmony_ci{ 1562e5c31af7Sopenharmony_ci const auto& vki = context.getInstanceInterface(); 1563e5c31af7Sopenharmony_ci const auto physicalDevice = context.getPhysicalDevice(); 1564e5c31af7Sopenharmony_ci 1565e5c31af7Sopenharmony_ci // Check if sampleRateShading is supported. 1566e5c31af7Sopenharmony_ci if(!vk::getPhysicalDeviceFeatures(vki, physicalDevice).sampleRateShading) 1567e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Sample rate shading is not supported"); 1568e5c31af7Sopenharmony_ci 1569e5c31af7Sopenharmony_ci // Check the specific image format. 1570e5c31af7Sopenharmony_ci const auto properties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat); 1571e5c31af7Sopenharmony_ci if (!(properties.optimalTilingFeatures & kFeatureFlags)) 1572e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Format does not support the required features"); 1573e5c31af7Sopenharmony_ci 1574e5c31af7Sopenharmony_ci // Check the supported sample count. 1575e5c31af7Sopenharmony_ci const auto imgProps = vk::getPhysicalDeviceImageFormatProperties(vki, physicalDevice, kImageFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, kUsageFlags, 0u); 1576e5c31af7Sopenharmony_ci if (!(imgProps.sampleCounts & m_params.sampleCount)) 1577e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Format does not support the required sample count"); 1578e5c31af7Sopenharmony_ci 1579e5c31af7Sopenharmony_ci checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType); 1580e5c31af7Sopenharmony_ci} 1581e5c31af7Sopenharmony_ci 1582e5c31af7Sopenharmony_civoid WriteSampleMaskTestCase::initPrograms (vk::SourceCollections& programCollection) const 1583e5c31af7Sopenharmony_ci{ 1584e5c31af7Sopenharmony_ci const auto bpc = de::toString(bitsPerCoord(m_params.sampleCount)); 1585e5c31af7Sopenharmony_ci const auto size = imageSize(m_params.sampleCount); 1586e5c31af7Sopenharmony_ci const auto bufferElems = getBufferElems(m_params.sampleCount); 1587e5c31af7Sopenharmony_ci 1588e5c31af7Sopenharmony_ci // Passthrough vertex shader. 1589e5c31af7Sopenharmony_ci std::ostringstream vertShader; 1590e5c31af7Sopenharmony_ci 1591e5c31af7Sopenharmony_ci vertShader 1592e5c31af7Sopenharmony_ci << "#version 450\n" 1593e5c31af7Sopenharmony_ci << "layout (location=0) in vec2 inPos;\n" 1594e5c31af7Sopenharmony_ci << "void main()\n" 1595e5c31af7Sopenharmony_ci << "{\n" 1596e5c31af7Sopenharmony_ci << " gl_Position = vec4(inPos, 0.0, 1.0);\n" 1597e5c31af7Sopenharmony_ci << "}\n" 1598e5c31af7Sopenharmony_ci ; 1599e5c31af7Sopenharmony_ci 1600e5c31af7Sopenharmony_ci // Fragment shader common header. 1601e5c31af7Sopenharmony_ci std::ostringstream fragHeader; 1602e5c31af7Sopenharmony_ci 1603e5c31af7Sopenharmony_ci fragHeader 1604e5c31af7Sopenharmony_ci << "#version 450\n" 1605e5c31af7Sopenharmony_ci << "\n" 1606e5c31af7Sopenharmony_ci // The color attachment is useless for the second subpass but avoids having to use an empty subpass and verifying the sample 1607e5c31af7Sopenharmony_ci // count is valid for it. 1608e5c31af7Sopenharmony_ci << "layout (location=0) out vec4 outColor;\n" 1609e5c31af7Sopenharmony_ci << "\n" 1610e5c31af7Sopenharmony_ci << "vec4 wcolor = " << getShaderDecl(kWriteColor) << ";\n" 1611e5c31af7Sopenharmony_ci << "vec4 ccolor = " << getShaderDecl(kClearColor) << ";\n" 1612e5c31af7Sopenharmony_ci << "\n" 1613e5c31af7Sopenharmony_ci ; 1614e5c31af7Sopenharmony_ci 1615e5c31af7Sopenharmony_ci const auto fragHeaderStr = fragHeader.str(); 1616e5c31af7Sopenharmony_ci 1617e5c31af7Sopenharmony_ci // Fragment shader setting the sample mask and writing to the output color attachment. The sample mask will guarantee each image 1618e5c31af7Sopenharmony_ci // pixel gets a different combination of sample bits set, allowing the fragment shader to write in that sample or not, from all 1619e5c31af7Sopenharmony_ci // zeros in pixel (0, 0) to all ones in the opposite corner. 1620e5c31af7Sopenharmony_ci std::ostringstream fragShaderWrite; 1621e5c31af7Sopenharmony_ci 1622e5c31af7Sopenharmony_ci fragShaderWrite 1623e5c31af7Sopenharmony_ci << fragHeaderStr 1624e5c31af7Sopenharmony_ci << "void main()\n" 1625e5c31af7Sopenharmony_ci << "{\n" 1626e5c31af7Sopenharmony_ci << " uvec2 ucoords = uvec2(gl_FragCoord);\n" 1627e5c31af7Sopenharmony_ci << " ivec2 icoords = ivec2(ucoords);\n" 1628e5c31af7Sopenharmony_ci << " gl_SampleMask[0] = int((ucoords.x << " << bpc << ") | ucoords.y);\n" 1629e5c31af7Sopenharmony_ci << " outColor = wcolor;\n" 1630e5c31af7Sopenharmony_ci << "}\n" 1631e5c31af7Sopenharmony_ci ; 1632e5c31af7Sopenharmony_ci 1633e5c31af7Sopenharmony_ci // Fragment shader reading from the previous output color attachment and copying the state to an SSBO for verification. 1634e5c31af7Sopenharmony_ci std::ostringstream fragShaderCheck; 1635e5c31af7Sopenharmony_ci 1636e5c31af7Sopenharmony_ci const bool isMultiSample = (m_params.sampleCount != vk::VK_SAMPLE_COUNT_1_BIT); 1637e5c31af7Sopenharmony_ci fragShaderCheck 1638e5c31af7Sopenharmony_ci << fragHeaderStr 1639e5c31af7Sopenharmony_ci << "layout(set=0, binding=0, input_attachment_index=0) uniform subpassInput" << (isMultiSample ? "MS" : "") << " inputAttachment;\n" 1640e5c31af7Sopenharmony_ci << "layout(set=0, binding=1, std430) buffer StorageBuffer {\n" 1641e5c31af7Sopenharmony_ci << " int writeFlags[" << bufferElems << "];\n" 1642e5c31af7Sopenharmony_ci << "} sb;\n" 1643e5c31af7Sopenharmony_ci << "\n" 1644e5c31af7Sopenharmony_ci << "void main()\n" 1645e5c31af7Sopenharmony_ci << "{\n" 1646e5c31af7Sopenharmony_ci << " uvec2 ucoords = uvec2(gl_FragCoord);\n" 1647e5c31af7Sopenharmony_ci << " ivec2 icoords = ivec2(ucoords);\n" 1648e5c31af7Sopenharmony_ci << " uint bufferp = ((ucoords.y * " << size.width << " + ucoords.x) * " << m_params.sampleCount << ") + uint(gl_SampleID);\n" 1649e5c31af7Sopenharmony_ci << " vec4 storedc = subpassLoad(inputAttachment" << (isMultiSample ? ", gl_SampleID" : "") << ");\n" 1650e5c31af7Sopenharmony_ci << " sb.writeFlags[bufferp] = ((storedc == wcolor) ? 1 : ((storedc == ccolor) ? 0 : 2));\n" 1651e5c31af7Sopenharmony_ci << " outColor = storedc;\n" 1652e5c31af7Sopenharmony_ci << "}\n" 1653e5c31af7Sopenharmony_ci ; 1654e5c31af7Sopenharmony_ci 1655e5c31af7Sopenharmony_ci programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.str()); 1656e5c31af7Sopenharmony_ci programCollection.glslSources.add("frag_write") << glu::FragmentSource(fragShaderWrite.str()); 1657e5c31af7Sopenharmony_ci programCollection.glslSources.add("frag_check") << glu::FragmentSource(fragShaderCheck.str()); 1658e5c31af7Sopenharmony_ci} 1659e5c31af7Sopenharmony_ci 1660e5c31af7Sopenharmony_ciTestInstance* WriteSampleMaskTestCase::createInstance (Context& context) const 1661e5c31af7Sopenharmony_ci{ 1662e5c31af7Sopenharmony_ci return new WriteSampleMaskTestInstance(context, m_params); 1663e5c31af7Sopenharmony_ci} 1664e5c31af7Sopenharmony_ci 1665e5c31af7Sopenharmony_cideUint32 WriteSampleMaskTestCase::getBufferElems (deUint32 sampleCount) 1666e5c31af7Sopenharmony_ci{ 1667e5c31af7Sopenharmony_ci const auto imgSize = imageSize(sampleCount); 1668e5c31af7Sopenharmony_ci return (imgSize.width * imgSize.height * sampleCount); 1669e5c31af7Sopenharmony_ci} 1670e5c31af7Sopenharmony_ci 1671e5c31af7Sopenharmony_ciWriteSampleMaskTestInstance::WriteSampleMaskTestInstance (Context& context, const WriteSampleMaskParams& params) 1672e5c31af7Sopenharmony_ci : vkt::TestInstance (context) 1673e5c31af7Sopenharmony_ci , m_params (params) 1674e5c31af7Sopenharmony_ci{} 1675e5c31af7Sopenharmony_ci 1676e5c31af7Sopenharmony_citcu::TestStatus WriteSampleMaskTestInstance::iterate (void) 1677e5c31af7Sopenharmony_ci{ 1678e5c31af7Sopenharmony_ci const auto& vki = m_context.getInstanceInterface(); 1679e5c31af7Sopenharmony_ci const auto& vkd = m_context.getDeviceInterface(); 1680e5c31af7Sopenharmony_ci const auto physicalDevice = m_context.getPhysicalDevice(); 1681e5c31af7Sopenharmony_ci const auto device = m_context.getDevice(); 1682e5c31af7Sopenharmony_ci auto& alloc = m_context.getDefaultAllocator(); 1683e5c31af7Sopenharmony_ci const auto queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 1684e5c31af7Sopenharmony_ci const auto queue = m_context.getUniversalQueue(); 1685e5c31af7Sopenharmony_ci 1686e5c31af7Sopenharmony_ci static constexpr auto kImageFormat = WriteSampleMaskTestCase::kImageFormat; 1687e5c31af7Sopenharmony_ci static constexpr auto kImageUsage = WriteSampleMaskTestCase::kUsageFlags; 1688e5c31af7Sopenharmony_ci const auto kImageExtent = getExtent3D(m_params.sampleCount); 1689e5c31af7Sopenharmony_ci const auto kBufferElems = WriteSampleMaskTestCase::getBufferElems(m_params.sampleCount); 1690e5c31af7Sopenharmony_ci const auto kBufferSize = static_cast<vk::VkDeviceSize>(kBufferElems * sizeof(deInt32)); 1691e5c31af7Sopenharmony_ci 1692e5c31af7Sopenharmony_ci // Create image. 1693e5c31af7Sopenharmony_ci const vk::VkImageCreateInfo imageCreateInfo = 1694e5c31af7Sopenharmony_ci { 1695e5c31af7Sopenharmony_ci vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 1696e5c31af7Sopenharmony_ci nullptr, // const void* pNext; 1697e5c31af7Sopenharmony_ci 0u, // VkImageCreateFlags flags; 1698e5c31af7Sopenharmony_ci vk::VK_IMAGE_TYPE_2D, // VkImageType imageType; 1699e5c31af7Sopenharmony_ci kImageFormat, // VkFormat format; 1700e5c31af7Sopenharmony_ci kImageExtent, // VkExtent3D extent; 1701e5c31af7Sopenharmony_ci 1u, // deUint32 mipLevels; 1702e5c31af7Sopenharmony_ci 1u, // deUint32 arrayLayers; 1703e5c31af7Sopenharmony_ci m_params.sampleCount, // VkSampleCountFlagBits samples; 1704e5c31af7Sopenharmony_ci vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 1705e5c31af7Sopenharmony_ci kImageUsage, // VkImageUsageFlags usage; 1706e5c31af7Sopenharmony_ci vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1707e5c31af7Sopenharmony_ci 0u, // deUint32 queueFamilyIndexCount; 1708e5c31af7Sopenharmony_ci nullptr, // const deUint32* pQueueFamilyIndices; 1709e5c31af7Sopenharmony_ci vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1710e5c31af7Sopenharmony_ci }; 1711e5c31af7Sopenharmony_ci 1712e5c31af7Sopenharmony_ci const vk::ImageWithMemory colorImage (vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any); 1713e5c31af7Sopenharmony_ci const vk::ImageWithMemory auxiliarImage (vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any); // For the second subpass. 1714e5c31af7Sopenharmony_ci 1715e5c31af7Sopenharmony_ci // Image views. 1716e5c31af7Sopenharmony_ci const auto subresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 1717e5c31af7Sopenharmony_ci const auto colorImageView = vk::makeImageView(vkd, device, colorImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, subresourceRange); 1718e5c31af7Sopenharmony_ci const auto auxiliarImageView = vk::makeImageView(vkd, device, auxiliarImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, subresourceRange); 1719e5c31af7Sopenharmony_ci 1720e5c31af7Sopenharmony_ci // Create storage buffer used to verify results. 1721e5c31af7Sopenharmony_ci const vk::BufferWithMemory storageBuffer(vkd, device, alloc, vk::makeBufferCreateInfo(kBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible); 1722e5c31af7Sopenharmony_ci 1723e5c31af7Sopenharmony_ci // Full-screen quad. 1724e5c31af7Sopenharmony_ci const std::vector<tcu::Vec2> quadVertices = 1725e5c31af7Sopenharmony_ci { 1726e5c31af7Sopenharmony_ci tcu::Vec2(-1.0f, 1.0f), // Lower left 1727e5c31af7Sopenharmony_ci tcu::Vec2( 1.0f, 1.0f), // Lower right 1728e5c31af7Sopenharmony_ci tcu::Vec2( 1.0f, -1.0f), // Top right. 1729e5c31af7Sopenharmony_ci tcu::Vec2(-1.0f, 1.0f), // Lower left 1730e5c31af7Sopenharmony_ci tcu::Vec2( 1.0f, -1.0f), // Top right. 1731e5c31af7Sopenharmony_ci tcu::Vec2(-1.0f, -1.0f), // Top left. 1732e5c31af7Sopenharmony_ci }; 1733e5c31af7Sopenharmony_ci 1734e5c31af7Sopenharmony_ci // Vertex buffer. 1735e5c31af7Sopenharmony_ci const auto vertexBufferSize = static_cast<vk::VkDeviceSize>(quadVertices.size() * sizeof(decltype(quadVertices)::value_type)); 1736e5c31af7Sopenharmony_ci const vk::BufferWithMemory vertexBuffer (vkd, device, alloc, vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), vk::MemoryRequirement::HostVisible); 1737e5c31af7Sopenharmony_ci const auto& vertexBufferAlloc = vertexBuffer.getAllocation(); 1738e5c31af7Sopenharmony_ci void* vertexBufferPtr = vertexBufferAlloc.getHostPtr(); 1739e5c31af7Sopenharmony_ci const vk::VkDeviceSize vertexBufferOffset = 0; 1740e5c31af7Sopenharmony_ci deMemcpy(vertexBufferPtr, quadVertices.data(), static_cast<size_t>(vertexBufferSize)); 1741e5c31af7Sopenharmony_ci vk::flushAlloc(vkd, device, vertexBufferAlloc); 1742e5c31af7Sopenharmony_ci 1743e5c31af7Sopenharmony_ci // Descriptor set layout. 1744e5c31af7Sopenharmony_ci vk::DescriptorSetLayoutBuilder setLayoutBuilder; 1745e5c31af7Sopenharmony_ci setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, vk::VK_SHADER_STAGE_FRAGMENT_BIT); 1746e5c31af7Sopenharmony_ci setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT); 1747e5c31af7Sopenharmony_ci const auto descriptorSetLayout = setLayoutBuilder.build(vkd, device); 1748e5c31af7Sopenharmony_ci 1749e5c31af7Sopenharmony_ci // Descriptor pool and set. 1750e5c31af7Sopenharmony_ci vk::DescriptorPoolBuilder poolBuilder; 1751e5c31af7Sopenharmony_ci poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u); 1752e5c31af7Sopenharmony_ci poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u); 1753e5c31af7Sopenharmony_ci const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 1754e5c31af7Sopenharmony_ci const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get()); 1755e5c31af7Sopenharmony_ci 1756e5c31af7Sopenharmony_ci // Render pass. 1757e5c31af7Sopenharmony_ci const std::vector<vk::VkAttachmentDescription> attachments = 1758e5c31af7Sopenharmony_ci { 1759e5c31af7Sopenharmony_ci // Main color attachment. 1760e5c31af7Sopenharmony_ci { 1761e5c31af7Sopenharmony_ci 0u, // VkAttachmentDescriptionFlags flags; 1762e5c31af7Sopenharmony_ci kImageFormat, // VkFormat format; 1763e5c31af7Sopenharmony_ci m_params.sampleCount, // VkSampleCountFlagBits samples; 1764e5c31af7Sopenharmony_ci vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 1765e5c31af7Sopenharmony_ci vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 1766e5c31af7Sopenharmony_ci vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 1767e5c31af7Sopenharmony_ci vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 1768e5c31af7Sopenharmony_ci vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1769e5c31af7Sopenharmony_ci vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout finalLayout; 1770e5c31af7Sopenharmony_ci }, 1771e5c31af7Sopenharmony_ci // Auxiliar color attachment for the check pass. 1772e5c31af7Sopenharmony_ci { 1773e5c31af7Sopenharmony_ci 0u, // VkAttachmentDescriptionFlags flags; 1774e5c31af7Sopenharmony_ci kImageFormat, // VkFormat format; 1775e5c31af7Sopenharmony_ci m_params.sampleCount, // VkSampleCountFlagBits samples; 1776e5c31af7Sopenharmony_ci vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; 1777e5c31af7Sopenharmony_ci vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp; 1778e5c31af7Sopenharmony_ci vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 1779e5c31af7Sopenharmony_ci vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 1780e5c31af7Sopenharmony_ci vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1781e5c31af7Sopenharmony_ci vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 1782e5c31af7Sopenharmony_ci }, 1783e5c31af7Sopenharmony_ci }; 1784e5c31af7Sopenharmony_ci 1785e5c31af7Sopenharmony_ci const vk::VkAttachmentReference colorAttachmentReference = 1786e5c31af7Sopenharmony_ci { 1787e5c31af7Sopenharmony_ci 0u, // deUint32 attachment; 1788e5c31af7Sopenharmony_ci vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; 1789e5c31af7Sopenharmony_ci }; 1790e5c31af7Sopenharmony_ci 1791e5c31af7Sopenharmony_ci const vk::VkAttachmentReference colorAsInputAttachment = 1792e5c31af7Sopenharmony_ci { 1793e5c31af7Sopenharmony_ci 0u, // deUint32 attachment; 1794e5c31af7Sopenharmony_ci vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout layout; 1795e5c31af7Sopenharmony_ci }; 1796e5c31af7Sopenharmony_ci 1797e5c31af7Sopenharmony_ci const vk::VkAttachmentReference auxiliarAttachmentReference = 1798e5c31af7Sopenharmony_ci { 1799e5c31af7Sopenharmony_ci 1u, // deUint32 attachment; 1800e5c31af7Sopenharmony_ci vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; 1801e5c31af7Sopenharmony_ci }; 1802e5c31af7Sopenharmony_ci 1803e5c31af7Sopenharmony_ci const std::vector<vk::VkSubpassDescription> subpasses = 1804e5c31af7Sopenharmony_ci { 1805e5c31af7Sopenharmony_ci // First subpass writing to the main attachment. 1806e5c31af7Sopenharmony_ci { 1807e5c31af7Sopenharmony_ci 0u, // VkSubpassDescriptionFlags flags; 1808e5c31af7Sopenharmony_ci vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 1809e5c31af7Sopenharmony_ci 0u, // deUint32 inputAttachmentCount; 1810e5c31af7Sopenharmony_ci nullptr, // const VkAttachmentReference* pInputAttachments; 1811e5c31af7Sopenharmony_ci 1u, // deUint32 colorAttachmentCount; 1812e5c31af7Sopenharmony_ci &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments; 1813e5c31af7Sopenharmony_ci nullptr, // const VkAttachmentReference* pResolveAttachments; 1814e5c31af7Sopenharmony_ci nullptr, // const VkAttachmentReference* pDepthStencilAttachment; 1815e5c31af7Sopenharmony_ci 0u, // deUint32 preserveAttachmentCount; 1816e5c31af7Sopenharmony_ci nullptr, // const deUint32* pPreserveAttachments; 1817e5c31af7Sopenharmony_ci }, 1818e5c31af7Sopenharmony_ci // Second subpass writing to the auxiliar attachment. 1819e5c31af7Sopenharmony_ci { 1820e5c31af7Sopenharmony_ci 0u, // VkSubpassDescriptionFlags flags; 1821e5c31af7Sopenharmony_ci vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 1822e5c31af7Sopenharmony_ci 1u, // deUint32 inputAttachmentCount; 1823e5c31af7Sopenharmony_ci &colorAsInputAttachment, // const VkAttachmentReference* pInputAttachments; 1824e5c31af7Sopenharmony_ci 1u, // deUint32 colorAttachmentCount; 1825e5c31af7Sopenharmony_ci &auxiliarAttachmentReference, // const VkAttachmentReference* pColorAttachments; 1826e5c31af7Sopenharmony_ci nullptr, // const VkAttachmentReference* pResolveAttachments; 1827e5c31af7Sopenharmony_ci nullptr, // const VkAttachmentReference* pDepthStencilAttachment; 1828e5c31af7Sopenharmony_ci 0u, // deUint32 preserveAttachmentCount; 1829e5c31af7Sopenharmony_ci nullptr, // const deUint32* pPreserveAttachments; 1830e5c31af7Sopenharmony_ci }, 1831e5c31af7Sopenharmony_ci }; 1832e5c31af7Sopenharmony_ci 1833e5c31af7Sopenharmony_ci const std::vector<vk::VkSubpassDependency> subpassDependencies = 1834e5c31af7Sopenharmony_ci { 1835e5c31af7Sopenharmony_ci // First subpass writes to the color attachment and second subpass reads it as an input attachment. 1836e5c31af7Sopenharmony_ci { 1837e5c31af7Sopenharmony_ci 0u, // deUint32 srcSubpass; 1838e5c31af7Sopenharmony_ci 1u, // deUint32 dstSubpass; 1839e5c31af7Sopenharmony_ci vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask; 1840e5c31af7Sopenharmony_ci vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask; 1841e5c31af7Sopenharmony_ci vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; 1842e5c31af7Sopenharmony_ci vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask; 1843e5c31af7Sopenharmony_ci 0u, // VkDependencyFlags dependencyFlags; 1844e5c31af7Sopenharmony_ci }, 1845e5c31af7Sopenharmony_ci }; 1846e5c31af7Sopenharmony_ci 1847e5c31af7Sopenharmony_ci const vk::VkRenderPassCreateInfo renderPassInfo = 1848e5c31af7Sopenharmony_ci { 1849e5c31af7Sopenharmony_ci vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 1850e5c31af7Sopenharmony_ci nullptr, // const void* pNext; 1851e5c31af7Sopenharmony_ci 0u, // VkRenderPassCreateFlags flags; 1852e5c31af7Sopenharmony_ci static_cast<deUint32>(attachments.size()), // deUint32 attachmentCount; 1853e5c31af7Sopenharmony_ci attachments.data(), // const VkAttachmentDescription* pAttachments; 1854e5c31af7Sopenharmony_ci static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount; 1855e5c31af7Sopenharmony_ci subpasses.data(), // const VkSubpassDescription* pSubpasses; 1856e5c31af7Sopenharmony_ci static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount; 1857e5c31af7Sopenharmony_ci subpassDependencies.data(), // const VkSubpassDependency* pDependencies; 1858e5c31af7Sopenharmony_ci }; 1859e5c31af7Sopenharmony_ci RenderPassWrapper renderPass (m_params.pipelineConstructionType, vkd, device, &renderPassInfo); 1860e5c31af7Sopenharmony_ci 1861e5c31af7Sopenharmony_ci // Framebuffer. 1862e5c31af7Sopenharmony_ci const std::vector<vk::VkImage> images = 1863e5c31af7Sopenharmony_ci { 1864e5c31af7Sopenharmony_ci colorImage.get(), 1865e5c31af7Sopenharmony_ci auxiliarImage.get(), 1866e5c31af7Sopenharmony_ci }; 1867e5c31af7Sopenharmony_ci const std::vector<vk::VkImageView> imageViews = 1868e5c31af7Sopenharmony_ci { 1869e5c31af7Sopenharmony_ci colorImageView.get(), 1870e5c31af7Sopenharmony_ci auxiliarImageView.get(), 1871e5c31af7Sopenharmony_ci }; 1872e5c31af7Sopenharmony_ci renderPass.createFramebuffer(vkd, device, static_cast<deUint32>(imageViews.size()), images.data(), imageViews.data(), kImageExtent.width, kImageExtent.height); 1873e5c31af7Sopenharmony_ci 1874e5c31af7Sopenharmony_ci // Empty pipeline layout for the first subpass. 1875e5c31af7Sopenharmony_ci const PipelineLayoutWrapper emptyPipelineLayout (m_params.pipelineConstructionType, vkd, device); 1876e5c31af7Sopenharmony_ci 1877e5c31af7Sopenharmony_ci // Pipeline layout for the second subpass. 1878e5c31af7Sopenharmony_ci const PipelineLayoutWrapper checkPipelineLayout (m_params.pipelineConstructionType, vkd, device, descriptorSetLayout.get()); 1879e5c31af7Sopenharmony_ci 1880e5c31af7Sopenharmony_ci // Shader modules. 1881e5c31af7Sopenharmony_ci const auto vertModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u); 1882e5c31af7Sopenharmony_ci const auto writeModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag_write"), 0u); 1883e5c31af7Sopenharmony_ci const auto checkModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag_check"), 0u); 1884e5c31af7Sopenharmony_ci 1885e5c31af7Sopenharmony_ci const std::vector<vk::VkVertexInputBindingDescription> vertexBindings = 1886e5c31af7Sopenharmony_ci { 1887e5c31af7Sopenharmony_ci { 1888e5c31af7Sopenharmony_ci 0u, // deUint32 binding; 1889e5c31af7Sopenharmony_ci static_cast<deUint32>(sizeof(decltype(quadVertices)::value_type)), // deUint32 stride; 1890e5c31af7Sopenharmony_ci vk::VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; 1891e5c31af7Sopenharmony_ci }, 1892e5c31af7Sopenharmony_ci }; 1893e5c31af7Sopenharmony_ci 1894e5c31af7Sopenharmony_ci const std::vector<vk::VkVertexInputAttributeDescription> vertexAttributes = 1895e5c31af7Sopenharmony_ci { 1896e5c31af7Sopenharmony_ci { 1897e5c31af7Sopenharmony_ci 0u, // deUint32 location; 1898e5c31af7Sopenharmony_ci 0u, // deUint32 binding; 1899e5c31af7Sopenharmony_ci vk::VK_FORMAT_R32G32_SFLOAT, // VkFormat format; 1900e5c31af7Sopenharmony_ci 0u, // deUint32 offset; 1901e5c31af7Sopenharmony_ci }, 1902e5c31af7Sopenharmony_ci }; 1903e5c31af7Sopenharmony_ci 1904e5c31af7Sopenharmony_ci const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo = 1905e5c31af7Sopenharmony_ci { 1906e5c31af7Sopenharmony_ci vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 1907e5c31af7Sopenharmony_ci nullptr, // const void* pNext; 1908e5c31af7Sopenharmony_ci 0u, // VkPipelineVertexInputStateCreateFlags flags; 1909e5c31af7Sopenharmony_ci static_cast<deUint32>(vertexBindings.size()), // deUint32 vertexBindingDescriptionCount; 1910e5c31af7Sopenharmony_ci vertexBindings.data(), // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 1911e5c31af7Sopenharmony_ci static_cast<deUint32>(vertexAttributes.size()), // deUint32 vertexAttributeDescriptionCount; 1912e5c31af7Sopenharmony_ci vertexAttributes.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 1913e5c31af7Sopenharmony_ci }; 1914e5c31af7Sopenharmony_ci 1915e5c31af7Sopenharmony_ci const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo = 1916e5c31af7Sopenharmony_ci { 1917e5c31af7Sopenharmony_ci vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 1918e5c31af7Sopenharmony_ci nullptr, // const void* pNext; 1919e5c31af7Sopenharmony_ci 0u, // VkPipelineInputAssemblyStateCreateFlags flags; 1920e5c31af7Sopenharmony_ci vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology; 1921e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 primitiveRestartEnable; 1922e5c31af7Sopenharmony_ci }; 1923e5c31af7Sopenharmony_ci 1924e5c31af7Sopenharmony_ci const std::vector<VkViewport> viewport { vk::makeViewport(kImageExtent) }; 1925e5c31af7Sopenharmony_ci const std::vector<VkRect2D> scissor { vk::makeRect2D(kImageExtent) }; 1926e5c31af7Sopenharmony_ci 1927e5c31af7Sopenharmony_ci const vk::VkPipelineMultisampleStateCreateInfo multisampleInfo = 1928e5c31af7Sopenharmony_ci { 1929e5c31af7Sopenharmony_ci vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 1930e5c31af7Sopenharmony_ci nullptr, // const void* pNext; 1931e5c31af7Sopenharmony_ci 0u, // VkPipelineMultisampleStateCreateFlags flags; 1932e5c31af7Sopenharmony_ci m_params.sampleCount, // VkSampleCountFlagBits rasterizationSamples; 1933e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 sampleShadingEnable; 1934e5c31af7Sopenharmony_ci 1.0f, // float minSampleShading; 1935e5c31af7Sopenharmony_ci nullptr, // const VkSampleMask* pSampleMask; 1936e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 alphaToCoverageEnable; 1937e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 alphaToOneEnable; 1938e5c31af7Sopenharmony_ci }; 1939e5c31af7Sopenharmony_ci 1940e5c31af7Sopenharmony_ci const auto stencilState = vk::makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0xFFu, 0xFFu, 0u); 1941e5c31af7Sopenharmony_ci 1942e5c31af7Sopenharmony_ci const vk::VkPipelineDepthStencilStateCreateInfo depthStencilInfo = 1943e5c31af7Sopenharmony_ci { 1944e5c31af7Sopenharmony_ci vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 1945e5c31af7Sopenharmony_ci nullptr, // const void* pNext; 1946e5c31af7Sopenharmony_ci 0u, // VkPipelineDepthStencilStateCreateFlags flags; 1947e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 depthTestEnable; 1948e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 depthWriteEnable; 1949e5c31af7Sopenharmony_ci vk::VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp; 1950e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 depthBoundsTestEnable; 1951e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 stencilTestEnable; 1952e5c31af7Sopenharmony_ci stencilState, // VkStencilOpState front; 1953e5c31af7Sopenharmony_ci stencilState, // VkStencilOpState back; 1954e5c31af7Sopenharmony_ci 0.0f, // float minDepthBounds; 1955e5c31af7Sopenharmony_ci 1.0f, // float maxDepthBounds; 1956e5c31af7Sopenharmony_ci }; 1957e5c31af7Sopenharmony_ci 1958e5c31af7Sopenharmony_ci const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState = 1959e5c31af7Sopenharmony_ci { 1960e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 blendEnable; 1961e5c31af7Sopenharmony_ci vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor; 1962e5c31af7Sopenharmony_ci vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 1963e5c31af7Sopenharmony_ci vk::VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 1964e5c31af7Sopenharmony_ci vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor; 1965e5c31af7Sopenharmony_ci vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 1966e5c31af7Sopenharmony_ci vk::VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 1967e5c31af7Sopenharmony_ci ( // VkColorComponentFlags colorWriteMask; 1968e5c31af7Sopenharmony_ci vk::VK_COLOR_COMPONENT_R_BIT | 1969e5c31af7Sopenharmony_ci vk::VK_COLOR_COMPONENT_G_BIT | 1970e5c31af7Sopenharmony_ci vk::VK_COLOR_COMPONENT_B_BIT | 1971e5c31af7Sopenharmony_ci vk::VK_COLOR_COMPONENT_A_BIT ), 1972e5c31af7Sopenharmony_ci }; 1973e5c31af7Sopenharmony_ci 1974e5c31af7Sopenharmony_ci const vk::VkPipelineColorBlendStateCreateInfo colorBlendInfo = 1975e5c31af7Sopenharmony_ci { 1976e5c31af7Sopenharmony_ci vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 1977e5c31af7Sopenharmony_ci nullptr, // const void* pNext; 1978e5c31af7Sopenharmony_ci 0u, // VkPipelineColorBlendStateCreateFlags flags; 1979e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 logicOpEnable; 1980e5c31af7Sopenharmony_ci vk::VK_LOGIC_OP_NO_OP, // VkLogicOp logicOp; 1981e5c31af7Sopenharmony_ci 1u, // deUint32 attachmentCount; 1982e5c31af7Sopenharmony_ci &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 1983e5c31af7Sopenharmony_ci { .0f, .0f, .0f, .0f }, // float blendConstants[4]; 1984e5c31af7Sopenharmony_ci }; 1985e5c31af7Sopenharmony_ci 1986e5c31af7Sopenharmony_ci const vk::VkPipelineDynamicStateCreateInfo dynamicStateInfo = 1987e5c31af7Sopenharmony_ci { 1988e5c31af7Sopenharmony_ci vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType; 1989e5c31af7Sopenharmony_ci nullptr, // const void* pNext; 1990e5c31af7Sopenharmony_ci 0u, // VkPipelineDynamicStateCreateFlags flags; 1991e5c31af7Sopenharmony_ci 0u, // deUint32 dynamicStateCount; 1992e5c31af7Sopenharmony_ci nullptr, // const VkDynamicState* pDynamicStates; 1993e5c31af7Sopenharmony_ci }; 1994e5c31af7Sopenharmony_ci 1995e5c31af7Sopenharmony_ci // Pipeline for the first subpass. 1996e5c31af7Sopenharmony_ci vk::GraphicsPipelineWrapper firstSubpassPipeline(vki, vkd, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 1997e5c31af7Sopenharmony_ci firstSubpassPipeline.setDynamicState(&dynamicStateInfo) 1998e5c31af7Sopenharmony_ci .setDefaultRasterizationState() 1999e5c31af7Sopenharmony_ci .setupVertexInputState(&vertexInputInfo, &inputAssemblyInfo) 2000e5c31af7Sopenharmony_ci .setupPreRasterizationShaderState(viewport, scissor, emptyPipelineLayout, *renderPass, 0u, vertModule) 2001e5c31af7Sopenharmony_ci .setupFragmentShaderState(emptyPipelineLayout, *renderPass, 0u, writeModule, &depthStencilInfo, &multisampleInfo) 2002e5c31af7Sopenharmony_ci .setupFragmentOutputState(*renderPass, 0u, &colorBlendInfo, &multisampleInfo) 2003e5c31af7Sopenharmony_ci .setMonolithicPipelineLayout(emptyPipelineLayout) 2004e5c31af7Sopenharmony_ci .buildPipeline(); 2005e5c31af7Sopenharmony_ci 2006e5c31af7Sopenharmony_ci // Pipeline for the second subpass. 2007e5c31af7Sopenharmony_ci vk::GraphicsPipelineWrapper secondSubpassPipeline(vki, vkd, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 2008e5c31af7Sopenharmony_ci secondSubpassPipeline.setDynamicState(&dynamicStateInfo) 2009e5c31af7Sopenharmony_ci .setDefaultRasterizationState() 2010e5c31af7Sopenharmony_ci .setupVertexInputState(&vertexInputInfo, &inputAssemblyInfo) 2011e5c31af7Sopenharmony_ci .setupPreRasterizationShaderState(viewport, scissor, checkPipelineLayout, *renderPass, 1u, vertModule) 2012e5c31af7Sopenharmony_ci .setupFragmentShaderState(checkPipelineLayout, *renderPass, 1u, checkModule, &depthStencilInfo, &multisampleInfo) 2013e5c31af7Sopenharmony_ci .setupFragmentOutputState(*renderPass, 1u, &colorBlendInfo, &multisampleInfo) 2014e5c31af7Sopenharmony_ci .setMonolithicPipelineLayout(checkPipelineLayout) 2015e5c31af7Sopenharmony_ci .buildPipeline(); 2016e5c31af7Sopenharmony_ci 2017e5c31af7Sopenharmony_ci // Command pool and command buffer. 2018e5c31af7Sopenharmony_ci const auto cmdPool = vk::makeCommandPool(vkd, device, queueFamilyIndex); 2019e5c31af7Sopenharmony_ci const auto cmdBufferPtr = vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY); 2020e5c31af7Sopenharmony_ci const auto cmdBuffer = cmdBufferPtr.get(); 2021e5c31af7Sopenharmony_ci 2022e5c31af7Sopenharmony_ci // Update descriptor set. 2023e5c31af7Sopenharmony_ci vk::DescriptorSetUpdateBuilder updateBuilder; 2024e5c31af7Sopenharmony_ci const auto imageInfo = vk::makeDescriptorImageInfo(DE_NULL, colorImageView.get(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 2025e5c31af7Sopenharmony_ci const auto bufferInfo = vk::makeDescriptorBufferInfo(storageBuffer.get(), 0u, VK_WHOLE_SIZE); 2026e5c31af7Sopenharmony_ci updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfo); 2027e5c31af7Sopenharmony_ci updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo); 2028e5c31af7Sopenharmony_ci updateBuilder.update(vkd, device); 2029e5c31af7Sopenharmony_ci 2030e5c31af7Sopenharmony_ci // Output buffer pipeline barrier. 2031e5c31af7Sopenharmony_ci const auto bufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, storageBuffer.get(), 0ull, VK_WHOLE_SIZE); 2032e5c31af7Sopenharmony_ci 2033e5c31af7Sopenharmony_ci // Run pipelines. 2034e5c31af7Sopenharmony_ci vk::beginCommandBuffer(vkd, cmdBuffer); 2035e5c31af7Sopenharmony_ci 2036e5c31af7Sopenharmony_ci renderPass.begin(vkd, cmdBuffer, vk::makeRect2D(kImageExtent), WriteSampleMaskTestCase::kClearColor); 2037e5c31af7Sopenharmony_ci vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 2038e5c31af7Sopenharmony_ci firstSubpassPipeline.bind(cmdBuffer); 2039e5c31af7Sopenharmony_ci vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(quadVertices.size()), 1u, 0u, 0u); 2040e5c31af7Sopenharmony_ci 2041e5c31af7Sopenharmony_ci renderPass.nextSubpass(vkd, cmdBuffer, vk::VK_SUBPASS_CONTENTS_INLINE); 2042e5c31af7Sopenharmony_ci secondSubpassPipeline.bind(cmdBuffer); 2043e5c31af7Sopenharmony_ci vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, checkPipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr); 2044e5c31af7Sopenharmony_ci vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(quadVertices.size()), 1u, 0u, 0u); 2045e5c31af7Sopenharmony_ci 2046e5c31af7Sopenharmony_ci renderPass.end(vkd, cmdBuffer); 2047e5c31af7Sopenharmony_ci vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr); 2048e5c31af7Sopenharmony_ci vk::endCommandBuffer(vkd, cmdBuffer); 2049e5c31af7Sopenharmony_ci 2050e5c31af7Sopenharmony_ci vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer); 2051e5c31af7Sopenharmony_ci 2052e5c31af7Sopenharmony_ci // Check buffer contents. 2053e5c31af7Sopenharmony_ci auto& bufferAlloc = storageBuffer.getAllocation(); 2054e5c31af7Sopenharmony_ci const void* bufferPtr = bufferAlloc.getHostPtr(); 2055e5c31af7Sopenharmony_ci std::vector<deInt32> bufferContents (kBufferElems, 0); 2056e5c31af7Sopenharmony_ci 2057e5c31af7Sopenharmony_ci vk::invalidateAlloc(vkd, device, bufferAlloc); 2058e5c31af7Sopenharmony_ci deMemcpy(bufferContents.data(), bufferPtr, static_cast<size_t>(kBufferSize)); 2059e5c31af7Sopenharmony_ci 2060e5c31af7Sopenharmony_ci const auto sampleCount = static_cast<deUint32>(m_params.sampleCount); 2061e5c31af7Sopenharmony_ci const auto bpc = bitsPerCoord(sampleCount); 2062e5c31af7Sopenharmony_ci 2063e5c31af7Sopenharmony_ci for (deUint32 x = 0; x < kImageExtent.width; ++x) 2064e5c31af7Sopenharmony_ci for (deUint32 y = 0; y < kImageExtent.height; ++y) 2065e5c31af7Sopenharmony_ci { 2066e5c31af7Sopenharmony_ci // Samples on which we expect writes. 2067e5c31af7Sopenharmony_ci const deUint32 sampleMask = ((x << bpc) | y); 2068e5c31af7Sopenharmony_ci 2069e5c31af7Sopenharmony_ci // Starting location for the pixel sample values in the buffer. 2070e5c31af7Sopenharmony_ci const deUint32 pixelOffset = (y * kImageExtent.width + x) * sampleCount; 2071e5c31af7Sopenharmony_ci 2072e5c31af7Sopenharmony_ci for (deUint32 s = 0; s < sampleCount; ++s) 2073e5c31af7Sopenharmony_ci { 2074e5c31af7Sopenharmony_ci const deUint32 sampleIndex = pixelOffset + s; 2075e5c31af7Sopenharmony_ci const deInt32& value = bufferContents[sampleIndex]; 2076e5c31af7Sopenharmony_ci 2077e5c31af7Sopenharmony_ci if (value != 0 && value != 1) 2078e5c31af7Sopenharmony_ci { 2079e5c31af7Sopenharmony_ci // Garbage! 2080e5c31af7Sopenharmony_ci std::ostringstream msg; 2081e5c31af7Sopenharmony_ci msg << "Found garbage value " << value << " in buffer position " << sampleIndex << " (x=" << x << ", y=" << y << ", sample=" << s << ")"; 2082e5c31af7Sopenharmony_ci return tcu::TestStatus::fail(msg.str()); 2083e5c31af7Sopenharmony_ci } 2084e5c31af7Sopenharmony_ci 2085e5c31af7Sopenharmony_ci const deInt32 expected = (((sampleMask & (1u << s)) != 0u) ? 1 : 0); 2086e5c31af7Sopenharmony_ci if (value != expected) 2087e5c31af7Sopenharmony_ci { 2088e5c31af7Sopenharmony_ci std::ostringstream msg; 2089e5c31af7Sopenharmony_ci msg << "Read " << value << " while expecting " << expected << " in buffer position " << sampleIndex << " (x=" << x << ", y=" << y << ", sample=" << s << ")"; 2090e5c31af7Sopenharmony_ci return tcu::TestStatus::fail(msg.str()); 2091e5c31af7Sopenharmony_ci } 2092e5c31af7Sopenharmony_ci } 2093e5c31af7Sopenharmony_ci } 2094e5c31af7Sopenharmony_ci 2095e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Pass"); 2096e5c31af7Sopenharmony_ci} 2097e5c31af7Sopenharmony_ci 2098e5c31af7Sopenharmony_ci} // multisample 2099e5c31af7Sopenharmony_ci 2100e5c31af7Sopenharmony_citcu::TestCaseGroup* createMultisampleShaderBuiltInTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType) 2101e5c31af7Sopenharmony_ci{ 2102e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_shader_builtin")); 2103e5c31af7Sopenharmony_ci 2104e5c31af7Sopenharmony_ci const tcu::UVec3 imageSizes[] = 2105e5c31af7Sopenharmony_ci { 2106e5c31af7Sopenharmony_ci tcu::UVec3(128u, 128u, 1u), 2107e5c31af7Sopenharmony_ci tcu::UVec3(137u, 191u, 1u), 2108e5c31af7Sopenharmony_ci }; 2109e5c31af7Sopenharmony_ci 2110e5c31af7Sopenharmony_ci const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3)); 2111e5c31af7Sopenharmony_ci 2112e5c31af7Sopenharmony_ci const vk::VkSampleCountFlagBits samplesSetFull[] = 2113e5c31af7Sopenharmony_ci { 2114e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_2_BIT, 2115e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_4_BIT, 2116e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_8_BIT, 2117e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_16_BIT, 2118e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_32_BIT, 2119e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_64_BIT, 2120e5c31af7Sopenharmony_ci }; 2121e5c31af7Sopenharmony_ci 2122e5c31af7Sopenharmony_ci const deUint32 samplesSetFullCount = static_cast<deUint32>(sizeof(samplesSetFull) / sizeof(vk::VkSampleCountFlagBits)); 2123e5c31af7Sopenharmony_ci 2124e5c31af7Sopenharmony_ci testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleID> >(testCtx, "sample_id", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount)); 2125e5c31af7Sopenharmony_ci 2126e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> samplePositionGroup(new tcu::TestCaseGroup(testCtx, "sample_position")); 2127e5c31af7Sopenharmony_ci 2128e5c31af7Sopenharmony_ci samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosDistribution> >(testCtx, "distribution", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount)); 2129e5c31af7Sopenharmony_ci samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosCorrectness> > (testCtx, "correctness", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount)); 2130e5c31af7Sopenharmony_ci 2131e5c31af7Sopenharmony_ci testGroup->addChild(samplePositionGroup.release()); 2132e5c31af7Sopenharmony_ci 2133e5c31af7Sopenharmony_ci const vk::VkSampleCountFlagBits samplesSetReduced[] = 2134e5c31af7Sopenharmony_ci { 2135e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_2_BIT, 2136e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_4_BIT, 2137e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_8_BIT, 2138e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_16_BIT, 2139e5c31af7Sopenharmony_ci vk::VK_SAMPLE_COUNT_32_BIT, 2140e5c31af7Sopenharmony_ci }; 2141e5c31af7Sopenharmony_ci 2142e5c31af7Sopenharmony_ci const deUint32 samplesSetReducedCount = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(samplesSetReduced)); 2143e5c31af7Sopenharmony_ci 2144e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> sampleMaskGroup(new tcu::TestCaseGroup(testCtx, "sample_mask")); 2145e5c31af7Sopenharmony_ci 2146e5c31af7Sopenharmony_ci sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskPattern> > (testCtx, "pattern", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount)); 2147e5c31af7Sopenharmony_ci sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskBitCount> > (testCtx, "bit_count", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount)); 2148e5c31af7Sopenharmony_ci sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskBitCount> > (testCtx, "bit_count_0_5", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount, multisample::ComponentData{}, 0.5f)); 2149e5c31af7Sopenharmony_ci sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskCorrectBit> >(testCtx, "correct_bit", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount)); 2150e5c31af7Sopenharmony_ci sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskWrite> > (testCtx, "write", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount)); 2151e5c31af7Sopenharmony_ci 2152e5c31af7Sopenharmony_ci testGroup->addChild(sampleMaskGroup.release()); 2153e5c31af7Sopenharmony_ci 2154e5c31af7Sopenharmony_ci // Write image sample tests using a storage images (tests construct only compute pipeline). 2155e5c31af7Sopenharmony_ci if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) 2156e5c31af7Sopenharmony_ci { 2157e5c31af7Sopenharmony_ci // Test OpImageWrite with a sample ID 2158e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> imageWriteSampleGroup(new tcu::TestCaseGroup(testCtx, "image_write_sample")); 2159e5c31af7Sopenharmony_ci 2160e5c31af7Sopenharmony_ci for (auto count : multisample::kValidSquareSampleCounts) 2161e5c31af7Sopenharmony_ci { 2162e5c31af7Sopenharmony_ci if (count == vk::VK_SAMPLE_COUNT_1_BIT) 2163e5c31af7Sopenharmony_ci continue; 2164e5c31af7Sopenharmony_ci 2165e5c31af7Sopenharmony_ci multisample::WriteSampleParams params { pipelineConstructionType, static_cast<vk::VkSampleCountFlagBits>(count) }; 2166e5c31af7Sopenharmony_ci const auto countStr = de::toString(count); 2167e5c31af7Sopenharmony_ci imageWriteSampleGroup->addChild(new multisample::WriteSampleTest(testCtx, countStr + "_samples", params)); 2168e5c31af7Sopenharmony_ci } 2169e5c31af7Sopenharmony_ci 2170e5c31af7Sopenharmony_ci testGroup->addChild(imageWriteSampleGroup.release()); 2171e5c31af7Sopenharmony_ci } 2172e5c31af7Sopenharmony_ci 2173e5c31af7Sopenharmony_ci // Write to gl_SampleMask from the fragment shader. 2174e5c31af7Sopenharmony_ci { 2175e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> writeSampleMaskGroup(new tcu::TestCaseGroup(testCtx, "write_sample_mask")); 2176e5c31af7Sopenharmony_ci 2177e5c31af7Sopenharmony_ci for (auto count : multisample::kValidSquareSampleCounts) 2178e5c31af7Sopenharmony_ci { 2179e5c31af7Sopenharmony_ci multisample::WriteSampleMaskParams params { pipelineConstructionType, static_cast<vk::VkSampleCountFlagBits>(count) }; 2180e5c31af7Sopenharmony_ci const auto countStr = de::toString(count); 2181e5c31af7Sopenharmony_ci writeSampleMaskGroup->addChild(new multisample::WriteSampleMaskTestCase(testCtx, countStr + "_samples", params)); 2182e5c31af7Sopenharmony_ci } 2183e5c31af7Sopenharmony_ci 2184e5c31af7Sopenharmony_ci testGroup->addChild(writeSampleMaskGroup.release()); 2185e5c31af7Sopenharmony_ci } 2186e5c31af7Sopenharmony_ci 2187e5c31af7Sopenharmony_ci return testGroup.release(); 2188e5c31af7Sopenharmony_ci} 2189e5c31af7Sopenharmony_ci 2190e5c31af7Sopenharmony_ci} // pipeline 2191e5c31af7Sopenharmony_ci} // vkt 2192