<commit_before>/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2019 The Khronos Group Inc.
 * Copyright (c) 2019 Google Inc.
 * Copyright (c) 2017 Codeplay Software Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */ /*!
 * \file
 * \brief Subgroups Tests
 */ /*--------------------------------------------------------------------*/

#include "vktSubgroupsBallotBroadcastTests.hpp"
#include "vktSubgroupsTestsUtils.hpp"

#include <string>
#include <vector>

using namespace tcu;
using namespace std;
using namespace vk;
using namespace vkt;

namespace
{
enum OpType
{
	OPTYPE_BROADCAST = 0,
	OPTYPE_BROADCAST_FIRST,
	OPTYPE_LAST
};

static bool checkVertexPipelineStages(std::vector<const void*> datas,
									  deUint32 width, deUint32)
{
	return vkt::subgroups::check(datas, width, 3);
}

static bool checkCompute(std::vector<const void*> datas,
						 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
						 deUint32)
{
	return vkt::subgroups::checkCompute(datas, numWorkgroups, localSize, 3);
}

std::string getOpTypeName(int opType)
{
	switch (opType)
	{
		default:
			DE_FATAL("Unsupported op type");
			return "";
		case OPTYPE_BROADCAST:
			return "subgroupBroadcast";
		case OPTYPE_BROADCAST_FIRST:
			return "subgroupBroadcastFirst";
	}
}

struct CaseDefinition
{
	int					opType;
	VkShaderStageFlags	shaderStage;
	VkFormat			format;
	de::SharedPtr<bool>	geometryPointSizeSupported;
	deBool				extShaderSubGroupBallotTests;
};

std::string getBodySource(CaseDefinition caseDef)
{
	std::ostringstream bdy;

	bdy << "  uvec4 mask = subgroupBallot(true);\n";
	bdy << "  uint tempResult = 0;\n";

	if (OPTYPE_BROADCAST == caseDef.opType)
	{
		bdy	<< "  tempResult = 0x3;\n";
		for (int i = 0; i < (int)subgroups::maxSupportedSubgroupSize(); i++)
		{
			bdy << "  {\n"
			<< "    const uint id = "<< i << ";\n"
			<< "    " << subgroups::getFormatNameForGLSL(caseDef.format)
			<< " op = subgroupBroadcast(data1[gl_SubgroupInvocationID], id);\n"
			<< "    if ((id < gl_SubgroupSize) && subgroupBallotBitExtract(mask, id))\n"
			<< "    {\n"
			<< "      if (op != data1[id])\n"
			<< "      {\n"
			<< "        tempResult = 0;\n"
			<< "      }\n"
			<< "    }\n"
			<< "  }\n";
		}
	}
	else
	{
		bdy	<< "  uint firstActive = 0;\n"
			<< "  for (uint i = 0; i < gl_SubgroupSize; i++)\n"
			<< "  {\n"
			<< "    if (subgroupBallotBitExtract(mask, i))\n"
			<< "    {\n"
			<< "      firstActive = i;\n"
			<< "      break;\n"
			<< "    }\n"
			<< "  }\n"
			<< "  tempResult |= (subgroupBroadcastFirst(data1[gl_SubgroupInvocationID]) == data1[firstActive]) ? 0x1 : 0;\n"
			<< "  // make the firstActive invocation inactive now\n"
			<< "  if (firstActive == gl_SubgroupInvocationID)\n"
			<< "  {\n"
			<< "    for (uint i = 0; i < gl_SubgroupSize; i++)\n"
			<< "    {\n"
			<< "      if (subgroupBallotBitExtract(mask, i))\n"
			<< "      {\n"
			<< "        firstActive = i;\n"
			<< "        break;\n"
			<< "      }\n"
			<< "    }\n"
			<< "    tempResult |= (subgroupBroadcastFirst(data1[gl_SubgroupInvocationID]) == data1[firstActive]) ? 0x2 : 0;\n"
			<< "  }\n"
			<< "  else\n"
			<< "  {\n"
			<< "    // the firstActive invocation didn't partake in the second result so set it to true\n"
			<< "    tempResult |= 0x2;\n"
			<< "  }\n";
	}
   return bdy.str();
}

std::string getBodySourceARB(CaseDefinition caseDef)
{
	std::ostringstream bdy;

	bdy << "  uint64_t mask = ballotARB(true);\n";
	bdy << "  uint tempResult = 0;\n";

	if (OPTYPE_BROADCAST == caseDef.opType)
	{
		bdy	<< "  tempResult = 0x3;\n";
		for (int i = 0; i < 64; i++)
		{
			bdy << "  {\n"
			<< "    const uint id = "<< i << ";\n"
			<< "    " << subgroups::getFormatNameForGLSL(caseDef.format)
			<< " op = readInvocationARB(data1[gl_SubGroupInvocationARB], id);\n"
			<< "    if ((id < gl_SubGroupSizeARB) && subgroupBallotBitExtract(mask, id))\n"
			<< "    {\n"
			<< "      if (op != data1[id])\n"
			<< "      {\n"
			<< "        tempResult = 0;\n"
			<< "      }\n"
			<< "    }\n"
			<< "  }\n";
		}
	}
	else
	{
		bdy	<< "  uint firstActive = 0;\n"
			<< "  for (uint i = 0; i < gl_SubGroupSizeARB; i++)\n"
			<< "  {\n"
			<< "    if (subgroupBallotBitExtract(mask, i))\n"
			<< "    {\n"
			<< "      firstActive = i;\n"
			<< "      break;\n"
			<< "    }\n"
			<< "  }\n"
			<< "  tempResult |= (readFirstInvocationARB(data1[gl_SubGroupInvocationARB]) == data1[firstActive]) ? 0x1 : 0;\n"
			<< "  // make the firstActive invocation inactive now\n"
			<< "  if (firstActive == gl_SubGroupInvocationARB)\n"
			<< "  {\n"
			<< "    for (uint i = 0; i < gl_SubGroupSizeARB; i++)\n"
			<< "    {\n"
			<< "      if (subgroupBallotBitExtract(mask, i))\n"
			<< "      {\n"
			<< "        firstActive = i;\n"
			<< "        break;\n"
			<< "      }\n"
			<< "    }\n"
			<< "    tempResult |= (readFirstInvocationARB(data1[gl_SubGroupInvocationARB]) == data1[firstActive]) ? 0x2 : 0;\n"
			<< "  }\n"
			<< "  else\n"
			<< "  {\n"
			<< "    // the firstActive invocation didn't partake in the second result so set it to true\n"
			<< "    tempResult |= 0x2;\n"
			<< "  }\n";
	}
   return bdy.str();
}

std::string getHelperFunctionARB(CaseDefinition caseDef)
{
	std::ostringstream bdy;

	if (caseDef.extShaderSubGroupBallotTests == DE_FALSE)
		return "";

	bdy << "bool subgroupBallotBitExtract(uint64_t value, uint index)\n";
	bdy << "{\n";
	bdy << "    if (index > 63)\n";
	bdy << "        return false;\n";
	bdy << "    uint64_t mask = uint64_t(1 << index);\n";
	bdy << "    if (bool((value & mask)) == true)\n";
	bdy << "        return true;\n";
	bdy << "    return false;\n";
	bdy << "}\n";
   return bdy.str();
}

void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
{
	const vk::ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
	const string extensionHeader =  (caseDef.extShaderSubGroupBallotTests ? "#extension GL_ARB_shader_ballot: enable\n#extension GL_KHR_shader_subgroup_basic: enable\n#extension GL_ARB_gpu_shader_int64: enable\n" : "#extension GL_KHR_shader_subgroup_ballot: enable\n");

	subgroups::setFragmentShaderFrameBuffer(programCollection);

	if (VK_SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
		subgroups::setVertexShaderFrameBuffer(programCollection);

	std::string bdyStr = (caseDef.extShaderSubGroupBallotTests ? getBodySourceARB(caseDef) : getBodySource(caseDef));
	std::string helperStrARB = getHelperFunctionARB(caseDef);

	if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
	{
		std::ostringstream				vertex;
		vertex << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
			<< extensionHeader.c_str()
			<< subgroups::getAdditionalExtensionForFormat(caseDef.format)
			<< "layout(location = 0) in highp vec4 in_position;\n"
			<< "layout(location = 0) out float out_color;\n"
			<< "layout(set = 0, binding = 0) uniform  Buffer1\n"
			<< "{\n"
			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" << subgroups::maxSupportedSubgroupSize() << "];\n"
			<< "};\n"
			<< "\n"
			<< helperStrARB.c_str()
			<< "void main (void)\n"
			<< "{\n"
			<< bdyStr
			<< "  out_color = float(tempResult);\n"
			<< "  gl_Position = in_position;\n"
			<< "  gl_PointSize = 1.0f;\n"
			<< "}\n";
		programCollection.glslSources.add("vert")
			<< glu::VertexSource(vertex.str()) << buildOptions;
	}
	else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
	{
		std::ostringstream geometry;

		geometry << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
			<< extensionHeader.c_str()
			<< subgroups::getAdditionalExtensionForFormat(caseDef.format)
			<< "layout(points) in;\n"
			<< "layout(points, max_vertices = 1) out;\n"
			<< "layout(location = 0) out float out_color;\n"
			<< "layout(set = 0, binding = 0) uniform Buffer1\n"
			<< "{\n"
			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" <<subgroups::maxSupportedSubgroupSize() << "];\n"
			<< "};\n"
			<< "\n"
			<< helperStrARB.c_str()
			<< "void main (void)\n"
			<< "{\n"
			<< bdyStr
			<< "  out_color = float(tempResult);\n"
			<< "  gl_Position = gl_in[0].gl_Position;\n"
			<< (*caseDef.geometryPointSizeSupported ? "  gl_PointSize = gl_in[0].gl_PointSize;\n" : "")
			<< "  EmitVertex();\n"
			<< "  EndPrimitive();\n"
			<< "}\n";

		programCollection.glslSources.add("geometry")
			<< glu::GeometrySource(geometry.str()) << buildOptions;
	}
	else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
	{
		std::ostringstream controlSource;

		controlSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
			<< extensionHeader.c_str()
			<< subgroups::getAdditionalExtensionForFormat(caseDef.format)
			<< "layout(vertices = 2) out;\n"
			<< "layout(location = 0) out float out_color[];\n"
			<< "layout(set = 0, binding = 0) uniform Buffer2\n"
			<< "{\n"
			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" <<subgroups::maxSupportedSubgroupSize() << "];\n"
			<< "};\n"
			<< "\n"
			<< helperStrARB.c_str()
			<< "void main (void)\n"
			<< "{\n"
			<< "  if (gl_InvocationID == 0)\n"
			<< "  {\n"
			<< "    gl_TessLevelOuter[0] = 1.0f;\n"
			<< "    gl_TessLevelOuter[1] = 1.0f;\n"
			<< "  }\n"
			<< bdyStr
			<< "  out_color[gl_InvocationID ] = float(tempResult);\n"
			<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
			<< "}\n";

