17ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski/*------------------------------------------------------------------------
27ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * Vulkan Conformance Tests
37ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * ------------------------
47ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski *
57ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * Copyright (c) 2016 The Khronos Group Inc.
67ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * Copyright (c) 2016 The Android Open Source Project
77ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski *
87ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * Licensed under the Apache License, Version 2.0 (the "License");
97ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * you may not use this file except in compliance with the License.
107ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * You may obtain a copy of the License at
117ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski *
127ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski *      http://www.apache.org/licenses/LICENSE-2.0
137ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski *
147ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * Unless required by applicable law or agreed to in writing, software
157ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * distributed under the License is distributed on an "AS IS" BASIS,
167ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
177ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * See the License for the specific language governing permissions and
187ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * limitations under the License.
197ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski *
207ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski *//*!
217ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * \file
227ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski * \brief Multisampled image load/store Tests
237ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski *//*--------------------------------------------------------------------*/
247ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
257ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vktImageMultisampleLoadStoreTests.hpp"
267ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vktTestCaseUtil.hpp"
277ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vktImageTestsUtil.hpp"
287ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vktImageLoadStoreUtil.hpp"
297ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vktImageTexture.hpp"
307ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
317ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vkDefs.hpp"
327ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vkRef.hpp"
337ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vkRefUtil.hpp"
347ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vkPlatform.hpp"
357ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vkPrograms.hpp"
367ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vkMemUtil.hpp"
377ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vkBuilderUtil.hpp"
387ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vkQueryUtil.hpp"
397ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "vkImageUtil.hpp"
407ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
417ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "deUniquePtr.hpp"
427ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
437ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include "tcuTextureUtil.hpp"
44b5c2f56daa415384202d097073cd8cb5dfcf2408Pyry Haulos#include "tcuTestLog.hpp"
457ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
467ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include <string>
477ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski#include <vector>
487ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
497ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskinamespace vkt
507ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski{
517ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskinamespace image
527ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski{
537ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskinamespace
547ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski{
557ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskiusing namespace vk;
567ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskiusing de::MovePtr;
577ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskiusing de::UniquePtr;
587ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskiusing tcu::IVec3;
597ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
607ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskistatic const VkFormat CHECKSUM_IMAGE_FORMAT = VK_FORMAT_R32_SINT;
617ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
627ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskistruct CaseDef
637ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski{
647ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	Texture					texture;
657ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	VkFormat				format;
667ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	VkSampleCountFlagBits	numSamples;
677ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	bool					singleLayerBind;
687ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski};
697ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
707ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski//  Multisampled storage image test.
717ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski//
727ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski//  Pass 1: Write a slightly different color pattern per-sample to the whole image.
737ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski//  Pass 2: Read samples of the same image and check if color values are in the expected range.
747ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski//          Write back results as a checksum image and verify them on the host.
757ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski//  Each checksum image pixel should contain an integer equal to the number of samples.
767ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
777ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskivoid initPrograms (SourceCollections& programCollection, const  CaseDef caseDef)
787ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski{
797ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const int			dimension			= (caseDef.singleLayerBind ? caseDef.texture.layerDimension() : caseDef.texture.dimension());
807ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const std::string	texelCoordStr		= (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
817ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
827ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const ImageType		usedImageType		= (caseDef.singleLayerBind ? getImageTypeForSingleLayer(caseDef.texture.type()) : caseDef.texture.type());
837ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const std::string	formatQualifierStr	= getShaderImageFormatQualifier(mapVkFormat(caseDef.format));
847ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const std::string	msImageTypeStr		= getShaderImageType(mapVkFormat(caseDef.format), usedImageType, (caseDef.texture.numSamples() > 1));
857ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
867ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const std::string	xMax				= de::toString(caseDef.texture.size().x() - 1);
877ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const std::string	yMax				= de::toString(caseDef.texture.size().y() - 1);
887ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const std::string	signednessPrefix	= isUintFormat(caseDef.format) ? "u" : isIntFormat(caseDef.format) ? "i" : "";
897ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const std::string	gvec4Expr			= signednessPrefix + "vec4";
907ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const int			numColorComponents	= tcu::getNumUsedChannels(mapVkFormat(caseDef.format).order);
917ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
927ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const float			storeColorScale		= computeStoreColorScale(caseDef.format, caseDef.texture.size());
937ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const float			storeColorBias		= computeStoreColorBias(caseDef.format);
947ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	DE_ASSERT(colorScaleAndBiasAreValid(caseDef.format, storeColorScale, storeColorBias));
957ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
967ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const std::string	colorScaleExpr		= (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
977ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski											+ (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
987ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const std::string	colorExpr			=
997ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		gvec4Expr + "("
1007ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		+                           "gx^gy^gz^(sampleNdx >> 5)^(sampleNdx & 31), "		// we "split" sampleNdx to keep this value in [0, 31] range for numSamples = 64 case
1017ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		+ (numColorComponents > 1 ? "(" + xMax + "-gx)^gy^gz, "              : "0, ")
1027ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		+ (numColorComponents > 2 ? "gx^(" + yMax + "-gy)^gz, "              : "0, ")
1037ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		+ (numColorComponents > 3 ? "(" + xMax + "-gx)^(" + yMax + "-gy)^gz" : "1")
1047ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		+ ")" + colorScaleExpr;
1057ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1067ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	// Store shader
1077ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
1087ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		std::ostringstream src;
1097ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1107ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "\n"
1117ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "layout(local_size_x = 1) in;\n"
1127ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "layout(set = 0, binding = 1, " << formatQualifierStr << ") writeonly uniform " << msImageTypeStr << " u_msImage;\n";
1137ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1147ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		if (caseDef.singleLayerBind)
1157ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			src << "layout(set = 0, binding = 0) readonly uniform Constants {\n"
1167ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				<< "    int u_layerNdx;\n"
1177ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				<< "};\n";
1187ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1197ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		src << "\n"
1207ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "void main (void)\n"
1217ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "{\n"
1227ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "    int gx = int(gl_GlobalInvocationID.x);\n"
1237ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "    int gy = int(gl_GlobalInvocationID.y);\n"
1247ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "    int gz = " << (caseDef.singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
1257ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "\n"
1267ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "    for (int sampleNdx = 0; sampleNdx < " << caseDef.texture.numSamples() <<"; ++sampleNdx) {\n"
1277ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "        imageStore(u_msImage, " << texelCoordStr << ", sampleNdx, " << colorExpr << ");\n"
1287ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "    }\n"
1297ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "}\n";
1307ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1317ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		programCollection.glslSources.add("comp_store") << glu::ComputeSource(src.str());
1327ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
1337ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1347ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	// Load shader
1357ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
1367ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const tcu::TextureFormat	checksumFormat			= mapVkFormat(CHECKSUM_IMAGE_FORMAT);
1377ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const std::string			checksumImageTypeStr	= getShaderImageType(checksumFormat, usedImageType);
1387ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const bool					useExactCompare			= isIntegerFormat(caseDef.format);
1397ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1407ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		std::ostringstream src;
1417ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1427ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "\n"
1437ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "layout(local_size_x = 1) in;\n"
1447ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "layout(set = 0, binding = 1, " << formatQualifierStr << ") readonly  uniform " << msImageTypeStr << " u_msImage;\n"
1457ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "layout(set = 0, binding = 2, " << getShaderImageFormatQualifier(checksumFormat) << ") writeonly uniform " << checksumImageTypeStr << " u_checksumImage;\n";
1467ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1477ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		if (caseDef.singleLayerBind)
1487ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			src << "layout(set = 0, binding = 0) readonly uniform Constants {\n"
1497ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				<< "    int u_layerNdx;\n"
1507ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				<< "};\n";
1517ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1527ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		src << "\n"
1537ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "void main (void)\n"
1547ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "{\n"
1557ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "    int gx = int(gl_GlobalInvocationID.x);\n"
1567ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "    int gy = int(gl_GlobalInvocationID.y);\n"
1577ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "    int gz = " << (caseDef.singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
1587ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "\n"
1597ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "    int checksum = 0;\n"
1607ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "    for (int sampleNdx = 0; sampleNdx < " << caseDef.texture.numSamples() <<"; ++sampleNdx) {\n"
1617ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "        " << gvec4Expr << " color = imageLoad(u_msImage, " << texelCoordStr << ", sampleNdx);\n";
1627ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1637ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		if (useExactCompare)
1647ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			src << "        if (color == " << colorExpr << ")\n"
1657ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				<< "            ++checksum;\n";
1667ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		else
1677ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			src << "        " << gvec4Expr << " diff  = abs(abs(color) - abs(" << colorExpr << "));\n"
1687ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				<< "        if (all(lessThan(diff, " << gvec4Expr << "(0.02))))\n"
1697ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				<< "            ++checksum;\n";
1707ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1717ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		src << "    }\n"
1727ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "\n"
1737ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "    imageStore(u_checksumImage, " << texelCoordStr << ", ivec4(checksum));\n"
1747ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			<< "}\n";
1757ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1767ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		programCollection.glslSources.add("comp_load") << glu::ComputeSource(src.str());
1777ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
1787ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski}
1797ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1807ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskivoid checkRequirements (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const CaseDef& caseDef)
1817ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski{
1827ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	VkPhysicalDeviceFeatures	features;
1837ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	vki.getPhysicalDeviceFeatures(physDevice, &features);
1847ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1857ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	if (!features.shaderStorageImageMultisample)
1867ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		TCU_THROW(NotSupportedError, "Multisampled storage images are not supported");
1877ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1887ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	VkImageFormatProperties		imageFormatProperties;
1897ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const VkResult				imageFormatResult		= vki.getPhysicalDeviceImageFormatProperties(
1907ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		physDevice, caseDef.format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_STORAGE_BIT, (VkImageCreateFlags)0, &imageFormatProperties);
1917ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1927ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	if (imageFormatResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
1937ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		TCU_THROW(NotSupportedError, "Format is not supported");
1947ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1957ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	if ((imageFormatProperties.sampleCounts & caseDef.numSamples) != caseDef.numSamples)
1967ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		TCU_THROW(NotSupportedError, "Requested sample count is not supported");
1977ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski}
1987ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
1997ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski//! Helper function to deal with per-layer resources.
2007ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskivoid insertImageViews (const DeviceInterface& vk, const VkDevice device, const CaseDef& caseDef, const VkFormat format, const VkImage image, std::vector<SharedVkImageView>* const pOutImageViews)
2017ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski{
2027ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	if (caseDef.singleLayerBind)
2037ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
2047ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		pOutImageViews->clear();
2057ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		pOutImageViews->resize(caseDef.texture.numLayers());
2067ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		for (int layerNdx = 0; layerNdx < caseDef.texture.numLayers(); ++layerNdx)
2077ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		{
2087ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			(*pOutImageViews)[layerNdx] = makeVkSharedPtr(makeImageView(
2097ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				vk, device, image, mapImageViewType(getImageTypeForSingleLayer(caseDef.texture.type())), format,
2107ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)));
2117ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		}
2127ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
2137ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	else // bind all layers at once
2147ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
2157ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		pOutImageViews->clear();
2167ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		pOutImageViews->resize(1);
2177ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		(*pOutImageViews)[0] = makeVkSharedPtr(makeImageView(
2187ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			vk, device, image, mapImageViewType(caseDef.texture.type()), format,
2197ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, caseDef.texture.numLayers())));
2207ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
2217ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski}
2227ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2237ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski//! Helper function to deal with per-layer resources.
2247ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskivoid insertDescriptorSets (const DeviceInterface& vk, const VkDevice device, const CaseDef& caseDef, const VkDescriptorPool descriptorPool, const VkDescriptorSetLayout descriptorSetLayout, std::vector<SharedVkDescriptorSet>* const pOutDescriptorSets)
2257ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski{
2267ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	if (caseDef.singleLayerBind)
2277ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
2287ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		pOutDescriptorSets->clear();
2297ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		pOutDescriptorSets->resize(caseDef.texture.numLayers());
2307ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		for (int layerNdx = 0; layerNdx < caseDef.texture.numLayers(); ++layerNdx)
2317ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			(*pOutDescriptorSets)[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout));
2327ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
2337ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	else // bind all layers at once
2347ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
2357ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		pOutDescriptorSets->clear();
2367ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		pOutDescriptorSets->resize(1);
2377ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		(*pOutDescriptorSets)[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout));
2387ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
2397ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski}
2407ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2417ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskitcu::TestStatus test (Context& context, const CaseDef caseDef)
2427ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski{
2437ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const InstanceInterface&	vki					= context.getInstanceInterface();
2447ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const VkPhysicalDevice		physDevice			= context.getPhysicalDevice();
2457ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const DeviceInterface&		vk					= context.getDeviceInterface();
2467ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const VkDevice				device				= context.getDevice();
2477ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const VkQueue				queue				= context.getUniversalQueue();
2487ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
2497ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	Allocator&					allocator			= context.getDefaultAllocator();
2507ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2517ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	checkRequirements(vki, physDevice, caseDef);
2527ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2537ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	// Images
2547ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2557ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const UniquePtr<Image> msImage(new Image(
2567ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		vk, device, allocator, makeImageCreateInfo(caseDef.texture, caseDef.format, VK_IMAGE_USAGE_STORAGE_BIT, 0u), MemoryRequirement::Any));
2577ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2587ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const UniquePtr<Image> checksumImage(new Image(
2597ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		vk, device, allocator,
2607ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		makeImageCreateInfo(Texture(caseDef.texture, 1), CHECKSUM_IMAGE_FORMAT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
2617ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		MemoryRequirement::Any));
2627ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2637ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	// Buffer used to pass constants to the shader.
2647ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2657ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const int			numLayers					= caseDef.texture.numLayers();
2667ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const VkDeviceSize	bufferChunkSize				= getOptimalUniformBufferChunkSize(vki, physDevice, sizeof(deInt32));
2677ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const VkDeviceSize	constantsBufferSizeBytes	= numLayers * bufferChunkSize;
2687ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	UniquePtr<Buffer>	constantsBuffer				(new Buffer(vk, device, allocator, makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
2697ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski													 MemoryRequirement::HostVisible));
2707ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2717ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
2727ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const Allocation&	alloc	= constantsBuffer->getAllocation();
2737ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		deUint8* const		basePtr = static_cast<deUint8*>(alloc.getHostPtr());
2747ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2757ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
2767ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2777ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
2787ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		{
2797ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			deInt32* const valuePtr = reinterpret_cast<deInt32*>(basePtr + layerNdx * bufferChunkSize);
2807ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			*valuePtr = layerNdx;
2817ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		}
2827ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2837ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), constantsBufferSizeBytes);
2847ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
2857ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2867ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const VkDeviceSize	resultBufferSizeBytes	= getImageSizeBytes(caseDef.texture.size(), CHECKSUM_IMAGE_FORMAT);
2877ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	UniquePtr<Buffer>	resultBuffer			(new Buffer(vk, device, allocator, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT),
2887ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski												 MemoryRequirement::HostVisible));
2897ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2907ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
2917ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const Allocation& alloc = resultBuffer->getAllocation();
2927ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(resultBufferSizeBytes));
2937ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes);
2947ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
2957ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2967ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	// Descriptors
2977ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
2987ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
2997ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
3007ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
3017ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
3027ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		.build(vk, device));
3037ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3047ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
3057ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
3067ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
3077ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
3087ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers));
3097ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3107ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	std::vector<SharedVkDescriptorSet>	allDescriptorSets;
3117ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	std::vector<SharedVkImageView>		allMultisampledImageViews;
3127ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	std::vector<SharedVkImageView>		allChecksumImageViews;
3137ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3147ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	insertDescriptorSets(vk, device, caseDef, *descriptorPool, *descriptorSetLayout, &allDescriptorSets);
3157ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	insertImageViews	(vk, device, caseDef, caseDef.format, **msImage, &allMultisampledImageViews);
3167ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	insertImageViews	(vk, device, caseDef, CHECKSUM_IMAGE_FORMAT, **checksumImage, &allChecksumImageViews);
3177ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3187ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	// Prepare commands
3197ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
32055dd4426673bd260dde56addcfea802f21c31304Mika Isojärvi	const Unique<VkPipelineLayout>	pipelineLayout	(makePipelineLayout(vk, device, *descriptorSetLayout));
32155dd4426673bd260dde56addcfea802f21c31304Mika Isojärvi	const Unique<VkCommandPool>		cmdPool			(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
32255dd4426673bd260dde56addcfea802f21c31304Mika Isojärvi	const Unique<VkCommandBuffer>	cmdBuffer		(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3237ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3247ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const tcu::IVec3				workSize				= (caseDef.singleLayerBind ? caseDef.texture.layerSize() : caseDef.texture.size());
3257ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const int						loopNumLayers			= (caseDef.singleLayerBind ? numLayers : 1);
3267ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const VkImageSubresourceRange	subresourceAllLayers	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, caseDef.texture.numLayers());
3277ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3287ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	// Pass 1: Write MS image
3297ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
3307ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const Unique<VkShaderModule>	shaderModule	(createShaderModule	(vk, device, context.getBinaryCollection().get("comp_store"), 0));
3317ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const Unique<VkPipeline>		pipeline		(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
3327ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3337ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		beginCommandBuffer(vk, *cmdBuffer);
3347ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
3357ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3367ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		{
3377ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const VkImageMemoryBarrier barriers[] =
3387ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			{
3397ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				makeImageMemoryBarrier((VkAccessFlags)0, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **msImage, subresourceAllLayers),
3407ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				makeImageMemoryBarrier((VkAccessFlags)0, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **checksumImage, subresourceAllLayers),
3417ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			};
3427ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3437ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0,
3447ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
3457ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		}
3467ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3477ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
3487ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		{
3497ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const VkDescriptorSet			descriptorSet					= **allDescriptorSets[layerNdx];
3507ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const VkDescriptorImageInfo		descriptorMultiImageInfo		= makeDescriptorImageInfo(DE_NULL, **allMultisampledImageViews[layerNdx], VK_IMAGE_LAYOUT_GENERAL);
3517ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const VkDescriptorBufferInfo	descriptorConstantsBufferInfo	= makeDescriptorBufferInfo(constantsBuffer->get(), layerNdx*bufferChunkSize, bufferChunkSize);
3527ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3537ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			DescriptorSetUpdateBuilder()
3547ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
3557ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorMultiImageInfo)
3567ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				.update(vk, device);
3577ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3587ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
3597ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
3607ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		}
3617ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3627ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		endCommandBuffer(vk, *cmdBuffer);
3637ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3647ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
3657ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3667ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	// Pass 2: "Resolve" MS image in compute shader
3677ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
3687ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const Unique<VkShaderModule>	shaderModule	(createShaderModule	(vk, device, context.getBinaryCollection().get("comp_load"), 0));
3697ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const Unique<VkPipeline>		pipeline		(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
3707ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3717ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		beginCommandBuffer(vk, *cmdBuffer);
3727ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
3737ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3747ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		{
3757ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const VkImageMemoryBarrier barriers[] =
3767ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			{
3777ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, **msImage, subresourceAllLayers),
3787ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			};
3797ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3807ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0,
3817ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
3827ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		}
3837ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3847ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
3857ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		{
3867ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const VkDescriptorSet			descriptorSet					= **allDescriptorSets[layerNdx];
3877ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const VkDescriptorImageInfo		descriptorMultiImageInfo		= makeDescriptorImageInfo(DE_NULL, **allMultisampledImageViews[layerNdx], VK_IMAGE_LAYOUT_GENERAL);
3887ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const VkDescriptorImageInfo		descriptorChecksumImageInfo		= makeDescriptorImageInfo(DE_NULL, **allChecksumImageViews[layerNdx], VK_IMAGE_LAYOUT_GENERAL);
3897ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const VkDescriptorBufferInfo	descriptorConstantsBufferInfo	= makeDescriptorBufferInfo(constantsBuffer->get(), layerNdx*bufferChunkSize, bufferChunkSize);
3907ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3917ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			DescriptorSetUpdateBuilder()
3927ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
3937ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorMultiImageInfo)
3947ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorChecksumImageInfo)
3957ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				.update(vk, device);
3967ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
3977ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
3987ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
3997ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		}
4007ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4017ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		endCommandBuffer(vk, *cmdBuffer);
4027ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4037ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
4047ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4057ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	// Retrieve result
4067ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
4077ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		beginCommandBuffer(vk, *cmdBuffer);
4087ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4097ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		{
4107ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const VkImageMemoryBarrier barriers[] =
4117ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			{
4127ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **checksumImage, subresourceAllLayers),
4137ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			};
4147ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
4157ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
4167ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		}
4177ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		{
4187ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(caseDef.texture.layerSize()), caseDef.texture.numLayers());
4197ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			vk.cmdCopyImageToBuffer(*cmdBuffer, **checksumImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **resultBuffer, 1u, &copyRegion);
4207ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		}
4217ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		{
4227ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const VkBufferMemoryBarrier barriers[] =
4237ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			{
4247ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, **resultBuffer, 0ull, resultBufferSizeBytes),
4257ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			};
4267ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
4277ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, 0u, DE_NULL);
4287ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		}
4297ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4307ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		endCommandBuffer(vk, *cmdBuffer);
4317ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4327ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
4337ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4347ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	// Verify
4357ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
4367ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const Allocation& alloc = resultBuffer->getAllocation();
4377ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes);
4387ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4397ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const IVec3		imageSize			= caseDef.texture.size();
4407ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const deInt32*	pDataPtr			= static_cast<deInt32*>(alloc.getHostPtr());
4417ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const deInt32	expectedChecksum	= caseDef.texture.numSamples();
4427ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4437ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		for (int layer = 0; layer < imageSize.z(); ++layer)
4447ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		for (int y = 0; y < imageSize.y(); ++y)
4457ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		for (int x = 0; x < imageSize.x(); ++x)
4467ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		{
4477ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			if (*pDataPtr != expectedChecksum)
4487ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			{
4497ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				context.getTestContext().getLog()
4507ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski					<< tcu::TestLog::Message << "Some sample colors were incorrect at (x, y, layer) = (" << x << ", " << y << ", " << layer << ")"	<< tcu::TestLog::EndMessage
4517ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski					<< tcu::TestLog::Message << "Checksum value is " << *pDataPtr << " but expected " << expectedChecksum << tcu::TestLog::EndMessage;
4527ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4537ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				return tcu::TestStatus::fail("Some sample colors were incorrect");
4547ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			}
4557ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			++pDataPtr;
4567ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		}
4577ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4587ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		return tcu::TestStatus::pass("OK");
4597ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
4607ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski}
4617ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4627ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski} // anonymous ns
4637ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4647ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowskitcu::TestCaseGroup* createImageMultisampleLoadStoreTests (tcu::TestContext& testCtx)
4657ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski{
4667ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	const Texture textures[] =
4677ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
4687ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		// \note Shader code is tweaked to work with image size of 32, take a look if this needs to be modified.
4697ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		Texture(IMAGE_TYPE_2D,			tcu::IVec3(32,	32,	1),		1),
4707ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		Texture(IMAGE_TYPE_2D_ARRAY,	tcu::IVec3(32,	32,	1),		4),
4717ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	};
4727ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4737ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	static const VkFormat formats[] =
4747ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
4757ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R32G32B32A32_SFLOAT,
4767ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R16G16B16A16_SFLOAT,
4777ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R32_SFLOAT,
4787ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4797ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R32G32B32A32_UINT,
4807ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R16G16B16A16_UINT,
4817ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R8G8B8A8_UINT,
4827ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R32_UINT,
4837ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4847ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R32G32B32A32_SINT,
4857ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R16G16B16A16_SINT,
4867ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R8G8B8A8_SINT,
4877ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R32_SINT,
4887ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4897ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R8G8B8A8_UNORM,
4907ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4917ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_FORMAT_R8G8B8A8_SNORM,
4927ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	};
4937ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
4947ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	static const VkSampleCountFlagBits samples[] =
4957ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
4967ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_SAMPLE_COUNT_2_BIT,
4977ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_SAMPLE_COUNT_4_BIT,
4987ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_SAMPLE_COUNT_8_BIT,
4997ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_SAMPLE_COUNT_16_BIT,
5007ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_SAMPLE_COUNT_32_BIT,
5017ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		VK_SAMPLE_COUNT_64_BIT,
5027ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	};
5037ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
5047ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store_multisample", "Multisampled image store and load"));
5057ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
5067ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	for (int baseTextureNdx = 0; baseTextureNdx < DE_LENGTH_OF_ARRAY(textures); ++baseTextureNdx)
5077ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	{
5087ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const Texture&				baseTexture			= textures[baseTextureNdx];
5097ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		MovePtr<tcu::TestCaseGroup>	imageViewGroup		(new tcu::TestCaseGroup(testCtx, getImageTypeName(baseTexture.type()).c_str(), ""));
5107ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		const int					numLayerBindModes	= (baseTexture.numLayers() == 1 ? 1 : 2);
5117ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
5127ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
5137ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		for (int layerBindMode = 0; layerBindMode < numLayerBindModes; ++layerBindMode)
5147ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		{
5157ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const bool					singleLayerBind	= (layerBindMode != 0);
5167ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			const std::string			formatGroupName	= getFormatShortString(formats[formatNdx]) + (singleLayerBind ? "_single_layer" : "");
5177ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			MovePtr<tcu::TestCaseGroup>	formatGroup		(new tcu::TestCaseGroup(testCtx, formatGroupName.c_str(), ""));
5187ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
5197ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
5207ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			{
5217ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				const std::string	samplesCaseName = "samples_" + de::toString(samples[samplesNdx]);
5227ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
5237ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				const CaseDef		caseDef =
5247ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				{
5257ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski					Texture(baseTexture, samples[samplesNdx]),
5267ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski					formats[formatNdx],
5277ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski					samples[samplesNdx],
5287ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski					singleLayerBind,
5297ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				};
5307ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
5317ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski				addFunctionCaseWithPrograms(formatGroup.get(), samplesCaseName, "", initPrograms, test, caseDef);
5327ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			}
5337ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski			imageViewGroup->addChild(formatGroup.release());
5347ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		}
5357ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski		testGroup->addChild(imageViewGroup.release());
5367ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	}
5377ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
5387ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski	return testGroup.release();
5397ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski}
5407ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski
5417ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski} // image
5427ac9a1f266eb171fa0eb411c300d2122f578a3a6Maciej Jesionowski} // vkt
543