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 "vktSubgroupsBuiltinVarTests.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 Henning
3569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningnamespace vkt
3669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
3769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningnamespace subgroups
3869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
3958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
4058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwabool checkVertexPipelineStagesSubgroupSize(std::vector<const void*> datas,
4169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		deUint32 width, deUint32 subgroupSize)
4269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
4369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32* data =
4469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		reinterpret_cast<const deUint32*>(datas[0]);
4569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 x = 0; x < width; ++x)
4669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
4769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		deUint32 val = data[x * 4];
4869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
4969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (subgroupSize != val)
5069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
5169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return false;
5269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
5369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
5469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
5569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return true;
5669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
5769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
5858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwabool checkVertexPipelineStagesSubgroupInvocationID(std::vector<const void*> datas,
5958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		deUint32 width, deUint32 subgroupSize)
6069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
6169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32* data =
6269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		reinterpret_cast<const deUint32*>(datas[0]);
6369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	vector<deUint32> subgroupInvocationHits(subgroupSize, 0);
6469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
6569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 x = 0; x < width; ++x)
6669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
6769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		deUint32 subgroupInvocationID = data[(x * 4) + 1];
6869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
6969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (subgroupInvocationID >= subgroupSize)
7069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
7169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return false;
7269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
7369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
7469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		subgroupInvocationHits[subgroupInvocationID]++;
7569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
7669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
7769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32 totalSize = width;
7869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
7969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	deUint32 totalInvocationsRun = 0;
8069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 i = 0; i < subgroupSize; ++i)
8169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
8269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		totalInvocationsRun += subgroupInvocationHits[i];
8369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
8469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
8569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	if (totalInvocationsRun != totalSize)
8669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
8769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		return false;
8869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
8969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
9069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return true;
9169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
9269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
9369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningstatic bool checkFragmentSubgroupSize(std::vector<const void*> datas,
9469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning									  deUint32 width, deUint32 height, deUint32 subgroupSize)
9569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
9669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32* data =
9769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		reinterpret_cast<const deUint32*>(datas[0]);
9869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 x = 0; x < width; ++x)
9969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
10069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		for (deUint32 y = 0; y < height; ++y)
10169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
10269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			deUint32 val = data[(x * height + y) * 4];
10369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
10469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			if (subgroupSize != val)
10569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			{
10669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				return false;
10769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			}
10869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
10969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
11069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
11169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return true;
11269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
11369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
11469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningstatic bool checkFragmentSubgroupInvocationID(
11569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	std::vector<const void*> datas, deUint32 width, deUint32 height,
11669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	deUint32 subgroupSize)
11769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
11869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32* data =
11969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		reinterpret_cast<const deUint32*>(datas[0]);
12069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	vector<deUint32> subgroupInvocationHits(subgroupSize, 0);
12169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
12269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 x = 0; x < width; ++x)
12369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
12469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		for (deUint32 y = 0; y < height; ++y)
12569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
12669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			deUint32 subgroupInvocationID = data[((x * height + y) * 4) + 1];
12769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
12869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			if (subgroupInvocationID >= subgroupSize)
12969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			{
13069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				return false;
13169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			}
13269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
13369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			subgroupInvocationHits[subgroupInvocationID]++;
13469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
13569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
13669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
13769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32 totalSize = width * height;
13869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
13969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	deUint32 totalInvocationsRun = 0;
14069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 i = 0; i < subgroupSize; ++i)
14169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
14269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		totalInvocationsRun += subgroupInvocationHits[i];
14369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
14469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
14569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	if (totalInvocationsRun != totalSize)
14669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
14769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		return false;
14869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
14969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
15069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return true;
15169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
15269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
15369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningstatic bool checkComputeSubgroupSize(std::vector<const void*> datas,
15469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning									 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
15569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning									 deUint32 subgroupSize)
15669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
15769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
15869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
15969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 nX = 0; nX < numWorkgroups[0]; ++nX)
16069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
16169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		for (deUint32 nY = 0; nY < numWorkgroups[1]; ++nY)
16269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
16369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			for (deUint32 nZ = 0; nZ < numWorkgroups[2]; ++nZ)
16469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			{
16569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				for (deUint32 lX = 0; lX < localSize[0]; ++lX)
16669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				{
16769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					for (deUint32 lY = 0; lY < localSize[1]; ++lY)
16869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					{
16969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						for (deUint32 lZ = 0; lZ < localSize[2];
17069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								++lZ)
17169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						{
17269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationX =
17369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nX * localSize[0] + lX;
17469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationY =
17569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nY * localSize[1] + lY;
17669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationZ =
17769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nZ * localSize[2] + lZ;
17869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
17969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalSizeX =
18069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								numWorkgroups[0] * localSize[0];
18169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalSizeY =
18269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								numWorkgroups[1] * localSize[1];
18369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
18469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 offset =
18569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								globalSizeX *
18669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								((globalSizeY *
18769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								  globalInvocationZ) +
18869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								 globalInvocationY) +
18969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								globalInvocationX;
19069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
19169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							if (subgroupSize != data[offset * 4])
19269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							{
19369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								return false;
19469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							}
19569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						}
19669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					}
19769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				}
19869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			}
19969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
20069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
20169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
20269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return true;
20369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
20469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
20569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningstatic bool checkComputeSubgroupInvocationID(std::vector<const void*> datas,
20669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		const deUint32 numWorkgroups[3], const deUint32 localSize[3],
20769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		deUint32 subgroupSize)
20869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
20969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
21069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
21169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 nX = 0; nX < numWorkgroups[0]; ++nX)
21269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
21369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		for (deUint32 nY = 0; nY < numWorkgroups[1]; ++nY)
21469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
21569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			for (deUint32 nZ = 0; nZ < numWorkgroups[2]; ++nZ)
21669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			{
21769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				const deUint32 totalLocalSize =
21869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					localSize[0] * localSize[1] * localSize[2];
21969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				vector<deUint32> subgroupInvocationHits(subgroupSize, 0);
22069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
22169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				for (deUint32 lX = 0; lX < localSize[0]; ++lX)
22269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				{
22369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					for (deUint32 lY = 0; lY < localSize[1]; ++lY)
22469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					{
22569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						for (deUint32 lZ = 0; lZ < localSize[2];
22669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								++lZ)
22769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						{
22869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationX =
22969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nX * localSize[0] + lX;
23069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationY =
23169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nY * localSize[1] + lY;
23269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationZ =
23369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nZ * localSize[2] + lZ;
23469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
23569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalSizeX =
23669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								numWorkgroups[0] * localSize[0];
23769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalSizeY =
23869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								numWorkgroups[1] * localSize[1];
23969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
24069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 offset =
24169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								globalSizeX *
24269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								((globalSizeY *
24369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								  globalInvocationZ) +
24469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								 globalInvocationY) +
24569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								globalInvocationX;
24669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
24769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							deUint32 subgroupInvocationID = data[(offset * 4) + 1];
24869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
24969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							if (subgroupInvocationID >= subgroupSize)
25069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							{
25169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								return false;
25269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							}
25369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
25469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							subgroupInvocationHits[subgroupInvocationID]++;
25569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						}
25669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					}
25769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				}
25869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
25969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				deUint32 totalInvocationsRun = 0;
26069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				for (deUint32 i = 0; i < subgroupSize; ++i)
26169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				{
26269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					totalInvocationsRun += subgroupInvocationHits[i];
26369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				}
26469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
26569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				if (totalInvocationsRun != totalLocalSize)
26669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				{
26769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					return false;
26869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				}
26969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			}
27069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
27169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
27269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
27369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return true;
27469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
27569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
27669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningstatic bool checkComputeNumSubgroups(std::vector<const void*> datas,
27769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning									 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
27869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning									 deUint32)
27969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
28069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
28169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
28269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 nX = 0; nX < numWorkgroups[0]; ++nX)
28369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
28469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		for (deUint32 nY = 0; nY < numWorkgroups[1]; ++nY)
28569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
28669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			for (deUint32 nZ = 0; nZ < numWorkgroups[2]; ++nZ)
28769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			{
28869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				const deUint32 totalLocalSize =
28969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					localSize[0] * localSize[1] * localSize[2];
29069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
29169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				for (deUint32 lX = 0; lX < localSize[0]; ++lX)
29269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				{
29369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					for (deUint32 lY = 0; lY < localSize[1]; ++lY)
29469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					{
29569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						for (deUint32 lZ = 0; lZ < localSize[2];
29669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								++lZ)
29769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						{
29869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationX =
29969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nX * localSize[0] + lX;
30069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationY =
30169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nY * localSize[1] + lY;
30269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationZ =
30369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nZ * localSize[2] + lZ;
30469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
30569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalSizeX =
30669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								numWorkgroups[0] * localSize[0];
30769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalSizeY =
30869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								numWorkgroups[1] * localSize[1];
30969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
31069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 offset =
31169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								globalSizeX *
31269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								((globalSizeY *
31369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								  globalInvocationZ) +
31469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								 globalInvocationY) +
31569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								globalInvocationX;
31669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
31769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							deUint32 numSubgroups = data[(offset * 4) + 2];
31869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
31969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							if (numSubgroups > totalLocalSize)
32069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							{
32169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								return false;
32269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							}
32369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						}
32469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					}
32569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				}
32669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			}
32769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
32869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
32969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
33069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return true;
33169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
33269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
33369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningstatic bool checkComputeSubgroupID(std::vector<const void*> datas,
33469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								   const deUint32 numWorkgroups[3], const deUint32 localSize[3],
33569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								   deUint32)
33669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
33769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
33869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
33969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (deUint32 nX = 0; nX < numWorkgroups[0]; ++nX)
34069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
34169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		for (deUint32 nY = 0; nY < numWorkgroups[1]; ++nY)
34269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
34369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			for (deUint32 nZ = 0; nZ < numWorkgroups[2]; ++nZ)
34469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			{
34569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				for (deUint32 lX = 0; lX < localSize[0]; ++lX)
34669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				{
34769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					for (deUint32 lY = 0; lY < localSize[1]; ++lY)
34869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					{
34969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						for (deUint32 lZ = 0; lZ < localSize[2];
35069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								++lZ)
35169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						{
35269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationX =
35369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nX * localSize[0] + lX;
35469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationY =
35569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nY * localSize[1] + lY;
35669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalInvocationZ =
35769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								nZ * localSize[2] + lZ;
35869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
35969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalSizeX =
36069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								numWorkgroups[0] * localSize[0];
36169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 globalSizeY =
36269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								numWorkgroups[1] * localSize[1];
36369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
36469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							const deUint32 offset =
36569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								globalSizeX *
36669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								((globalSizeY *
36769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								  globalInvocationZ) +
36869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								 globalInvocationY) +
36969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								globalInvocationX;
37069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
37169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							deUint32 numSubgroups = data[(offset * 4) + 2];
37269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							deUint32 subgroupID = data[(offset * 4) + 3];
37369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
37469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							if (subgroupID >= numSubgroups)
37569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							{
37669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning								return false;
37769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning							}
37869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning						}
37969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					}
38069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				}
38169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			}
38269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
38369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
38469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
38569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return true;
38669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
38769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
38869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningnamespace
38969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
39069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningstruct CaseDefinition
39169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
39269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	std::string varName;
39369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	VkShaderStageFlags shaderStage;
39458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	bool noSSBO;
39569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning};
39669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
39769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
39858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwavoid initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
39958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa{
40058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	std::ostringstream src;
40158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
40258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	{
40358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		src << "#version 450\n"
40458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
40558319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "layout(location = 0) out vec4 out_color;\n"
40658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "layout(location = 0) in highp vec4 in_position;\n"
40758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "\n"
40858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "void main (void)\n"
40958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "{\n"
41058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "  out_color = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, 1.0f, 1.0f);\n"
41158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "  gl_Position = in_position;\n"
4128e70b5bff809a7f05bd563e3919abe3f6eee7d0fStu Smith			<< "  gl_PointSize = 1.0f;\n"
41358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			<< "}\n";
41458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
415ef086961c26f3bee5c08531a177926bf7fb8b27aAlexander Galazin		programCollection.glslSources.add("vert") << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
41658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
41758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		std::ostringstream source;
41858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		source	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
41958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa				<< "layout(location = 0) in vec4 in_color;\n"
42058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa				<< "layout(location = 0) out uvec4 out_color;\n"
42158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa				<< "void main()\n"
42258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa				<<"{\n"
42358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa				<< "	out_color = uvec4(in_color);\n"
42458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa				<< "}\n";
425ef086961c26f3bee5c08531a177926bf7fb8b27aAlexander Galazin		programCollection.glslSources.add("fragment") << glu::FragmentSource(source.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
42658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	}
42758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	else
42858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	{
42958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		DE_FATAL("Unsupported shader stage");
43058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	}
43158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa}
43258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
43369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningvoid initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
43469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
43569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
43669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
43769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		std::ostringstream src;
43869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
43969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "#version 450\n"
44069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
44169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout (local_size_x_id = 0, local_size_y_id = 1, "
44269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			"local_size_z_id = 2) in;\n"
44369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 0, std430) buffer Output\n"
44469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
44569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uvec4 result[];\n"
44669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
44769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "\n"
44869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "void main (void)\n"
44969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
45069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
45169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  highp uint offset = globalSize.x * ((globalSize.y * "
45269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			"gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
45369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			"gl_GlobalInvocationID.x;\n"
45469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  result[offset] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, gl_NumSubgroups, gl_SubgroupID);\n"
45569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "}\n";
45669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
45769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("comp")
458d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
45969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
46069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
46169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
46269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("vert")
463ef086961c26f3bee5c08531a177926bf7fb8b27aAlexander Galazin				<< glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
46469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
46569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		std::ostringstream frag;
46669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
46769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		frag << "#version 450\n"
46869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
46969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "layout(location = 0) out uvec4 data;\n"
47069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "void main (void)\n"
47169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "{\n"
47269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "  data = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0, 0);\n"
47369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			 << "}\n";
47469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
47569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("frag")
476d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
47769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
47869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
47969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
48069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		std::ostringstream src;
48169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
48269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "#version 450\n"
48369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
48469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 0, std430) buffer Output\n"
48569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
48669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uvec4 result[];\n"
48769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
48869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "\n"
48969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "void main (void)\n"
49069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
49169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  result[gl_VertexIndex] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0, 0);\n"
492a76eb94eda712267ccded7d3dfe5065fb6d15e37Chris Forbes			<< "  gl_PointSize = 1.0f;\n"
49369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "}\n";
49469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
49569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("vert")
496d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
49769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
49869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_GEOMETRY_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		std::ostringstream src;
50469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
50569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "#version 450\n"
50669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
50769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(points) in;\n"
50869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(points, max_vertices = 1) out;\n"
50969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 0, std430) buffer Output\n"
51069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
51169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uvec4 result[];\n"
51269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
51369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "\n"
51469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "void main (void)\n"
51569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
51669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  result[gl_PrimitiveIDIn] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0, 0);\n"
51769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "}\n";
51869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
51969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("geom")
520d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
52169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
52269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
52369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
52469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("vert")
525ef086961c26f3bee5c08531a177926bf7fb8b27aAlexander Galazin				<< glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
52669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
52769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("tese")
52869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				<< glu::TessellationEvaluationSource("#version 450\nlayout(isolines) in;\nvoid main (void) {}\n");
52969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
53069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		std::ostringstream src;
53169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
53269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "#version 450\n"
53369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
53469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(vertices=1) out;\n"
53569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 0, std430) buffer Output\n"
53669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
53769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uvec4 result[];\n"
53869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
53969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "\n"
54069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "void main (void)\n"
54169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
54269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  result[gl_PrimitiveID] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0, 0);\n"
54369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "}\n";
54469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
54569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("tesc")
546d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
54769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
54869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
54969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
55069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("vert")
551d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
55269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
55369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("tesc")
55469593fca6204550740739cc03ec9a51d29f5d8c5Neil 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");
55569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
55669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		std::ostringstream src;
55769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
55869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		src << "#version 450\n"
55969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
56069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(isolines) in;\n"
56169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "layout(set = 0, binding = 0, std430) buffer Output\n"
56269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
56369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  uvec4 result[];\n"
56469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "};\n"
56569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "\n"
56669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "void main (void)\n"
56769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "{\n"
56869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "  result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0, 0);\n"
56969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			<< "}\n";
57069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
57169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		programCollection.glslSources.add("tese")
572d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin				<< glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
57369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
57469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else
57569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
57669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		DE_FATAL("Unsupported shader stage");
57769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
57869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
57969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
58069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningtcu::TestStatus test(Context& context, const CaseDefinition caseDef)
58169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
5824e3b4214a201bd02f2e4868f464222ca6ede8dc0Samuel Iglesias Gonsálvez	if (!subgroups::isSubgroupSupported(context))
5834e3b4214a201bd02f2e4868f464222ca6ede8dc0Samuel Iglesias Gonsálvez		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
5844e3b4214a201bd02f2e4868f464222ca6ede8dc0Samuel Iglesias Gonsálvez
58569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	if (!areSubgroupOperationsSupportedForStage(
58669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning				context, caseDef.shaderStage))
58769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
58869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (areSubgroupOperationsRequiredForStage(caseDef.shaderStage))
58969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
59069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return tcu::TestStatus::fail(
59169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   "Shader stage " + getShaderStageName(caseDef.shaderStage) +
59269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   " is required to support subgroup operations!");
59369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
59469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
59569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
59669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
59769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
59869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
59969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
60058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	//Tests which don't use the SSBO
60158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	if (caseDef.noSSBO && VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
60258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	{
60358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		if ("gl_SubgroupSize" == caseDef.varName)
60458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		{
60558319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			return makeVertexFrameBufferTest(
60658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupSize);
60758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		}
60858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		else if ("gl_SubgroupInvocationID" == caseDef.varName)
60958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		{
61058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			return makeVertexFrameBufferTest(
61158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupInvocationID);
61258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		}
61358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa	}
61458319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
61569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	if ((VK_SHADER_STAGE_FRAGMENT_BIT != caseDef.shaderStage) &&
61669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			(VK_SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage))
61769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
61869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if (!subgroups::isVertexSSBOSupportedForDevice(context))
61969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
62069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
62169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
62269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
62369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
62469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
62569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
62669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if ("gl_SubgroupSize" == caseDef.varName)
62769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
62869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeComputeTest(
62969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkComputeSubgroupSize);
63069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
63169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else if ("gl_SubgroupInvocationID" == caseDef.varName)
63269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
63369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeComputeTest(
63469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkComputeSubgroupInvocationID);
63569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
63669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else if ("gl_NumSubgroups" == caseDef.varName)
63769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
63869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeComputeTest(
63969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkComputeNumSubgroups);
64069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
64169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else if ("gl_SubgroupID" == caseDef.varName)
64269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
64369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeComputeTest(
64469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkComputeSubgroupID);
64569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
64669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
64769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
64869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return tcu::TestStatus::fail(
64969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   caseDef.varName + " failed (unhandled error checking case " +
65069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   caseDef.varName + ")!");
65169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
65269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
65369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
65469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
65569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if ("gl_SubgroupSize" == caseDef.varName)
65669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
65769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeFragmentTest(
65869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkFragmentSubgroupSize);
65969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
66069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else if ("gl_SubgroupInvocationID" == caseDef.varName)
66169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
66269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeFragmentTest(
66369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkFragmentSubgroupInvocationID);
66469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
66569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
66669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
66769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return tcu::TestStatus::fail(
66869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   caseDef.varName + " failed (unhandled error checking case " +
66969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   caseDef.varName + ")!");
67069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
67169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
67269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
67369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
67469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if ("gl_SubgroupSize" == caseDef.varName)
67569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
67669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeVertexTest(
67769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupSize);
67869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
67969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else if ("gl_SubgroupInvocationID" == caseDef.varName)
68069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
68169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeVertexTest(
68269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupInvocationID);
68369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
68469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
68569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
68669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return tcu::TestStatus::fail(
68769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   caseDef.varName + " failed (unhandled error checking case " +
68869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   caseDef.varName + ")!");
68969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
69069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
69169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
69269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
69369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if ("gl_SubgroupSize" == caseDef.varName)
69469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
69569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeGeometryTest(
69669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupSize);
69769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
69869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else if ("gl_SubgroupInvocationID" == caseDef.varName)
69969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
70069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeGeometryTest(
70169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupInvocationID);
70269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
70369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
70469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
70569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return tcu::TestStatus::fail(
70669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   caseDef.varName + " failed (unhandled error checking case " +
70769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   caseDef.varName + ")!");
70869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
70969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
71069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
71169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
71269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if ("gl_SubgroupSize" == caseDef.varName)
71369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
71469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeTessellationControlTest(
71569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupSize);
71669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
71769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else if ("gl_SubgroupInvocationID" == caseDef.varName)
71869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
71969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeTessellationControlTest(
72069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupInvocationID);
72169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
72269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
72369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
72469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return tcu::TestStatus::fail(
72569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   caseDef.varName + " failed (unhandled error checking case " +
72669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   caseDef.varName + ")!");
72769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
72869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
72969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
73069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
73169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		if ("gl_SubgroupSize" == caseDef.varName)
73269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
73369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeTessellationEvaluationTest(
73469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupSize);
73569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
73669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else if ("gl_SubgroupInvocationID" == caseDef.varName)
73769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
73869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return makeTessellationEvaluationTest(
73969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupInvocationID);
74069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
74169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		else
74269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
74369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			return tcu::TestStatus::fail(
74469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   caseDef.varName + " failed (unhandled error checking case " +
74569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning					   caseDef.varName + ")!");
74669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
74769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
74869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	else
74969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
75069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		TCU_THROW(InternalError, "Unhandled shader stage");
75169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
75269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
75369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
75469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henningtcu::TestCaseGroup* createSubgroupsBuiltinVarTests(tcu::TestContext& testCtx)
75569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning{
75669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(
75769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			testCtx, "builtin_var", "Subgroup builtin variable tests"));
75869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
75969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const char* const all_stages_vars[] =
76069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
76169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		"SubgroupSize",
76269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		"SubgroupInvocationID"
76369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	};
76469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
76569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const char* const compute_only_vars[] =
76669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
76769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		"NumSubgroups",
76869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		"SubgroupID"
76969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	};
77069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
77169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	const VkShaderStageFlags stages[] =
77269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
77369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
77469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
77569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_SHADER_STAGE_GEOMETRY_BIT,
77669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_SHADER_STAGE_VERTEX_BIT,
77769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_SHADER_STAGE_FRAGMENT_BIT,
77869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		VK_SHADER_STAGE_COMPUTE_BIT,
77969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	};
78069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
78169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
78269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
78369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		const VkShaderStageFlags stage = stages[stageIndex];
78469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
78569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		for (int a = 0; a < DE_LENGTH_OF_ARRAY(all_stages_vars); ++a)
78669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		{
78769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			const std::string var = all_stages_vars[a];
78869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
78958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			CaseDefinition caseDef = {"gl_" + var, stage, false};
79069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
79169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning			addFunctionCaseWithPrograms(group.get(),
79269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning										de::toLower(var) + "_" +
79369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning										getShaderStageName(stage), "",
79469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning										initPrograms, test, caseDef);
79558319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa
79658319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			if (VK_SHADER_STAGE_VERTEX_BIT == stage)
79758319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			{
79858319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa				caseDef.noSSBO = true;
79958319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa				addFunctionCaseWithPrograms(group.get(),
80058319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa							de::toLower(var) + "_" +
80158319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa							getShaderStageName(stage)+"_framebuffer", "",
80258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa							initFrameBufferPrograms, test, caseDef);
80358319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa			}
80469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		}
80569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
80669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
80769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	for (int a = 0; a < DE_LENGTH_OF_ARRAY(compute_only_vars); ++a)
80869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	{
80969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		const VkShaderStageFlags stage = VK_SHADER_STAGE_COMPUTE_BIT;
81069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		const std::string var = compute_only_vars[a];
81169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
81258319ae0eef4b512aa128726f87b765cb0c7e2a8Arkadiusz Sarwa		CaseDefinition caseDef = {"gl_" + var, stage, false};
81369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
81469593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning		addFunctionCaseWithPrograms(group.get(), de::toLower(var) +
81569593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning									"_" + getShaderStageName(stage), "",
81669593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning									initPrograms, test, caseDef);
81769593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	}
81869593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
81969593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning	return group.release();
82069593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning}
82169593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning
82269593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning} // subgroups
82369593fca6204550740739cc03ec9a51d29f5d8c5Neil Henning} // vkt
824