169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning/*------------------------------------------------------------------------
269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * Vulkan Conformance Tests
369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * ------------------------
469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning *
569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * Copyright (c) 2017 The Khronos Group Inc.
669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * Copyright (c) 2017 Codeplay Software Ltd.
769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning *
869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * Licensed under the Apache License, Version 2.0 (the "License");
969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * you may not use this file except in compliance with the License.
1069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * You may obtain a copy of the License at
1169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning *
1269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning *      http://www.apache.org/licenses/LICENSE-2.0
1369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning *
1469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * Unless required by applicable law or agreed to in writing, software
1569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * distributed under the License is distributed on an "AS IS" BASIS,
1669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * See the License for the specific language governing permissions and
1869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * limitations under the License.
1969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning *
2069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning */ /*!
2169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * \file
2269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning * \brief Subgroups Tests
2369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning */ /*--------------------------------------------------------------------*/
2469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
2569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning#include "vktSubgroupsQuadTests.hpp"
2669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning#include "vktSubgroupsTestsUtils.hpp"
2769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
2869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning#include <string>
2969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning#include <vector>
3069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
3169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningusing namespace tcu;
3269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningusing namespace std;
3369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningusing namespace vk;
3469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningusing namespace vkt;
3569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
3669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningnamespace
3769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
3869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningenum OpType
3969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
4069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	OPTYPE_QUAD_BROADCAST = 0,
4169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	OPTYPE_QUAD_SWAP_HORIZONTAL,
4269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	OPTYPE_QUAD_SWAP_VERTICAL,
4369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	OPTYPE_QUAD_SWAP_DIAGONAL,
4469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	OPTYPE_LAST
4569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning};
4669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
4769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningstatic bool checkVertexPipelineStages(std::vector<const void*> datas,
4869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning									  deUint32 width, deUint32)
4969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
5069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32* data =
5169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		reinterpret_cast<const deUint32*>(datas[0]);
5269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 x = 0; x < width; ++x)
5369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
5469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		deUint32 val = data[x];
5569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
5669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (0x1 != val)
5769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
5869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return false;
5969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
6069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
6169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
6269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return true;
6369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
6469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
6569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningstatic bool checkFragment(std::vector<const void*> datas,
6669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						  deUint32 width, deUint32 height, deUint32)
6769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
6869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32* data =
6969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		reinterpret_cast<const deUint32*>(datas[0]);
7069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 x = 0; x < width; ++x)
7169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
7269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		for (deUint32 y = 0; y < height; ++y)
7369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
7469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			deUint32 val = data[x * height + y];
7569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
7669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			if (0x1 != val)
7769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			{
7869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				return false;
7969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			}
8069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
8169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
8269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
8369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return true;
8469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
8569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
8669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningstatic bool checkCompute(std::vector<const void*> datas,
8769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
8869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						 deUint32)
8969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
9069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32* data =
9169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		reinterpret_cast<const deUint32*>(datas[0]);
9269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
9369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 nX = 0; nX < numWorkgroups[0]; ++nX)
9469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
9569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		for (deUint32 nY = 0; nY < numWorkgroups[1]; ++nY)
9669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
9769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			for (deUint32 nZ = 0; nZ < numWorkgroups[2]; ++nZ)
9869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			{
9969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				for (deUint32 lX = 0; lX < localSize[0]; ++lX)
10069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				{
10169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					for (deUint32 lY = 0; lY < localSize[1]; ++lY)
10269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					{
10369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						for (deUint32 lZ = 0; lZ < localSize[2];
10469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								++lZ)
10569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						{
10669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationX =
10769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nX * localSize[0] + lX;
10869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationY =
10969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nY * localSize[1] + lY;
11069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationZ =
11169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nZ * localSize[2] + lZ;
11269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
11369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalSizeX =
11469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								numWorkgroups[0] * localSize[0];
11569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalSizeY =
11669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								numWorkgroups[1] * localSize[1];
11769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
11869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 offset =
11969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								globalSizeX *
12069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								((globalSizeY *
12169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								  globalInvocationZ) +
12269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								 globalInvocationY) +
12369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								globalInvocationX;
12469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
12569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							if (0x1 != data[offset])
12669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							{
12769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								return false;
12869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							}
12969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						}
13069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					}
13169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				}
13269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			}
13369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
13469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
13569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
13669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return true;
13769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
13869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
13969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningstd::string getOpTypeName(int opType)
14069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
14169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	switch (opType)
14269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
14369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		default:
14469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			DE_FATAL("Unsupported op type");
14569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		case OPTYPE_QUAD_BROADCAST:
14669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return "subgroupQuadBroadcast";
14769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		case OPTYPE_QUAD_SWAP_HORIZONTAL:
14869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return "subgroupQuadSwapHorizontal";
14969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		case OPTYPE_QUAD_SWAP_VERTICAL:
15069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return "subgroupQuadSwapVertical";
15169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		case OPTYPE_QUAD_SWAP_DIAGONAL:
15269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return "subgroupQuadSwapDiagonal";
15369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
15469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
15569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
15669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningstruct CaseDefinition
15769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
15858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	int					opType;
15958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	VkShaderStageFlags	shaderStage;
16058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	VkFormat			format;
16158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	int					direction;
16258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	bool				noSSBO;
16369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning};
16469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
16558319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwavoid initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
16658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa{
16758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	std::string swapTable[OPTYPE_LAST];
16858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	swapTable[OPTYPE_QUAD_BROADCAST] = "";
16958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	swapTable[OPTYPE_QUAD_SWAP_HORIZONTAL] = "  const uint swapTable[4] = {1, 0, 3, 2};\n";
17058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	swapTable[OPTYPE_QUAD_SWAP_VERTICAL] = "  const uint swapTable[4] = {2, 3, 0, 1};\n";
17158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	swapTable[OPTYPE_QUAD_SWAP_DIAGONAL] = "  const uint swapTable[4] = {3, 2, 1, 0};\n";
17258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
17358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
17458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	{
17558319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		std::ostringstream	src;
17658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		std::ostringstream	fragmentSrc;
17758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
17858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		src << "#version 450\n"
17958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "#extension GL_KHR_shader_subgroup_quad: enable\n"
18058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
18158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "layout(location = 0) in highp vec4 in_position;\n"
18258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "layout(location = 0) out float result;\n"
18358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "layout(set = 0, binding = 0) uniform Buffer1\n"
18458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "{\n"
18558319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
18658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "};\n"
18758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "\n"
18858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "void main (void)\n"
18958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "{\n"
19058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "  uvec4 mask = subgroupBallot(true);\n"
19158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< swapTable[caseDef.opType];
19258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
19358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
19458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		{
19558319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
19658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa				<< getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
19758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
19858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		}
19958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		else
20058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		{
20158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
20258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa				<< getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
20358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
20458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		}
20558319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
20658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		src << "  if (subgroupBallotBitExtract(mask, otherID))\n"
20758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "  {\n"
20858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "    result = (op == data[otherID]) ? 1.0f : 0.0f;\n"
20958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "  }\n"
21058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "  else\n"
21158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "  {\n"
21258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "    result = 1.0f; // Invocation we read from was inactive, so we can't verify results!\n"
21358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "  }\n"
21458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "  gl_Position = in_position;\n"
21504cbcfca9460cb4bf54daf3911a40533c2583455Graeme Leese			<< "  gl_PointSize = 1.0f;\n"
21658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "}\n";
21758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
218ef086961c26f3bee5c08531a177926bf7fb8b27aAlexander Galazin		programCollection.glslSources.add("vert") << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
21958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
22058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		fragmentSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
22158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "layout(location = 0) in float result;\n"
22258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "layout(location = 0) out uint out_color;\n"
22358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "void main()\n"
22458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<<"{\n"
22558319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "	out_color = uint(result);\n"
22658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "}\n";
22758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
228ef086961c26f3bee5c08531a177926bf7fb8b27aAlexander Galazin		programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentSrc.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
22958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	}
23058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	else
23158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	{
23258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		DE_FATAL("Unsupported shader stage");
23358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	}
23458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa}
23558319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
23669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningvoid initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
23769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
23869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	std::string swapTable[OPTYPE_LAST];
23969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	swapTable[OPTYPE_QUAD_BROADCAST] = "";
24069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	swapTable[OPTYPE_QUAD_SWAP_HORIZONTAL] = "  const uint swapTable[4] = {1, 0, 3, 2};\n";
24169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	swapTable[OPTYPE_QUAD_SWAP_VERTICAL] = "  const uint swapTable[4] = {2, 3, 0, 1};\n";
24269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	swapTable[OPTYPE_QUAD_SWAP_DIAGONAL] = "  const uint swapTable[4] = {3, 2, 1, 0};\n";
24369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
24469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
24569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
24669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		std::ostringstream src;
24769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
24869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "#version 450\n"
24969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_quad: enable\n"
25069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
25169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout (local_size_x_id = 0, local_size_y_id = 1, "
25269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			"local_size_z_id = 2) in;\n"
25369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
25469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
25569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uint result[];\n"
25669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
25769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
25869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
25969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[];\n"
26069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
26169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "\n"
26269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "void main (void)\n"
26369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
26469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
26569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  highp uint offset = globalSize.x * ((globalSize.y * "
26669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			"gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
26769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			"gl_GlobalInvocationID.x;\n"
26869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uvec4 mask = subgroupBallot(true);\n"
26969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< swapTable[caseDef.opType];
27069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
27169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
27269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
27369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
27469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
27569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
27669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
27769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
27869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
27969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
28069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
28169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
28269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
28369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
28469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
28569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "  if (subgroupBallotBitExtract(mask, otherID))\n"
28669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  {\n"
28769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "    result[offset] = (op == data[otherID]) ? 1 : 0;\n"
28869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  }\n"
28969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  else\n"
29069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  {\n"
29169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "    result[offset] = 1; // Invocation we read from was inactive, so we can't verify results!\n"
29269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  }\n"
29369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "}\n";
29469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
29569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("comp")
296d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
29769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
29869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
29969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
30069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("vert")
301ef086961c26f3bee5c08531a177926bf7fb8b27aAlexander Galazin				<< glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
30269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
30369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		std::ostringstream frag;
30469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
30569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		frag << "#version 450\n"
30669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "#extension GL_KHR_shader_subgroup_quad: enable\n"
30769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
30869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "layout(location = 0) out uint result;\n"
30958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			 << "layout(set = 0, binding = 0, std430) readonly buffer Buffer2\n"
31069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "{\n"
31169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[];\n"
31269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "};\n"
31369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "void main (void)\n"
31469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "{\n"
31569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "  uvec4 mask = subgroupBallot(true);\n"
31669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << swapTable[caseDef.opType];
31769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
31869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
31969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
32069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			frag << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
32169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
32269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				 << "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
32369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
32469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
32569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
32669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
32769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			frag << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
32869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
32969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				 << "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
33069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
33169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
33269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		frag << "  if (subgroupBallotBitExtract(mask, otherID))\n"
33369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "  {\n"
33469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "    result = (op == data[otherID]) ? 1 : 0;\n"
33569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "  }\n"
33669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "  else\n"
33769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "  {\n"
33869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "    result = 1; // Invocation we read from was inactive, so we can't verify results!\n"
33969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "  }\n"
34069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "}\n";
34169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
34269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("frag")
343d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
34469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
34569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
34669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
34769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		std::ostringstream src;
34869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
34969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "#version 450\n"
35069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_quad: enable\n"
35169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
35269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
35369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
35469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uint result[];\n"
35569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
35669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
35769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
35869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[];\n"
35969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
36069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "\n"
36169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "void main (void)\n"
36269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
36369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uvec4 mask = subgroupBallot(true);\n"
36469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< swapTable[caseDef.opType];
36569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
36669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
36769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
36869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
36969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
37069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
37169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
37269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
37369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
37469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
37569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
37669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
37769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
37869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
37969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "  if (subgroupBallotBitExtract(mask, otherID))\n"
38069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  {\n"
38169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "    result[gl_VertexIndex] = (op == data[otherID]) ? 1 : 0;\n"
38269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  }\n"
38369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  else\n"
38469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  {\n"
38569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "    result[gl_VertexIndex] = 1; // Invocation we read from was inactive, so we can't verify results!\n"
38669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  }\n"
38769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "}\n";
38869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
38969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("vert")
390d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
39169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
39269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
39369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
39469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("vert")
395ef086961c26f3bee5c08531a177926bf7fb8b27aAlexander Galazin				<< glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
39669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
39769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		std::ostringstream src;
39869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
39969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "#version 450\n"
40069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_quad: enable\n"
40169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
40269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(points) in;\n"
40369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(points, max_vertices = 1) out;\n"
40469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
40569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
40669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uint result[];\n"
40769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
40869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
40969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
41069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[];\n"
41169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
41269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "\n"
41369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "void main (void)\n"
41469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
41569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uvec4 mask = subgroupBallot(true);\n"
41669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< swapTable[caseDef.opType];
41769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
41869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
41969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
42069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
42169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
42269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
42369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
42469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
42569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
42669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
42769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
42869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
42969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
43069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
43169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "  if (subgroupBallotBitExtract(mask, otherID))\n"
43269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  {\n"
43369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "    result[gl_PrimitiveIDIn] = (op == data[otherID]) ? 1 : 0;\n"
43469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  }\n"
43569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  else\n"
43669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  {\n"
43769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "    result[gl_PrimitiveIDIn] = 1; // Invocation we read from was inactive, so we can't verify results!\n"
43869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  }\n"
43969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "}\n";
44069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
44169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("geom")
442d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
44369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
44469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
44569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
44669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("vert")
447ef086961c26f3bee5c08531a177926bf7fb8b27aAlexander Galazin				<< glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
44869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
44969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("tese")
45069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< glu::TessellationEvaluationSource("#version 450\nlayout(isolines) in;\nvoid main (void) {}\n");
45169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
45269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		std::ostringstream src;
45369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
45469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "#version 450\n"
45569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_quad: enable\n"
45669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
45769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(vertices=1) out;\n"
45869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
45969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
46069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uint result[];\n"
46169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
46269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
46369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
46469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[];\n"
46569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
46669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "\n"
46769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "void main (void)\n"
46869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
46969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uvec4 mask = subgroupBallot(true);\n"
47069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< swapTable[caseDef.opType];
47169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
47269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
47369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
47469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
47569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
47669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
47769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
47869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
47969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
48069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
48169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
48269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
48369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
48469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
48569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "  if (subgroupBallotBitExtract(mask, otherID))\n"
48669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  {\n"
48769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "    result[gl_PrimitiveID] = (op == data[otherID]) ? 1 : 0;\n"
48869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  }\n"
48969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  else\n"
49069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  {\n"
49169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "    result[gl_PrimitiveID] = 1; // Invocation we read from was inactive, so we can't verify results!\n"
49269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  }\n"
49369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "}\n";
49469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
49569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("tesc")
496d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
49769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
49869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
49969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
50069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("vert")
501ef086961c26f3bee5c08531a177926bf7fb8b27aAlexander Galazin				<< glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
50269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
50369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("tesc")
50469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< glu::TessellationControlSource("#version 450\nlayout(vertices=1) out;\nvoid main (void) { for(uint i = 0; i < 4; i++) { gl_TessLevelOuter[i] = 1.0f; } }\n");
50569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
50669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		std::ostringstream src;
50769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
50869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "#version 450\n"
50969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_quad: enable\n"
51069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
51169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(isolines) in;\n"
51269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
51369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
51469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uint result[];\n"
51569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
51669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
51769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
51869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[];\n"
51969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
52069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "\n"
52169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "void main (void)\n"
52269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
52369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uvec4 mask = subgroupBallot(true);\n"
52469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< swapTable[caseDef.opType];
52569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
52669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
52769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
52869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
52969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
53069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
53169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
53269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
53369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
53469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
53569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
53669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
53769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
53869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
53969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "  if (subgroupBallotBitExtract(mask, otherID))\n"
54069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  {\n"
54169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "    result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = (op == data[otherID]) ? 1 : 0;\n"
54269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  }\n"
54369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  else\n"
54469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  {\n"
54569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "    result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = 1; // Invocation we read from was inactive, so we can't verify results!\n"
54669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  }\n"
54769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "}\n";
54869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
54969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("tese")
550d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
55169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
55269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else
55369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
55469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		DE_FATAL("Unsupported shader stage");
55569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
55669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
55769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
55869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningtcu::TestStatus test(Context& context, const CaseDefinition caseDef)
55969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
5604e3b4214a201bd02f2e4868f464222ca6ede8dc0Samuel Iglesias Gonsálvez	if (!subgroups::isSubgroupSupported(context))
5614e3b4214a201bd02f2e4868f464222ca6ede8dc0Samuel Iglesias Gonsálvez		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
5624e3b4214a201bd02f2e4868f464222ca6ede8dc0Samuel Iglesias Gonsálvez
56369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	if (!subgroups::areSubgroupOperationsSupportedForStage(
56469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				context, caseDef.shaderStage))
56569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
56669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (subgroups::areSubgroupOperationsRequiredForStage(
56769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					caseDef.shaderStage))
56869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
56969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return tcu::TestStatus::fail(
57069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   "Shader stage " +
57169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   subgroups::getShaderStageName(caseDef.shaderStage) +
57269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   " is required to support subgroup operations!");
57369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
57469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
57569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
57669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
57769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
57869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
57969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
58069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_QUAD_BIT))
58169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
58269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		TCU_THROW(NotSupportedError, "Device does not support subgroup quad operations");
58369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
58469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
58569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	if (subgroups::isDoubleFormat(caseDef.format) &&
58669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			!subgroups::isDoubleSupportedForDevice(context))
58769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
58869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		TCU_THROW(NotSupportedError, "Device does not support subgroup double operations");
58969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
59069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
59158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	//Tests which don't use the SSBO
59258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	if (caseDef.noSSBO && VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
59358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	{
59458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			subgroups::SSBOData inputData;
59558319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			inputData.format = caseDef.format;
59658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			inputData.numElements = subgroups::maxSupportedSubgroupSize();
59758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
59858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
59958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages);
60058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	}
60158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
60269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	if ((VK_SHADER_STAGE_FRAGMENT_BIT != caseDef.shaderStage) &&
60369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			(VK_SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage))
60469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
60569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (!subgroups::isVertexSSBOSupportedForDevice(context))
60669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
60769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
60869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
60969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
61069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
61169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
61269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
61369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		subgroups::SSBOData inputData;
61469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.format = caseDef.format;
61569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.numElements = subgroups::maxSupportedSubgroupSize();
61669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
61769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
61869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		return subgroups::makeFragmentTest(context, VK_FORMAT_R32_UINT,
61969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning										   &inputData, 1, checkFragment);
62069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
62169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
62269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
62369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		subgroups::SSBOData inputData;
62469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.format = caseDef.format;
62569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.numElements = subgroups::maxSupportedSubgroupSize();
62669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
62769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
62869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, &inputData,
62969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning										  1, checkCompute);
63069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
63169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
63269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
63369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		subgroups::SSBOData inputData;
63469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.format = caseDef.format;
63569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.numElements = subgroups::maxSupportedSubgroupSize();
63669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
63769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
63869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		return subgroups::makeVertexTest(context, VK_FORMAT_R32_UINT, &inputData,
63969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning										 1, checkVertexPipelineStages);
64069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
64169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
64269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
64369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		subgroups::SSBOData inputData;
64469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.format = caseDef.format;
64569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.numElements = subgroups::maxSupportedSubgroupSize();
64669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
64769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
64869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		return subgroups::makeGeometryTest(context, VK_FORMAT_R32_UINT, &inputData,
64969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning										   1, checkVertexPipelineStages);
65069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
65169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
65269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
65369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		subgroups::SSBOData inputData;
65469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.format = caseDef.format;
65569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.numElements = subgroups::maxSupportedSubgroupSize();
65669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
65769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
65869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		return subgroups::makeTessellationControlTest(context, VK_FORMAT_R32_UINT, &inputData,
65969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				1, checkVertexPipelineStages);
66069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
66169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
66269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
66369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		subgroups::SSBOData inputData;
66469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.format = caseDef.format;
66569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.numElements = subgroups::maxSupportedSubgroupSize();
66669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
66769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
66869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		return subgroups::makeTessellationEvaluationTest(context, VK_FORMAT_R32_UINT, &inputData,
66969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				1, checkVertexPipelineStages);
67069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
67169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else
67269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
67369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		TCU_THROW(InternalError, "Unhandled shader stage");
67469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
67569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
67669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
67769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
67869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningnamespace vkt
67969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
68069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningnamespace subgroups
68169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
68269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningtcu::TestCaseGroup* createSubgroupsQuadTests(tcu::TestContext& testCtx)
68369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
68469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(
68569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			testCtx, "quad", "Subgroup quad category tests"));
68669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
68769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const VkShaderStageFlags stages[] =
68869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
68969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
69069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
69169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_SHADER_STAGE_GEOMETRY_BIT,
69269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_SHADER_STAGE_VERTEX_BIT,
69369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_SHADER_STAGE_FRAGMENT_BIT,
69469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_SHADER_STAGE_COMPUTE_BIT
69569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	};
69669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
69769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const VkFormat formats[] =
69869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
69969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_FORMAT_R32_SINT, VK_FORMAT_R32G32_SINT, VK_FORMAT_R32G32B32_SINT,
70069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32_UINT, VK_FORMAT_R32G32_UINT,
70169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_FORMAT_R32G32B32_UINT, VK_FORMAT_R32G32B32A32_UINT,
70269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT,
70369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_FORMAT_R32G32B32_SFLOAT, VK_FORMAT_R32G32B32A32_SFLOAT,
70469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_FORMAT_R64_SFLOAT, VK_FORMAT_R64G64_SFLOAT,
70569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_FORMAT_R64G64B64_SFLOAT, VK_FORMAT_R64G64B64A64_SFLOAT,
70669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_FORMAT_R8_USCALED, VK_FORMAT_R8G8_USCALED,
70769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_FORMAT_R8G8B8_USCALED, VK_FORMAT_R8G8B8A8_USCALED,
70869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	};
70969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
71069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (int direction = 0; direction < 4; ++direction)
71169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
71269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
71369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
71469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			const VkShaderStageFlags stage = stages[stageIndex];
71569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
71669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			for (int formatIndex = 0; formatIndex < DE_LENGTH_OF_ARRAY(formats); ++formatIndex)
71769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			{
71869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				const VkFormat format = formats[formatIndex];
71969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
72069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
72169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				{
72258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa					CaseDefinition caseDef = {opTypeIndex, stage, format, direction, false};
72369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
72469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					std::ostringstream name;
72569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
72669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					std::string op = getOpTypeName(opTypeIndex);
72769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
72869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					name << de::toLower(op);
72969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
73069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					if (OPTYPE_QUAD_BROADCAST == opTypeIndex)
73169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					{
73269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						name << "_" << direction;
73369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					}
73469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					else
73569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					{
73669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						if (0 != direction)
73769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						{
73869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							// We don't need direction for swap operations.
73969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							continue;
74069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						}
74169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					}
74269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
74369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					name << "_" << subgroups::getFormatNameForGLSL(format)
74469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						 << "_" << getShaderStageName(stage);
74569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
74669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					addFunctionCaseWithPrograms(group.get(), name.str(),
74769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning												"", initPrograms, test, caseDef);
74858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
74958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa					if (VK_SHADER_STAGE_VERTEX_BIT == stage )
75058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa					{
75158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa						caseDef.noSSBO = true;
75258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa						addFunctionCaseWithPrograms(group.get(), name.str()+"_framebuffer", "",
75358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa													initFrameBufferPrograms, test, caseDef);
75458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa					}
75558319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
75669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				}
75769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			}
75869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
75969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
76069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
76169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return group.release();
76269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
76369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
76469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning} // subgroups
76569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning} // vkt
766