		programCollection.glslSources.add("tesc")
			<< glu::TessellationControlSource(controlSource.str()) << buildOptions;
		subgroups::setTesEvalShaderFrameBuffer(programCollection);
	}
	else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
	{
		std::ostringstream evaluationSource;
		evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
			<< extensionHeader.c_str()
			<< subgroups::getAdditionalExtensionForFormat(caseDef.format)
			<< "layout(isolines, equal_spacing, ccw ) in;\n"
			<< "layout(location = 0) out float out_color;\n"
			<< "layout(set = 0, binding = 0) uniform Buffer1\n"
			<< "{\n"
			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" <<subgroups::maxSupportedSubgroupSize() << "];\n"
			<< "};\n"
			<< "\n"
			<< helperStrARB.c_str()
			<< "void main (void)\n"
			<< "{\n"
			<< bdyStr
			<< "  out_color  = float(tempResult);\n"
			<< "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
			<< "}\n";

		subgroups::setTesCtrlShaderFrameBuffer(programCollection);
		programCollection.glslSources.add("tese")
			<< glu::TessellationEvaluationSource(evaluationSource.str()) << buildOptions;
	}
	else
	{
		DE_FATAL("Unsupported shader stage");
	}
}

void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
{
	std::string bdyStr = caseDef.extShaderSubGroupBallotTests ? getBodySourceARB(caseDef) : getBodySource(caseDef);
	std::string helperStrARB = getHelperFunctionARB(caseDef);

	const string extensionHeader =  (caseDef.extShaderSubGroupBallotTests ? "#extension GL_ARB_shader_ballot: enable\n#extension GL_KHR_shader_subgroup_basic: enable\n#extension GL_ARB_gpu_shader_int64: enable\n" : "#extension GL_KHR_shader_subgroup_ballot: enable\n");

	if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
	{
		std::ostringstream src;

		src << "#version 450\n"
			<< extensionHeader.c_str()
			<< subgroups::getAdditionalExtensionForFormat(caseDef.format)
			<< "layout (local_size_x_id = 0, local_size_y_id = 1, "
			"local_size_z_id = 2) in;\n"
			<< "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
			<< "{\n"<commit_msg>Combine ARB and Core subgroupBroadcast code<commit_after>/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2019 The Khronos Group Inc.
 * Copyright (c) 2019 Google Inc.
 * Copyright (c) 2017 Codeplay Software Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */ /*!
 * \file
 * \brief Subgroups Tests
 */ /*--------------------------------------------------------------------*/

#include "vktSubgroupsBallotBroadcastTests.hpp"
#include "vktSubgroupsTestsUtils.hpp"

#include <string>
#include <vector>

using namespace tcu;
using namespace std;
using namespace vk;
using namespace vkt;

namespace
{
enum OpType
{
	OPTYPE_BROADCAST = 0,
	OPTYPE_BROADCAST_FIRST,
	OPTYPE_LAST
};

static bool checkVertexPipelineStages(std::vector<const void*> datas,
									  deUint32 width, deUint32)
{
	return vkt::subgroups::check(datas, width, 3);
}

static bool checkCompute(std::vector<const void*> datas,
						 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
						 deUint32)
{
	return vkt::subgroups::checkCompute(datas, numWorkgroups, localSize, 3);
}

std::string getOpTypeName(int opType)
{
	switch (opType)
	{
		default:
			DE_FATAL("Unsupported op type");
			return "";
		case OPTYPE_BROADCAST:
			return "subgroupBroadcast";
		case OPTYPE_BROADCAST_FIRST:
			return "subgroupBroadcastFirst";
	}
}

struct CaseDefinition
{
	int					opType;
	VkShaderStageFlags	shaderStage;
	VkFormat			format;
	de::SharedPtr<bool>	geometryPointSizeSupported;
	deBool				extShaderSubGroupBallotTests;
};

std::string getBodySource(CaseDefinition caseDef)
{
	std::ostringstream bdy;

	std::string broadcast;
	std::string broadcastFirst;
	int max;
	if (caseDef.extShaderSubGroupBallotTests)
	{
		broadcast		= "readInvocationARB";
		broadcastFirst	= "readFirstInvocationARB";
		max = 64;

		bdy << "  uint64_t mask = ballotARB(true);\n";
		bdy << "  uint sgSize = gl_SubGroupSizeARB;\n";
		bdy << "  uint sgInvocation = gl_SubGroupInvocationARB;\n";
	}
	else
	{
		broadcast		= "subgroupBroadcast";
		broadcastFirst	= "subgroupBroadcastFirst";
		max = (int)subgroups::maxSupportedSubgroupSize();

		bdy << "  uvec4 mask = subgroupBallot(true);\n";
		bdy << "  uint sgSize = gl_SubgroupSize;\n";
		bdy << "  uint sgInvocation = gl_SubgroupInvocationID;\n";
	}

	if (OPTYPE_BROADCAST == caseDef.opType)
	{
		bdy	<< "  uint tempResult = 0x3;\n";
		for (int i = 0; i < max; i++)
		{
			bdy << "  {\n"
			<< "    const uint id = "<< i << ";\n"
			<< "    " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
				<< broadcast << "(data1[sgInvocation], id);\n"
			<< "    if ((id < sgSize) && subgroupBallotBitExtract(mask, id))\n"
			<< "    {\n"
			<< "      if (op != data1[id])\n"
			<< "      {\n"
			<< "        tempResult = 0;\n"
			<< "      }\n"
			<< "    }\n"
			<< "  }\n";
		}
	}
	else
	{
		bdy << "  uint tempResult = 0;\n"
			<< "  uint firstActive = 0;\n"
			<< "  for (uint i = 0; i < sgSize; i++)\n"
			<< "  {\n"
			<< "    if (subgroupBallotBitExtract(mask, i))\n"
			<< "    {\n"
			<< "      firstActive = i;\n"
			<< "      break;\n"
			<< "    }\n"
			<< "  }\n"
			<< "  tempResult |= (" << broadcastFirst << "(data1[sgInvocation]) == data1[firstActive]) ? 0x1 : 0;\n"
			<< "  // make the firstActive invocation inactive now\n"
			<< "  if (firstActive == sgInvocation)\n"
			<< "  {\n"
			<< "    for (uint i = 0; i < sgSize; i++)\n"
			<< "    {\n"
			<< "      if (subgroupBallotBitExtract(mask, i))\n"
			<< "      {\n"
			<< "        firstActive = i;\n"
			<< "        break;\n"
			<< "      }\n"
			<< "    }\n"
			<< "    tempResult |= (" << broadcastFirst << "(data1[sgInvocation]) == data1[firstActive]) ? 0x2 : 0;\n"
			<< "  }\n"
			<< "  else\n"
			<< "  {\n"
			<< "    // the firstActive invocation didn't partake in the second result so set it to true\n"
			<< "    tempResult |= 0x2;\n"
			<< "  }\n";
	}
   return bdy.str();
}

std::string getHelperFunctionARB(CaseDefinition caseDef)
{
	std::ostringstream bdy;

	if (caseDef.extShaderSubGroupBallotTests == DE_FALSE)
		return "";

	bdy << "bool subgroupBallotBitExtract(uint64_t value, uint index)\n";
	bdy << "{\n";
	bdy << "    if (index > 63)\n";
	bdy << "        return false;\n";
	bdy << "    uint64_t mask = uint64_t(1 << index);\n";
	bdy << "    if (bool((value & mask)) == true)\n";
	bdy << "        return true;\n";
	bdy << "    return false;\n";
	bdy << "}\n";
   return bdy.str();
}

void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
{
	const vk::ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
	const string extensionHeader =  (caseDef.extShaderSubGroupBallotTests ?	"#extension GL_ARB_shader_ballot: enable\n"
																			"#extension GL_KHR_shader_subgroup_basic: enable\n"
																			"#extension GL_ARB_gpu_shader_int64: enable\n"
																		:	"#extension GL_KHR_shader_subgroup_ballot: enable\n");

	subgroups::setFragmentShaderFrameBuffer(programCollection);

	if (VK_SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
		subgroups::setVertexShaderFrameBuffer(programCollection);

	std::string bdyStr = getBodySource(caseDef);
	std::string helperStrARB = getHelperFunctionARB(caseDef);

	if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
	{
		std::ostringstream				vertex;
		vertex << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
			<< extensionHeader.c_str()
			<< subgroups::getAdditionalExtensionForFormat(caseDef.format)
			<< "layout(location = 0) in highp vec4 in_position;\n"
			<< "layout(location = 0) out float out_color;\n"
			<< "layout(set = 0, binding = 0) uniform  Buffer1\n"
			<< "{\n"
			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" << subgroups::maxSupportedSubgroupSize() << "];\n"
			<< "};\n"
			<< "\n"
			<< helperStrARB.c_str()
			<< "void main (void)\n"
			<< "{\n"
			<< bdyStr
			<< "  out_color = float(tempResult);\n"
			<< "  gl_Position = in_position;\n"
			<< "  gl_PointSize = 1.0f;\n"
			<< "}\n";
		programCollection.glslSources.add("vert")
			<< glu::VertexSource(vertex.str()) << buildOptions;
	}
	else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
	{
		std::ostringstream geometry;

		geometry << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
			<< extensionHeader.c_str()
			<< subgroups::getAdditionalExtensionForFormat(caseDef.format)
			<< "layout(points) in;\n"
			<< "layout(points, max_vertices = 1) out;\n"
			<< "layout(location = 0) out float out_color;\n"
			<< "layout(set = 0, binding = 0) uniform Buffer1\n"
			<< "{\n"
			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" <<subgroups::maxSupportedSubgroupSize() << "];\n"
			<< "};\n"
			<< "\n"
			<< helperStrARB.c_str()
			<< "void main (void)\n"
			<< "{\n"
			<< bdyStr
			<< "  out_color = float(tempResult);\n"
			<< "  gl_Position = gl_in[0].gl_Position;\n"
			<< (*caseDef.geometryPointSizeSupported ? "  gl_PointSize = gl_in[0].gl_PointSize;\n" : "")
			<< "  EmitVertex();\n"
			<< "  EndPrimitive();\n"
			<< "}\n";

		programCollection.glslSources.add("geometry")
			<< glu::GeometrySource(geometry.str()) << buildOptions;
	}
	else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
	{
		std::ostringstream controlSource;

		controlSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
			<< extensionHeader.c_str()
			<< subgroups::getAdditionalExtensionForFormat(caseDef.format)
			<< "layout(vertices = 2) out;\n"
			<< "layout(location = 0) out float out_color[];\n"
			<< "layout(set = 0, binding = 0) uniform Buffer2\n"
			<< "{\n"
			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" <<subgroups::maxSupportedSubgroupSize() << "];\n"
			<< "};\n"
			<< "\n"
			<< helperStrARB.c_str()
			<< "void main (void)\n"
			<< "{\n"
			<< "  if (gl_InvocationID == 0)\n"
			<< "  {\n"
			<< "    gl_TessLevelOuter[0] = 1.0f;\n"
			<< "    gl_TessLevelOuter[1] = 1.0f;\n"
			<< "  }\n"
			<< bdyStr
			<< "  out_color[gl_InvocationID ] = float(tempResult);\n"
			<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
			<< "}\n";

		programCollection.glslSources.add("tesc")
			<< glu::TessellationControlSource(controlSource.str()) << buildOptions;
		subgroups::setTesEvalShaderFrameBuffer(programCollection);
	}
	else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
	{
		std::ostringstream evaluationSource;
		evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
			<< extensionHeader.c_str()
			<< subgroups::getAdditionalExtensionForFormat(caseDef.format)
			<< "layout(isolines, equal_spacing, ccw ) in;\n"
			<< "layout(location = 0) out float out_color;\n"
			<< "layout(set = 0, binding = 0) uniform Buffer1\n"
			<< "{\n"
			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" <<subgroups::maxSupportedSubgroupSize() << "];\n"
			<< "};\n"
			<< "\n"
			<< helperStrARB.c_str()
			<< "void main (void)\n"
			<< "{\n"
			<< bdyStr
			<< "  out_color  = float(tempResult);\n"
			<< "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
			<< "}\n";

		subgroups::setTesCtrlShaderFrameBuffer(programCollection);
		programCollection.glslSources.add("tese")
			<< glu::TessellationEvaluationSource(evaluationSource.str()) << buildOptions;
	}
	else
	{
		DE_FATAL("Unsupported shader stage");
	}
}

void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
{
	std::string bdyStr = getBodySource(caseDef);
	std::string helperStrARB = getHelperFunctionARB(caseDef);

	const string extensionHeader =  (caseDef.extShaderSubGroupBallotTests ?	"#extension GL_ARB_shader_ballot: enable\n"
																			"#extension GL_KHR_shader_subgroup_basic: enable\n"
																			"#extension GL_ARB_gpu_shader_int64: enable\n"
																		:	"#extension GL_KHR_shader_subgroup_ballot: enable\n");

	if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
	{
		std::ostringstream src;

		src << "#version 450\n"
			<< extensionHeader.c_str()
			<< subgroups::getAdditionalExtensionForFormat(caseDef.format)
			<< "layout (local_size_x_id = 0, local_size_y_id = 1, "
			"local_size_z_id = 2) in;\n"
			<< "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
			<< "{\n"
{'fraction_non_alphanumeric': 0.18012717913224036, 'fraction_numerical': 0.01263139680754423, 'mean_word_length': 3.4160458452722064, 'pattern_counts': {'":': 0, '<': 811, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1796462', 'n_tokens_mistral': 9432, 'n_tokens_neox': 8355, 'n_words': 1517}