148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*-------------------------------------------------------------------------
248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * OpenGL Conformance Test Suite
348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * -----------------------------
448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Copyright (c) 2014-2016 The Khronos Group Inc.
648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Licensed under the Apache License, Version 2.0 (the "License");
848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * you may not use this file except in compliance with the License.
948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * You may obtain a copy of the License at
1048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
1148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *      http://www.apache.org/licenses/LICENSE-2.0
1248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
1348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Unless required by applicable law or agreed to in writing, software
1448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * distributed under the License is distributed on an "AS IS" BASIS,
1548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * See the License for the specific language governing permissions and
1748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * limitations under the License.
1848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
1984322c9402f810da3cd80b52e9f9ef72150a9004Alexander Galazin */ /*!
2048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * \file
2148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * \brief
2284322c9402f810da3cd80b52e9f9ef72150a9004Alexander Galazin */ /*-------------------------------------------------------------------*/
2348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
2448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "glwEnums.hpp"
2548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
2648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "gluContextInfo.hpp"
2748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuRenderTarget.hpp"
2848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuVectorUtil.hpp"
2948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include <assert.h>
3048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include <map>
3148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
3248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "es31cExplicitUniformLocationTest.hpp"
3348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
3448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosnamespace glcts
3548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
3648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosusing namespace glw;
3748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosnamespace
3848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
3948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
4048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass Logger
4148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
4248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
4348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Logger() : null_log_(0)
4448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
4548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
4648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
4748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Logger(const Logger& rhs)
4848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
4948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		null_log_ = rhs.null_log_;
5048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!null_log_)
5148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
5248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			str_ << rhs.str_.str();
5348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
5448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
5548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
5648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	~Logger()
5748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
5848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s_tcuLog->writeMessage(str_.str().c_str());
5948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!str_.str().empty())
6048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
6148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s_tcuLog->writeMessage(NL);
6248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
6348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
6448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
6548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	template <class T>
6648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Logger& operator<<(const T& t)
6748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
6848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!null_log_)
6948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
7048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			str_ << t;
7148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
7248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return *this;
7348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
7448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
7548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static tcu::TestLog* Get()
7648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
7748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s_tcuLog;
7848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
7948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
8048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static void setOutput(tcu::TestLog& log)
8148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
8248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s_tcuLog = &log;
8348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
8448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
8548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
8648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void				 operator=(const Logger&);
8748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool				 null_log_;
8848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::ostringstream   str_;
8948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static tcu::TestLog* s_tcuLog;
9048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
9148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostcu::TestLog* Logger::s_tcuLog = NULL;
9248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
9348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass DefOccurence
9448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
9548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
9648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	enum DefOccurenceEnum
9748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
9848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ALL_SH,
9948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		VSH,
10048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		FSH_OR_CSH, //"one shader"
10148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ALL_BUT_FSH,
10248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ALL_BUT_VSH,
10348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		NONE_SH,
10448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	} occurence;
10548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
10648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	DefOccurence(DefOccurenceEnum _occurence) : occurence(_occurence)
10748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
10848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
10948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
11048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool occurs(GLenum shader) const
11148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
11248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (occurence == NONE_SH)
11348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
11448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return false;
11548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
11648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (occurence == ALL_SH)
11748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
11848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return true;
11948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
12048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (occurence == FSH_OR_CSH)
12148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
12248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return shader == GL_FRAGMENT_SHADER || shader == GL_COMPUTE_SHADER;
12348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
12448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (occurence == VSH)
12548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
12648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return shader == GL_VERTEX_SHADER;
12748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
12848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (occurence == ALL_BUT_FSH)
12948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
13048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return shader != GL_FRAGMENT_SHADER;
13148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
13248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (occurence == ALL_BUT_VSH)
13348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
13448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return shader != GL_VERTEX_SHADER;
13548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
13648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		assert(0);
13748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return false;
13848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
13948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
14048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
14148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass LocationSpecifier
14248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
14348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
14448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass IndexSpecifier
14548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
14648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
14748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
14848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass LayoutSpecifierBase
14948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
15048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
15148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	enum NumSys
15248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
15348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		Dec,
15448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		Oct,
15548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		Hex,
15648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	};
15748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
15848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutSpecifierBase(int _val, NumSys _numSys, DefOccurence _occurence)
15948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: val(_val), numSys(_numSys), occurence(_occurence)
16048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
16148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
16248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
16348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool isImplicit(const std::vector<GLenum> stages) const
16448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
16548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bool implicit = true;
16648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < stages.size(); i++)
16748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
16848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			implicit &= !occurence.occurs(stages[i]);
16948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
17048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
17148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return implicit;
17248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
17348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
17448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int			 val;
17548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	NumSys		 numSys;
17648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	DefOccurence occurence;
17748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
17848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
17948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostemplate <class T>
18048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass LayoutSpecifier : public LayoutSpecifierBase
18148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
18248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
18348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutSpecifier(int _val, NumSys _numSys, DefOccurence _occurence) : LayoutSpecifierBase(_val, _numSys, _occurence)
18448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
18548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
18648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
18748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static LayoutSpecifier<T> C(int _val, NumSys _sys = Dec)
18848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
18948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutSpecifier<T>(_val, _sys, DefOccurence::ALL_SH);
19048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
19148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
19248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static LayoutSpecifier<T> C(int _val, DefOccurence _occurence)
19348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
19448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutSpecifier<T>(_val, Dec, _occurence);
19548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
19648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
19748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static LayoutSpecifier<T> Implicit()
19848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
19948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutSpecifier<T>(1999999, Dec, DefOccurence::NONE_SH);
20048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
20148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
20248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void streamDefinition(std::ostringstream& str, GLenum shader) const;
20348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
20448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
20548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostypedef LayoutSpecifier<LocationSpecifier> Loc;
20648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostypedef LayoutSpecifier<IndexSpecifier>	Index;
20748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
20848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostemplate <>
20948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosvoid LayoutSpecifier<LocationSpecifier>::streamDefinition(std::ostringstream& str, GLenum shader) const
21048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
21148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (val < 0 || !occurence.occurs(shader))
21248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
21348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return;
21448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
21548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
21648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	str << "layout(location = ";
21748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (numSys == Loc::Oct)
21848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
21948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		str << std::oct << "0";
22048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
22148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	else if (numSys == Loc::Hex)
22248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
22348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		str << std::hex << "0x";
22448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
22548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	str << val << std::dec << ") ";
22648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
22748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
22848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostemplate <>
22948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosvoid LayoutSpecifier<IndexSpecifier>::streamDefinition(std::ostringstream& str, GLenum shader) const
23048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
23148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (val < 0 || !occurence.occurs(shader))
23248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
23348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return;
23448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
23548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
23648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	str << "layout(index = ";
23748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (numSys == Loc::Oct)
23848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
23948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		str << std::oct << "0";
24048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
24148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	else if (numSys == Loc::Hex)
24248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
24348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		str << std::hex << "0x";
24448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
24548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	str << val << std::dec << ") ";
24648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
24748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
24848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformStructCounter
24948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
25048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
25148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformStructCounter() : counter(0)
25248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
25348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
25448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GLint getNextCount()
25548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
25648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return counter++;
25748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
25848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
25948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
26048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformStructCounter(const UniformStructCounter&);
26148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GLint counter;
26248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
26348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
26448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformType
26548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
26648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
26748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformType(GLenum _enumType, int _arraySize = 0)
26848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: enumType(_enumType), arraySize(_arraySize), isArray(_arraySize > 0), signedType(true)
26948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
27048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!arraySize)
27148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
27248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			arraySize = 1;
27348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
27448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		arraySizesSegmented.push_back(arraySize);
27548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		fill();
27648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
27748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformType(GLenum _enumType, const std::vector<int>& _arraySizesSegmented)
27848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: enumType(_enumType), arraySizesSegmented(_arraySizesSegmented), isArray(true), signedType(true)
27948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
28048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		arraySize = 1;
28148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < arraySizesSegmented.size(); i++)
28248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
28348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			assert(arraySizesSegmented[i] > 0);
28448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			arraySize *= arraySizesSegmented[i];
28548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
28648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		fill();
28748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
28848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformType(UniformStructCounter& structCounter, std::vector<UniformType> _childTypes, int _arraySize = 0)
28948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: enumType(0), arraySize(_arraySize), childTypes(_childTypes), isArray(_arraySize > 0), signedType(true)
29048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
29148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		baseType = 0;
29248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream _str;
29348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		_str << "S" << structCounter.getNextCount();
29448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		strType = _str.str();
29548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!arraySize)
29648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
29748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			arraySize = 1;
29848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
29948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		arraySizesSegmented.push_back(arraySize);
30048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
30148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
30248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	inline const std::string& str() const
30348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
30448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return strType;
30548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
30648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
30748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	inline const std::string& refStr() const
30848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
30948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return refStrType;
31048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
31148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
31248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool isStruct() const
31348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
31448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return (baseType == 0);
31548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
31648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
31748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool isSigned() const
31848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
31948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return signedType;
32048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
32148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
32248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const char* abs() const
32348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
32448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (baseType)
32548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
32648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT:
32748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_SAMPLER:
32848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return "0.1";
32948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_UNSIGNED_INT:
33048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return "0u";
33148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_INT:
33248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return "0";
33348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
33448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			assert(0);
33548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return "";
33648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
33748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
33848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
33948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::pair<int, int> getSize() const
34048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
34148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return size;
34248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
34348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
34448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GLenum getBaseType() const
34548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
34648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return baseType;
34748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
34848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
34948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void streamArrayStr(std::ostringstream& _str, int arrayElem = -1) const
35048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
35148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!isArray)
35248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
35348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return;
35448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
35548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (arrayElem < 0)
35648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
35748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t segment = 0; segment < arraySizesSegmented.size(); segment++)
35848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
35948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				_str << "[" << arraySizesSegmented[segment] << "]";
36048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
36148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
36248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
36348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
36448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			int tailSize = arraySize;
36548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t segment = 0; segment < arraySizesSegmented.size(); segment++)
36648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
36748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				tailSize /= arraySizesSegmented[segment];
36848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				_str << "[" << arrayElem / tailSize << "]";
36948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				arrayElem %= tailSize;
37048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
37148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
37248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
37348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
37448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GLenum enumType;
37548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
37648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//arrays-of-arrays size
37748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<int> arraySizesSegmented;
37848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
37948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//premultiplied array size
38048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int arraySize;
38148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
38248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//child types for nested (struct) types;
38348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<UniformType> childTypes;
38448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
38548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
38648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void fill()
38748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
38848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
38948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		size = std::pair<int, int>(1, 1);
39048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
39148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (enumType)
39248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
39348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_SAMPLER_2D:
39448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = "vec4";
39548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			strType	= "sampler2D";
39648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType   = GL_SAMPLER;
39748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
39848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT:
39948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = strType = "float";
40048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType			 = GL_FLOAT;
40148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
40248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_INT:
40348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = strType = "int";
40448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType			 = GL_INT;
40548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
40648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_UNSIGNED_INT:
40748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = strType = "uint";
40848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType			 = GL_UNSIGNED_INT;
40948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			signedType			 = false;
41048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
41148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT_VEC2:
41248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = strType = "vec2";
41348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType			 = GL_FLOAT;
41448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first			 = 2;
41548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
41648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT_VEC3:
41748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = strType = "vec3";
41848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType			 = GL_FLOAT;
41948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first			 = 3;
42048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
42148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT_VEC4:
42248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = strType = "vec4";
42348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType			 = GL_FLOAT;
42448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first			 = 4;
42548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
42648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT_MAT2:
42748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			strType	= "mat2";
42848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = "vec2";
42948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType   = GL_FLOAT;
43048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first = size.second = 2;
43148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
43248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT_MAT3:
43348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			strType	= "mat3";
43448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = "vec3";
43548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType   = GL_FLOAT;
43648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first = size.second = 3;
43748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
43848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT_MAT4:
43948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			strType	= "mat4";
44048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = "vec4";
44148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType   = GL_FLOAT;
44248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first = size.second = 4;
44348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
44448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT_MAT2x3:
44548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			strType		= "mat2x3";
44648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType  = "vec3";
44748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType	= GL_FLOAT;
44848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first  = 3;
44948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.second = 2;
45048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
45148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT_MAT4x3:
45248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			strType		= "mat4x3";
45348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType  = "vec3";
45448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType	= GL_FLOAT;
45548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first  = 3;
45648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.second = 4;
45748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
45848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT_MAT2x4:
45948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			strType		= "mat2x4";
46048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType  = "vec4";
46148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType	= GL_FLOAT;
46248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first  = 4;
46348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.second = 2;
46448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
46548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT_MAT3x4:
46648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			strType		= "mat3x4";
46748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType  = "vec4";
46848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType	= GL_FLOAT;
46948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first  = 4;
47048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.second = 3;
47148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
47248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT_MAT3x2:
47348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			strType		= "mat3x2";
47448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType  = "vec2";
47548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType	= GL_FLOAT;
47648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first  = 2;
47748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.second = 3;
47848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
47948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FLOAT_MAT4x2:
48048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			strType		= "mat4x2";
48148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType  = "vec2";
48248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType	= GL_FLOAT;
48348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first  = 2;
48448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.second = 4;
48548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
48648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_INT_VEC2:
48748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = strType = "ivec2";
48848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType			 = GL_INT;
48948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first			 = 2;
49048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
49148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_INT_VEC3:
49248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = strType = "ivec3";
49348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType			 = GL_INT;
49448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first			 = 3;
49548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
49648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_INT_VEC4:
49748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			refStrType = strType = "ivec4";
49848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			baseType			 = GL_INT;
49948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			size.first			 = 4;
50048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
50148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
50248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			assert(0);
50348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
50448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
50548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
50648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::string strType, refStrType;
50748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::pair<int, int> size;
50848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GLenum baseType;
50948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool   isArray;
51048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool   signedType;
51148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
51248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
51348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformValueGenerator
51448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
51548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
51648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformValueGenerator() : fValue(0.0f), iValue(0)
51748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
51848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
51948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GLfloat genF()
52048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
52148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (fValue > 99999.0f)
52248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
52348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			fValue = 0.0f;
52448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
52548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return (fValue += 1.0f);
52648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
52748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GLint genI()
52848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
52948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return (iValue += 1);
53048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
53148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
53248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
53348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformValueGenerator(const UniformValueGenerator&);
53448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GLfloat fValue;
53548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GLint   iValue;
53648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
53748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
53848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformValue
53948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
54048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
54148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void streamValue(std::ostringstream& str, int arrayElement = 0, int column = 0) const
54248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
54348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int arrayElementSize = type.getSize().first * type.getSize().second;
54448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
54548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		str << type.refStr() << "(";
54648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
54748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (type.getBaseType() == GL_SAMPLER)
54848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
54948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t elem = 0; elem < 4; elem++)
55048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
55148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (elem)
55248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					str << ", ";
55348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				str << fValues[arrayElement * 4 + elem];
55448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
55548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			str << ")";
55648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return;
55748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
55848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
55948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int elem = 0; fValues.size() && elem < type.getSize().first; elem++)
56048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
56148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (elem)
56248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				str << ", ";
56348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			str << fValues[arrayElement * arrayElementSize + column * type.getSize().first + elem] << ".0";
56448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
56548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int elem = 0; iValues.size() && elem < type.getSize().first; elem++)
56648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
56748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (elem)
56848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				str << ", ";
56948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			str << iValues[arrayElement * arrayElementSize + elem];
57048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
57148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int elem = 0; uValues.size() && elem < type.getSize().first; elem++)
57248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
57348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (elem)
57448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				str << ", ";
57548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			str << uValues[arrayElement * arrayElementSize + elem] << "u";
57648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
57748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		str << ")";
57848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
57948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
58048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const void* getPtr(int arrayElement) const
58148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
58248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int arrayElementSize = type.getSize().first * type.getSize().second;
58348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (type.getBaseType() == GL_INT || type.getBaseType() == GL_SAMPLER)
58448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
58548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return &iValues[arrayElement * arrayElementSize];
58648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
58748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else if (type.getBaseType() == GL_UNSIGNED_INT)
58848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
58948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return &uValues[arrayElement * arrayElementSize];
59048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
59148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else if (type.getBaseType() == GL_FLOAT)
59248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
59348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return &fValues[arrayElement * arrayElementSize];
59448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
59548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		assert(0);
59648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return NULL;
59748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
59848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
59948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformValue(const UniformType& _type, UniformValueGenerator& generator) : type(_type)
60048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
60148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const int sizeRow	= type.getSize().first;
60248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const int sizeColumn = type.getSize().second;
60348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
60448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (type.isStruct())
60548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
60648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return;
60748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
60848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
60948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (type.getBaseType() == GL_INT)
61048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
61148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			assert(sizeColumn == 1);
61248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			iValues.resize(sizeRow * type.arraySize);
61348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t elem = 0; elem < iValues.size(); elem++)
61448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
61548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				iValues[elem] = generator.genI();
61648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
61748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
61848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else if (type.getBaseType() == GL_UNSIGNED_INT)
61948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
62048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			assert(sizeColumn == 1);
62148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			uValues.resize(sizeRow * type.arraySize);
62248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t elem = 0; elem < uValues.size(); elem++)
62348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
62448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				uValues[elem] = static_cast<GLuint>(generator.genI());
62548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
62648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
62748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else if (type.getBaseType() == GL_FLOAT)
62848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
62948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			fValues.resize(sizeColumn * sizeRow * type.arraySize);
63048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t elem = 0; elem < fValues.size(); elem++)
63148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
63248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				fValues[elem] = generator.genF();
63348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
63448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
63548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else if (type.getBaseType() == GL_SAMPLER)
63648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
63748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//color ref value
63848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			fValues.resize(4 * type.arraySize);
63948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t elem = 0; elem < fValues.size(); elem++)
64048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
64148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				fValues[elem] = float(elem) / float(fValues.size());
64248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
64348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//uniform value
64448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			iValues.resize(type.arraySize);
64548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t elem = 0; elem < iValues.size(); elem++)
64648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
64748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				iValues[elem] = generator.genI() % 16;
64848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
64948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
65048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
65148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
65248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			assert(0);
65348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
65448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
65548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
65648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<GLfloat> fValues;
65748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<GLint>   iValues;
65848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<GLint>   uValues;
65948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
66048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
66148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformType type;
66248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
66348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
66448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass Uniform
66548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
66648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
66748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Uniform(UniformValueGenerator& generator, UniformType _type, Loc _location,
66848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DefOccurence _declOccurence = DefOccurence::ALL_SH, DefOccurence _usageOccurence = DefOccurence::ALL_SH)
66948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: type(_type)
67048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, location(_location)
67148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, declOccurence(_declOccurence)
67248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, usageOccurence(_usageOccurence)
67348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, value(_type, generator)
67448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
67548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
67648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (type.isStruct())
67748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
67848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			int currentLocation = location.val;
67948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int arrayElem = 0; arrayElem < type.arraySize; arrayElem++)
68048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
68148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				for (size_t child = 0; child < type.childTypes.size(); child++)
68248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
68348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					Loc childLocation = Loc::Implicit();
68448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (currentLocation > 0)
68548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
68648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						childLocation = Loc::C(currentLocation);
68748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
68848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					childUniforms.push_back(
68948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						Uniform(generator, type.childTypes[child], childLocation, declOccurence, usageOccurence));
69048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					currentLocation += type.childTypes[child].arraySize;
69148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
69248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
69348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
69448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
69548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
69648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void setName(const std::string& parentName, const std::string& _name)
69748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
69848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		shortName = _name;
69948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
70048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::ostringstream __name;
70148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			__name << parentName << _name;
70248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			name = __name.str();
70348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
70448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (type.isStruct())
70548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
70648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t i = 0; i < childUniforms.size(); i++)
70748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
70848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				std::ostringstream childName;
70948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				childName << "m" << (i % (childUniforms.size() / type.arraySize));
71048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				std::ostringstream childParentName;
71148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				childParentName << name;
71248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				type.streamArrayStr(childParentName, (int)(i / type.arraySize));
71348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				childParentName << ".";
71448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				childUniforms[i].setName(childParentName.str(), childName.str());
71548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
71648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
71748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
71848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const std::string& getName() const
71948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
72048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return name;
72148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
72248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
72348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void streamDefinition(std::ostringstream& str) const
72448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
72548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		str << type.str() << " " << shortName;
72648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		type.streamArrayStr(str);
72748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
72848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
72948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformType  type;
73048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Loc			 location;
73148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	DefOccurence declOccurence, usageOccurence;
73248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformValue value;
73348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
73448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<Uniform> childUniforms;
73548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::string			 name, shortName;
73648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
73748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
73848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineFunction
73948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
74048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
74148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	SubroutineFunction(UniformValueGenerator& generator, Index _index = Index::Implicit())
74248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: index(_index), embeddedRetVal(GL_FLOAT_VEC4, generator)
74348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
74448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
74548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const UniformValue& getRetVal() const
74648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
74748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return embeddedRetVal;
74848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
74948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
75048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	inline const std::string& getName() const
75148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
75248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return name;
75348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
75448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
75548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void setName(int _name)
75648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
75748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream __name;
75848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		__name << "sf" << _name;
75948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		name = __name.str();
76048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
76148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
76248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Index index;
76348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
76448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
76548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformValue embeddedRetVal;
76648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::string  name;
76748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
76848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
76948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineFunctionSet
77048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
77148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
77248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	SubroutineFunctionSet(UniformValueGenerator& generator, size_t count = 0) : fn(count, SubroutineFunction(generator))
77348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
77448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
77548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
77648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void push_back(const SubroutineFunction& _fn)
77748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
77848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		fn.push_back(_fn);
77948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
78048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
78148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	inline const std::string& getTypeName() const
78248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
78348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return typeName;
78448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
78548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
78648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void setTypeName(int _name)
78748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
78848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream __name;
78948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		__name << "st" << _name;
79048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		typeName = __name.str();
79148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
79248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
79348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<SubroutineFunction> fn;
79448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::string						typeName;
79548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
79648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
79748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineUniform
79848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
79948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
80048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	SubroutineUniform(UniformValueGenerator& generator, SubroutineFunctionSet& _functions, Loc _location,
80148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					  int _arraySize = 0, DefOccurence _defOccurence = DefOccurence::ALL_SH, bool _used = true)
80248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: functions(_functions)
80348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, location(_location)
80448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, arraySize(_arraySize)
80548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, defOccurence(_defOccurence)
80648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, used(_used)
80748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, embeddedUIntUniform(GL_UNSIGNED_INT, generator)
80848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
80948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
81048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		assert(arraySize >= 0);
81148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
81248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!arraySize)
81348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
81448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			arraySize = 1;
81548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			isArray   = false;
81648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
81748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
81848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
81948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			isArray = true;
82048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
82148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
82248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		arraySizesSegmented.push_back(arraySize);
82348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
82448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		embeddedUIntUniform = UniformValue(UniformType(GL_UNSIGNED_INT, arraySize), generator);
82548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int i = 0; i < arraySize; i++)
82648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
82748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			embeddedUIntUniform.uValues[i] = static_cast<GLint>(embeddedUIntUniform.uValues[i] % functions.fn.size());
82848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
82948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
83048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
83148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	SubroutineUniform(UniformValueGenerator& generator, SubroutineFunctionSet& _functions, Loc _location,
83248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					  std::vector<int> _arraySizesSegmented, DefOccurence _defOccurence = DefOccurence::ALL_SH,
83348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					  bool _used = true)
83448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: functions(_functions)
83548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, location(_location)
83648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, defOccurence(_defOccurence)
83748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, used(_used)
83848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, arraySizesSegmented(_arraySizesSegmented)
83948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, isArray(true)
84048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, embeddedUIntUniform(GL_UNSIGNED_INT, generator)
84148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
84248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
84348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		arraySize = 1;
84448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < arraySizesSegmented.size(); i++)
84548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
84648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			assert(arraySizesSegmented[i] > 0);
84748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			arraySize *= arraySizesSegmented[i];
84848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
84948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
85048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		embeddedUIntUniform = UniformValue(UniformType(GL_UNSIGNED_INT, arraySize), generator);
85148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int i = 0; i < arraySize; i++)
85248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
85348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			embeddedUIntUniform.uValues[i] = static_cast<GLint>(embeddedUIntUniform.uValues[i] % functions.fn.size());
85448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
85548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
85648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void setName(const std::string& _name)
85748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
85848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		name = _name;
85948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
86048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
86148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const std::string& getName() const
86248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
86348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return name;
86448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
86548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
86648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void streamArrayStr(std::ostringstream& str, int arrayElem = -1) const
86748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
86848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!isArray)
86948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
87048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return;
87148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
87248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (arrayElem < 0)
87348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
87448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t segment = 0; segment < arraySizesSegmented.size(); segment++)
87548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
87648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				str << "[" << arraySizesSegmented[segment] << "]";
87748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
87848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
87948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
88048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
88148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			int tailSize = arraySize;
88248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t segment = 0; segment < arraySizesSegmented.size(); segment++)
88348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
88448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				tailSize /= arraySizesSegmented[segment];
88548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				str << "[" << arrayElem / tailSize << "]";
88648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				arrayElem %= tailSize;
88748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
88848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
88948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
89048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
89148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const SubroutineFunction& getSelectedFunction(int arrayElem) const
89248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
89348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		assert(arrayElem < arraySize);
89448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return functions.fn[embeddedUIntUniform.uValues[arrayElem]];
89548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
89648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
89748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	SubroutineFunctionSet functions;
89848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Loc					  location;
89948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int					  arraySize;
90048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	DefOccurence		  defOccurence;
90148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool				  used;
90248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
90348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
90448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<int> arraySizesSegmented;
90548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool			 isArray;
90648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformValue	 embeddedUIntUniform;
90748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
90848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::string name;
90948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
91048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
91148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ShaderKey
91248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
91348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
91448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ShaderKey()
91548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
91648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
91748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ShaderKey(GLenum _stage, const std::string& _input, const std::string& _output)
91848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: stage(_stage), input(_input), output(_output)
91948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
92048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
92148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GLenum		stage;
92248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::string input, output;
92348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
92448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool operator<(const ShaderKey& rhs) const
92548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
92648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (stage == rhs.stage)
92748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
92848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (input == rhs.input)
92948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
93048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return (output < rhs.output);
93148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
93248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return input < rhs.input;
93348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
93448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return stage < rhs.stage;
93548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
93648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
93748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
93848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass CompiledProgram
93948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
94048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
94148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GLuint				name;
94248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<GLenum> stages;
94348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
94448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
94548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ShaderSourceFactory
94648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
94748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
94848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static void streamUniformDefinitions(const std::vector<Uniform>& uniforms, GLenum shader, std::ostringstream& ret)
94948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
95048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < uniforms.size(); i++)
95148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
95248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (uniforms[i].declOccurence.occurs(shader))
95348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
95448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (uniforms[i].type.isStruct())
95548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
95648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret << "struct " << uniforms[i].type.str() << " {" << std::endl;
95748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					for (size_t child = 0; child < uniforms[i].childUniforms.size() / uniforms[i].type.arraySize;
95848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						 child++)
95948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
96048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						ret << "    ";
96148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						uniforms[i].childUniforms[child].streamDefinition(ret);
96248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						ret << ";" << std::endl;
96348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
96448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret << "};" << std::endl;
96548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
96648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				uniforms[i].location.streamDefinition(ret, shader);
96748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret << "uniform ";
96848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				uniforms[i].streamDefinition(ret);
96948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret << ";" << std::endl;
97048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
97148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
97248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
97348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
97448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static void streamSubroutineDefinitions(const std::vector<SubroutineUniform>& subroutineUniforms, GLenum shader,
97548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											std::ostringstream& ret)
97648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
97748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (subroutineUniforms.size())
97848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
97948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//add a "zero" uniform;
98048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ret << "uniform float zero;" << std::endl;
98148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
98248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
98348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < subroutineUniforms.size(); i++)
98448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
98548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (subroutineUniforms[i].defOccurence.occurs(shader))
98648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
98748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
98848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				//subroutine vec4 st0(float param);
98948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret << "subroutine vec4 " << subroutineUniforms[i].functions.getTypeName() << "(float param);"
99048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					<< std::endl;
99148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
99248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				for (size_t fn = 0; fn < subroutineUniforms[i].functions.fn.size(); fn++)
99348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
99448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					//layout(index = X) subroutine(st0) vec4 sf0(float param) { .... };
99548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					subroutineUniforms[i].functions.fn[fn].index.streamDefinition(ret, shader);
99648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret << "subroutine(" << subroutineUniforms[i].functions.getTypeName() << ") vec4 "
99748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						<< subroutineUniforms[i].functions.fn[fn].getName() << "(float param) { return zero + ";
99848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					subroutineUniforms[i].functions.fn[fn].getRetVal().streamValue(ret);
99948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret << "; }" << std::endl;
100048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
100148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
100248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				//layout(location = X) subroutine uniform stX uX[...];
100348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				subroutineUniforms[i].location.streamDefinition(ret, shader);
100448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret << "subroutine uniform " << subroutineUniforms[i].functions.getTypeName() << " "
100548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					<< subroutineUniforms[i].getName();
100648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				subroutineUniforms[i].streamArrayStr(ret);
100748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret << ";" << std::endl;
100848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
100948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
101048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
101148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
101248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static void streamUniformValidator(std::ostringstream& ret, const Uniform& uniform, GLenum shader,
101348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									   const char* outTemporary)
101448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
101548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (uniform.declOccurence.occurs(shader) && uniform.usageOccurence.occurs(shader))
101648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
101748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (uniform.type.isStruct())
101848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
101948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				for (size_t child = 0; child < uniform.childUniforms.size(); child++)
102048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
102148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					streamUniformValidator(ret, uniform.childUniforms[child], shader, outTemporary);
102248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
102348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
102448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			else
102548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
102648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				for (int arrayElement = 0; arrayElement < uniform.type.arraySize; arrayElement++)
102748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
102848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					for (int column = 0; column < uniform.type.getSize().second; column++)
102948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
103048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						std::string columnIndex;
103148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						if (uniform.type.getSize().second > 1)
103248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						{
103348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							std::ostringstream str;
103448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							str << "[" << column << "]";
103548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							columnIndex = str.str();
103648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						}
103748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						std::string absoluteF;
103848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						if (uniform.type.isSigned())
103948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						{
104048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							absoluteF = "abs";
104148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						}
104248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
104348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						if (uniform.type.getBaseType() == GL_SAMPLER)
104448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						{
104548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							ret << NL "    if (any(greaterThan(" << absoluteF << "(texture(" << uniform.getName();
104648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							uniform.type.streamArrayStr(ret, arrayElement);
104748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							ret << columnIndex << ", vec2(0.5)) - ";
104848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							uniform.value.streamValue(ret, arrayElement, column);
104948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							ret << " ), " << uniform.type.refStr() << "(" << uniform.type.abs() << ")))) {";
105048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						}
105148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						else if (uniform.type.getSize().first > 1)
105248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						{
105348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							ret << NL "    if (any(greaterThan(" << absoluteF << "(" << uniform.getName();
105448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							uniform.type.streamArrayStr(ret, arrayElement);
105548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							ret << columnIndex << " - ";
105648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							uniform.value.streamValue(ret, arrayElement, column);
105748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							ret << "), " << uniform.type.refStr() << "(" << uniform.type.abs() << ")))) {";
105848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						}
105948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						else
106048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						{
106148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							ret << NL "    if (" << absoluteF << "(" << uniform.getName();
106248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							uniform.type.streamArrayStr(ret, arrayElement);
106348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							ret << " - ";
106448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							uniform.value.streamValue(ret, arrayElement);
106548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							ret << ") >" << uniform.type.refStr() << "(" << uniform.type.abs() << ")) {";
106648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						}
106748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						ret << NL "       " << outTemporary << " = vec4 (1.0, 0.0, 0.0, 1.0);";
106848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						ret << NL "    }";
106948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
107048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
107148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
107248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
107348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
107448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
107548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static void streamUniformValidators(std::ostringstream& ret, const std::vector<Uniform>& uniforms, GLenum shader,
107648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										const char* outTemporary)
107748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
107848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < uniforms.size(); i++)
107948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
108048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			streamUniformValidator(ret, uniforms[i], shader, outTemporary);
108148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
108248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
108348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
108448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static void streamSubroutineValidator(std::ostringstream& ret, const SubroutineUniform& subroutineUniform,
108548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										  GLenum shader, const char* outTemporary)
108648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
108748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (subroutineUniform.defOccurence.occurs(shader) && subroutineUniform.used)
108848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
108948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int arrayElem = 0; arrayElem < subroutineUniform.arraySize; arrayElem++)
109048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
109148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret << NL "    if (any(greaterThan(abs(" << subroutineUniform.getName();
109248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				subroutineUniform.streamArrayStr(ret, arrayElem);
109348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret << "(zero) - ";
109448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				subroutineUniform.getSelectedFunction(arrayElem).getRetVal().streamValue(ret);
109548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret << "), vec4(0.1)))) {";
109648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret << NL "       " << outTemporary << " = vec4 (1.0, 0.0, 0.0, 1.0);";
109748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret << NL "    }";
109848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
109948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
110048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
110148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
110248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static void streamSubroutineValidators(std::ostringstream&					 ret,
110348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										   const std::vector<SubroutineUniform>& subroutineUniforms, GLenum shader,
110448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										   const char* outTemporary)
110548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
110648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < subroutineUniforms.size(); i++)
110748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
110848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			streamSubroutineValidator(ret, subroutineUniforms[i], shader, outTemporary);
110948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
111048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
111148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
111248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static void streamShaderHeader(std::ostringstream& str, const glu::ContextType type)
111348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
111448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (glu::isContextTypeES(type))
111548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
111648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			str << "#version 310 es" NL "precision highp float;" NL "precision highp int;";
111748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
111848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
111948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
112048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			str << "#version 430 core" NL;
112148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
112248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
112348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
112448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static std::string generateFragmentShader(const ShaderKey& key, const std::vector<Uniform>& uniforms,
112548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											  const std::vector<SubroutineUniform>& subroutineUniforms,
112648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											  const std::string& additionalDef, const glu::ContextType type)
112748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
112848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
112948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream ret;
113048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamShaderHeader(ret, type);
113148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL;
113248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamUniformDefinitions(uniforms, GL_FRAGMENT_SHADER, ret);
113348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL;
113448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamSubroutineDefinitions(subroutineUniforms, GL_FRAGMENT_SHADER, ret);
113548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL << additionalDef << NL "in vec4 " << key.input << ";" << NL "out vec4 out_FragColor;"
113648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			<< NL "void main() {" << NL "    vec4 validationResult = " << key.input << ";" << NL;
113748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamUniformValidators(ret, uniforms, GL_FRAGMENT_SHADER, "validationResult");
113848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL;
113948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamSubroutineValidators(ret, subroutineUniforms, GL_FRAGMENT_SHADER, "validationResult");
114048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL "    out_FragColor =  validationResult;" << NL "}";
114148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
114248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret.str();
114348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
114448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
114548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static std::string generateVertexShader(const ShaderKey& key, const std::vector<Uniform>& uniforms,
114648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											const std::vector<SubroutineUniform>& subroutineUniforms,
114748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											const std::string& additionalDef, const glu::ContextType type)
114848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
114948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
115048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream ret;
115148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamShaderHeader(ret, type);
115248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL;
115348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamUniformDefinitions(uniforms, GL_VERTEX_SHADER, ret);
115448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL;
115548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamSubroutineDefinitions(subroutineUniforms, GL_VERTEX_SHADER, ret);
115648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL << additionalDef << NL "in vec4 in_Position;" << NL "out vec4 " << key.output << ";"
115748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			<< NL "void main() {" << NL "    vec4 validationResult = vec4(0.0, 1.0, 0.0, 1.0);" << NL;
115848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamUniformValidators(ret, uniforms, GL_VERTEX_SHADER, "validationResult");
115948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL;
116048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamSubroutineValidators(ret, subroutineUniforms, GL_VERTEX_SHADER, "validationResult");
116148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL "    " << key.output << " = validationResult;" << NL "    gl_Position = in_Position;" << NL "}";
116248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret.str();
116348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
116448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
116548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static std::string generateComputeShader(const ShaderKey&, const std::vector<Uniform>& uniforms,
116648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											 const std::vector<SubroutineUniform>& subroutineUniforms,
116748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											 const std::string& additionalDef, const glu::ContextType type)
116848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
116948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
117048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream ret;
117148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamShaderHeader(ret, type);
117248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL "layout (local_size_x = 1, local_size_y = 1) in;"
117348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			<< NL "layout (std430, binding = 1) buffer ResultBuffer {" << NL "    vec4 cs_ValidationResult;" << NL "};"
117448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			<< NL;
117548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamUniformDefinitions(uniforms, GL_COMPUTE_SHADER, ret);
117648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL;
117748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamSubroutineDefinitions(subroutineUniforms, GL_COMPUTE_SHADER, ret);
117848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL << additionalDef << NL "void main() {" << NL "    vec4 validationResult = vec4(0.0, 1.0, 0.0, 1.0);"
117948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			<< NL;
118048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamUniformValidators(ret, uniforms, GL_COMPUTE_SHADER, "validationResult");
118148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL;
118248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		streamSubroutineValidators(ret, subroutineUniforms, GL_COMPUTE_SHADER, "validationResult");
118348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret << NL "    cs_ValidationResult =  validationResult;" << NL "}";
118448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret.str();
118548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
118648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
118748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
118848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static std::string generateShader(const ShaderKey& key, const std::vector<Uniform>& uniforms,
118948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									  const std::vector<SubroutineUniform>& subroutineUniforms,
119048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									  const std::string& additionalDef, const glu::ContextType type)
119148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
119248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
119348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (key.stage)
119448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
119548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_VERTEX_SHADER:
119648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return generateVertexShader(key, uniforms, subroutineUniforms, additionalDef, type);
119748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FRAGMENT_SHADER:
119848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return generateFragmentShader(key, uniforms, subroutineUniforms, additionalDef, type);
119948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
120048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_COMPUTE_SHADER:
120148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return generateComputeShader(key, uniforms, subroutineUniforms, additionalDef, type);
120248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
120348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
120448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			assert(0);
120548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return "";
120648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
120748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
120848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
120948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
121048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ExplicitUniformLocationCaseBase : public glcts::SubcaseBase
121148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
121248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual std::string Title()
121348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
121448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "";
121548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
121648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual std::string Purpose()
121748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
121848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "";
121948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
122048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual std::string Method()
122148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
122248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "";
122348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
122448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual std::string PassCriteria()
122548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
122648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return "";
122748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
122848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
122948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int getWindowWidth()
123048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
123148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_context.getRenderContext().getRenderTarget().getWidth();
123248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
123348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
123448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int getWindowHeight()
123548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
123648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_context.getRenderContext().getRenderTarget().getHeight();
123748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
123848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
123948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::map<ShaderKey, GLuint> CreateShaders(const std::vector<std::vector<ShaderKey> >& programConfigs,
124048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											  const std::vector<Uniform>&			uniforms,
124148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											  const std::vector<SubroutineUniform>& subroutineUniforms,
124248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											  const std::string&					additionalDef)
124348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
124448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::map<ShaderKey, GLuint> ret;
124548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
124648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//create shaders
124748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t config = 0; config < programConfigs.size(); config++)
124848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
124948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t target = 0; target < programConfigs[config].size(); target++)
125048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
125148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
125248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (ret.find(programConfigs[config][target]) == ret.end())
125348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
125448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					GLuint shader = glCreateShader(programConfigs[config][target].stage);
125548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
125648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					std::string source = ShaderSourceFactory::generateShader(programConfigs[config][target], uniforms,
125748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos																			 subroutineUniforms, additionalDef,
125848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos																			 m_context.getRenderContext().getType());
125948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					const char* cSource[] = { source.c_str() };
126048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glShaderSource(shader, 1, cSource, NULL);
126148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret[programConfigs[config][target]] = shader;
126248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
126348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
126448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
126548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
126648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//compile shaders
126748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (std::map<ShaderKey, GLuint>::iterator i = ret.begin(); i != ret.end(); i++)
126848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
126948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glCompileShader(i->second);
127048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
127148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
127248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret;
127348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
127448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
127548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long CreatePrograms(std::vector<CompiledProgram>& programs, const std::vector<Uniform>& uniforms,
127648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						const std::vector<SubroutineUniform>& subroutineUniforms, const std::string& additionalDef,
127748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						bool negativeCompile, bool negativeLink)
127848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
127948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
128048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		long ret = NO_ERROR;
128148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
128248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<std::vector<ShaderKey> > programConfigs;
128348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
128448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::vector<ShaderKey> vsh_fsh(2);
128548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			vsh_fsh[0] = ShaderKey(GL_VERTEX_SHADER, "", "vs_ValidationResult");
128648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			vsh_fsh[1] = ShaderKey(GL_FRAGMENT_SHADER, "vs_ValidationResult", "");
128748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			programConfigs.push_back(vsh_fsh);
128848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
128948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
129048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::vector<ShaderKey> csh(1);
129148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			csh[0] = ShaderKey(GL_COMPUTE_SHADER, "", "");
129248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			programConfigs.push_back(csh);
129348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
129448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
129548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::map<ShaderKey, GLuint> shaders =
129648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			CreateShaders(programConfigs, uniforms, subroutineUniforms, additionalDef);
129748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
129848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//query compilation results
129948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (std::map<ShaderKey, GLuint>::iterator it = shaders.begin(); it != shaders.end(); it++)
130048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
130148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLint status;
130248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glGetShaderiv(it->second, GL_COMPILE_STATUS, &status);
130348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLchar infoLog[1000], source[4000];
130448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glGetShaderSource(it->second, 4000, NULL, source);
130548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glGetShaderInfoLog(it->second, 1000, NULL, infoLog);
130648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			Logger::Get()->writeKernelSource(source);
130748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			Logger::Get()->writeCompileInfo("shader", "", status == GL_TRUE, infoLog);
130848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
130948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!negativeLink)
131048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
131148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (!negativeCompile)
131248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
131348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (status != GL_TRUE)
131448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
131548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						Logger() << "Shader compilation failed";
131648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						ret |= ERROR;
131748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
131848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
131948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				else
132048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
132148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (status)
132248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
132348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						Logger() << "Negative compilation case failed: shader shoult not compile, but "
132448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									"GL_COMPILE_STATUS != 0";
132548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						ret |= ERROR;
132648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
132748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
132848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
132948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
133048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
133148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (negativeCompile)
133248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
133348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
133448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//delete shaders
133548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (std::map<ShaderKey, GLuint>::iterator it = shaders.begin(); it != shaders.end(); it++)
133648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
133748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				glDeleteShader(it->second);
133848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
133948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
134048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return ret;
134148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
134248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
134348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//assemble programs and link
134448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t config = 0; config < programConfigs.size(); config++)
134548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
134648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			CompiledProgram program;
134748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			program.name = glCreateProgram();
134848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
134948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t target = 0; target < programConfigs[config].size(); target++)
135048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
135148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
135248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				GLuint shader = shaders.find(programConfigs[config][target])->second;
135348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
135448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				glAttachShader(program.name, shader);
135548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
135648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				program.stages.push_back(programConfigs[config][target].stage);
135748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
135848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			programs.push_back(program);
135948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glLinkProgram(programs[config].name);
136048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
136148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t config = 0; config < programConfigs.size(); config++)
136248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
136348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glLinkProgram(programs[config].name);
136448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
136548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
136648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//delete shaders
136748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (std::map<ShaderKey, GLuint>::iterator it = shaders.begin(); it != shaders.end(); it++)
136848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
136948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glDeleteShader(it->second);
137048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
137148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
137248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//query link status:
137348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t config = 0; config < programConfigs.size(); config++)
137448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
137548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLint status;
137648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
137748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glGetProgramiv(programs[config].name, GL_LINK_STATUS, &status);
137848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLchar infoLog[1000];
137948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glGetProgramInfoLog(programs[config].name, 1000, NULL, infoLog);
138048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			Logger::Get()->writeCompileInfo("program", "", status == GL_TRUE, infoLog);
138148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
138248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!negativeLink)
138348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
138448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (status != GL_TRUE)
138548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
138648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					Logger() << "Shader link failed";
138748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret |= ERROR;
138848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
138948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
139048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			else
139148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
139248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (status)
139348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
139448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					Logger() << "Negative link case failed: program should not link, but GL_LINK_STATUS != 0";
139548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret |= ERROR;
139648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
139748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
139848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
139948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret;
140048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
140148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
140248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long DeletePrograms(std::vector<CompiledProgram>& programs)
140348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
140448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < programs.size(); i++)
140548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
140648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glDeleteProgram(programs[i].name);
140748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
140848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		programs.resize(0);
140948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return NO_ERROR;
141048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
141148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
141248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void setUniform(const Uniform& uniform, const CompiledProgram& program)
141348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
141448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
141548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bool used = false;
141648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < program.stages.size(); i++)
141748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
141848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			used |= uniform.declOccurence.occurs(program.stages[i]) && uniform.usageOccurence.occurs(program.stages[i]);
141948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
142048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!used)
142148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return;
142248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
142348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (uniform.type.isStruct())
142448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
142548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t j = 0; j < uniform.childUniforms.size(); j++)
142648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
142748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				setUniform(uniform.childUniforms[j], program);
142848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
142948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
143048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
143148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
143248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLint loc;
143348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (uniform.location.isImplicit(program.stages))
143448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
143548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				std::ostringstream name;
143648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				name << uniform.getName();
143748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				uniform.type.streamArrayStr(name, 0);
143848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				loc = glGetUniformLocation(program.name, name.str().c_str());
143948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
144048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			else
144148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
144248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				loc = uniform.location.val;
144348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
144448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
144548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int arrayElem = 0; arrayElem < uniform.type.arraySize; arrayElem++)
144648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
144748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				switch (uniform.type.enumType)
144848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
144948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT:
145048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniform1f(loc, *(GLfloat*)uniform.value.getPtr(arrayElem));
145148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
145248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT_VEC2:
145348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniform2fv(loc, 1, (GLfloat*)uniform.value.getPtr(arrayElem));
145448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
145548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT_VEC3:
145648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniform3fv(loc, 1, (GLfloat*)uniform.value.getPtr(arrayElem));
145748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
145848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT_VEC4:
145948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniform4fv(loc, 1, (GLfloat*)uniform.value.getPtr(arrayElem));
146048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
146148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT_MAT2:
146248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniformMatrix2fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
146348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
146448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT_MAT3:
146548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniformMatrix3fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
146648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
146748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT_MAT4:
146848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
146948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
147048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT_MAT2x3:
147148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniformMatrix2x3fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
147248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
147348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT_MAT4x3:
147448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniformMatrix4x3fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
147548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
147648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT_MAT2x4:
147748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniformMatrix2x4fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
147848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
147948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT_MAT3x4:
148048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniformMatrix3x4fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
148148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
148248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT_MAT3x2:
148348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniformMatrix3x2fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
148448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
148548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_FLOAT_MAT4x2:
148648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniformMatrix4x2fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
148748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
148848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_INT:
148948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_SAMPLER_2D:
149048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniform1i(loc, *(GLint*)uniform.value.getPtr(arrayElem));
149148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
149248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_INT_VEC2:
149348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniform2iv(loc, 1, (GLint*)uniform.value.getPtr(arrayElem));
149448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
149548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_INT_VEC3:
149648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniform3iv(loc, 1, (GLint*)uniform.value.getPtr(arrayElem));
149748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
149848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_INT_VEC4:
149948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniform4iv(loc, 1, (GLint*)uniform.value.getPtr(arrayElem));
150048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
150148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				case GL_UNSIGNED_INT:
150248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glUniform1ui(loc, *(GLuint*)uniform.value.getPtr(arrayElem));
150348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
150448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				default:
150548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					assert(0);
150648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
150748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				loc++;
150848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
150948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
151048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
151148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
151248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void setSubroutineUniform(const SubroutineUniform& subroutineUniform, const CompiledProgram& program, GLenum stage,
151348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							  std::vector<glw::GLuint>& indicesOut)
151448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
151548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bool used = subroutineUniform.defOccurence.occurs(stage) && subroutineUniform.used;
151648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (used)
151748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
151848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
151948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int arrayElem = 0; arrayElem < subroutineUniform.arraySize; arrayElem++)
152048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
152148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				GLint loc = -1;
152248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (subroutineUniform.location.isImplicit(program.stages))
152348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
152448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					std::ostringstream name;
152548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					name << subroutineUniform.getName();
152648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					subroutineUniform.streamArrayStr(name, arrayElem);
152748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					loc = glGetSubroutineUniformLocation(program.name, stage, name.str().c_str());
152848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
152948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				else
153048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
153148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					loc = subroutineUniform.location.val + arrayElem;
153248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
153348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
153448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (loc >= 0)
153548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
153648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					const SubroutineFunction& selectedFunction = subroutineUniform.getSelectedFunction(arrayElem);
153748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
153848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					int index = -1;
153948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (selectedFunction.index.isImplicit(std::vector<GLenum>(1, stage)))
154048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
154148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						index = glGetSubroutineIndex(program.name, stage, selectedFunction.getName().c_str());
154248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
154348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					else
154448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
154548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						index = selectedFunction.index.val;
154648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
154748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
154848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (loc < (int)indicesOut.size())
154948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
155048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						indicesOut[loc] = index;
155148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
155248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					else
155348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
155448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						assert(0);
155548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
155648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
155748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				else
155848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
155948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					assert(0);
156048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
156148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
156248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
156348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
156448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
156548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long runExecuteProgram(const CompiledProgram& program, const std::vector<Uniform>& uniforms,
156648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						   const std::vector<SubroutineUniform>& subroutineUniforms)
156748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
156848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		long ret = NO_ERROR;
156948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
157048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glUseProgram(program.name);
157148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
157248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < uniforms.size(); i++)
157348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
157448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setUniform(uniforms[i], program);
157548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
157648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
157748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t stage = 0; stage < program.stages.size() && subroutineUniforms.size(); stage++)
157848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
157948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
158048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glw::GLint numactive;
158148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glGetProgramStageiv(program.name, program.stages[stage], GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
158248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								&numactive);
158348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (numactive)
158448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
158548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				std::vector<glw::GLuint> indices(numactive, 0);
158648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
158748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				for (size_t i = 0; i < subroutineUniforms.size(); i++)
158848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
158948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					setSubroutineUniform(subroutineUniforms[i], program, program.stages[stage], indices);
159048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
159148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				glUniformSubroutinesuiv(program.stages[stage], numactive, &indices[0]);
159248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
159348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
159448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
159548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (program.stages[0] != GL_COMPUTE_SHADER)
159648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
159748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glClear(GL_COLOR_BUFFER_BIT);
159848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
159948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
160048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4);
160148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
160248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
160348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t i = 0; i < pixels.size(); i += 4)
160448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
160548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (pixels[i] != 0 || pixels[i + 1] != 255 || pixels[i + 2] != 0)
160648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
160748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret |= ERROR;
160848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					Logger() << "Program " << program.name << ": Wrong color. Expected green, got (" << (int)pixels[i]
160948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 << ", " << (int)pixels[i + 1] << ", " << (int)pixels[i + 2] << ", " << (int)pixels[i + 3]
161048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 << ").";
161148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					break;
161248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
161348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
161448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			Logger().Get()->writeImage("rendered image", "", QP_IMAGE_COMPRESSION_MODE_BEST, QP_IMAGE_FORMAT_RGBA8888,
161548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									   getWindowWidth(), getWindowHeight(), 0, &pixels[0]);
161648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
161748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
161848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
161948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLuint buffer;
162048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glGenBuffers(1, &buffer);
162148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
162248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(GLfloat), NULL, GL_DYNAMIC_READ);
162348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffer);
162448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
162548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glDispatchCompute(1, 1, 1);
162648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
162748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
162848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLfloat* color = reinterpret_cast<GLfloat*>(
162948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(GLfloat), GL_MAP_READ_BIT));
163048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
163148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (color[0] != 0 || color[1] != 1.0 || color[2] != 0)
163248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
163348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret |= ERROR;
163448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				Logger() << "Program " << program.name << ": Wrong color. Expected green, got (" << (int)color[0]
163548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						 << ", " << (int)color[1] << ", " << (int)color[2] << ", " << (int)color[3] << ").";
163648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
163748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
163848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
163948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
164048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glDeleteBuffers(1, &buffer);
164148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
164248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
164348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret;
164448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
164548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
164648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long runQueryUniform(const CompiledProgram& program, const Uniform& uniform, std::set<GLuint>& usedLocations,
164748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						 GLint max)
164848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
164948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		long ret = NO_ERROR;
165048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
165148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/*
165248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 glGetUniformLocation(program, name);
165348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 Query passes if returned value is unique in current program, matches
165448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 explicit location (if passed in GLSL code) and is less than value of
165548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 GL_MAX_UNIFORM_LOCATIONS.
165648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
165748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 glGetProgramResourceLocation(program, GL_UNIFIORM, name);
165848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 Query passes if returned value matches value returned from
165948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 glGetUniformLocation().
166048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 */
166148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
166248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (uniform.type.isStruct())
166348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
166448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t i = 0; i < uniform.childUniforms.size(); i++)
166548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
166648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret |= runQueryUniform(program, uniform.childUniforms[i], usedLocations, max);
166748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
166848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
166948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
167048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
167148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int arrayElem = 0; arrayElem < uniform.type.arraySize; arrayElem++)
167248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
167348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
167448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				/* Location that is taken by this uniform (even if not used).*/
167548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				GLint reservedLocation = -1;
167648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (!uniform.location.isImplicit(program.stages))
167748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
167848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					reservedLocation = uniform.location.val + arrayElem;
167948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
168048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
168148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				//optimization: for continuous arrays run queries at the beging and end only.
168248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				bool runQueries = uniform.location.isImplicit(program.stages) ||
168348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								  (arrayElem < 1000 || arrayElem > uniform.type.arraySize - 1000);
168448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
168548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (runQueries)
168648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
168748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					std::ostringstream name;
168848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					name << uniform.getName();
168948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					uniform.type.streamArrayStr(name, arrayElem);
169048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					GLint returned = glGetUniformLocation(program.name, name.str().c_str());
169148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
169248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					GLint returnedPIQ = glGetProgramResourceLocation(program.name, GL_UNIFORM, name.str().c_str());
169348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
169448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (returned != returnedPIQ)
169548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
169648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						ret |= ERROR;
169748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						Logger()
169848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							<< "Locations of  uniform \"" << name.str()
169948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							<< "\" returned by glGetUniformLocation and differ glGetProgramResourceLocation differ: "
170048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							<< returned << " != " << returnedPIQ << ".";
170148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
170248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
170348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					bool used = false;
170448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					for (size_t i = 0; i < program.stages.size(); i++)
170548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
170648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						used |= uniform.declOccurence.occurs(program.stages[i]) &&
170748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								uniform.usageOccurence.occurs(program.stages[i]);
170848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
170948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
171048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (!uniform.location.isImplicit(program.stages))
171148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
171248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						//Validate uniform location against explicit value
171348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						GLint expected = reservedLocation;
171448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						if (!(expected == returned || (!used && returned == -1)))
171548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						{
171648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							ret |= ERROR;
171748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							Logger() << "Unexpected uniform \"" << name.str() << "\" location: expected " << expected
171848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									 << ", got " << returned << ".";
171948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						}
172048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
172148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					else
172248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
172348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						//Check if location > 0 if used;
172448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						if (used)
172548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						{
172648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							if (returned < 0)
172748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							{
172848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								ret |= ERROR;
172948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								Logger() << "Unexpected uniform \"" << name.str()
173048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										 << "\" location: expected positive value, got " << returned << ".";
173148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							}
173248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							else
173348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							{
173448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								reservedLocation = returned;
173548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							}
173648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						}
173748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
173848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
173948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (returned >= 0)
174048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
174148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						//check if location is less than max
174248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
174348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						if (returned >= max)
174448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						{
174548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							ret |= ERROR;
174648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							Logger() << "Uniform \"" << name.str() << "\" returned location (" << returned
174748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									 << ") is greater than implementation dependent limit (" << max << ").";
174848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						}
174948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
175048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				} //if (runQueries)
175148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
175248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				//usedLocations is always checked (even if queries were not run.
175348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (reservedLocation >= 0)
175448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
175548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					//check if location is unique
175648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (usedLocations.find(reservedLocation) != usedLocations.end())
175748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
175848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						ret |= ERROR;
175948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						Logger() << "Uniform location (" << reservedLocation << ") is not unique.";
176048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
176148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					usedLocations.insert(reservedLocation);
176248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
176348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
176448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
176548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret;
176648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
176748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
176848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long runQueryUniformSubroutine(const CompiledProgram& program, GLenum stage,
176948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   const SubroutineUniform& subroutineUniform, std::set<GLuint>& usedLocations,
177048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   GLint max)
177148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
177248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		long ret = NO_ERROR;
177348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/*
177448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 glGetSubroutineUniformLocation(program, shaderType, name)
177548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 Query passes if returned value is unique in current program stage,
177648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 matches explicit location (if passed in GLSL code) and is less than
177748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 value of GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS.
177848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
177948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 glGetProgramResourceLocation(program, GL_(VERTEX|FRAGMENT|COMPUTE|...
178048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 ..._SUBROUTINE_UNIFORM, name)
178148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 Query passes if returned value matches value returned from
178248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 glGetUniformLocation().
178348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 */
178448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
178548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int arrayElem = 0; arrayElem < subroutineUniform.arraySize; arrayElem++)
178648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
178748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::ostringstream name;
178848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			name << subroutineUniform.getName();
178948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
179048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			subroutineUniform.streamArrayStr(name, arrayElem);
179148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
179248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLint returned = glGetSubroutineUniformLocation(program.name, stage, name.str().c_str());
179348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
179448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glw::GLenum piqStage = 0;
179548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			switch (stage)
179648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
179748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case GL_VERTEX_SHADER:
179848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				piqStage = GL_VERTEX_SUBROUTINE_UNIFORM;
179948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
180048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case GL_FRAGMENT_SHADER:
180148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				piqStage = GL_FRAGMENT_SUBROUTINE_UNIFORM;
180248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
180348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case GL_COMPUTE_SHADER:
180448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				piqStage = GL_COMPUTE_SUBROUTINE_UNIFORM;
180548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
180648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			default:
180748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				assert(0);
180848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
180948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
181048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLint returnedPIQ = glGetProgramResourceLocation(program.name, piqStage, name.str().c_str());
181148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
181248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (returned != returnedPIQ)
181348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
181448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret |= ERROR;
181548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				Logger() << "Locations of subrutine uniform \"" << name.str()
181648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						 << "\" returned by glGetUniformLocation and differ glGetProgramResourceLocation differ: "
181748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						 << returned << " != " << returnedPIQ << ".";
181848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
181948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
182048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			bool used = subroutineUniform.defOccurence.occurs(stage) && subroutineUniform.used;
182148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
182248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLint reservedLocation = -1;
182348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
182448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!subroutineUniform.location.isImplicit(std::vector<glw::GLenum>(1, stage)))
182548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
182648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				//Validate uniform location against explicit value
182748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				GLint expected = subroutineUniform.location.val + arrayElem;
182848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (!(expected == returned || (!used && returned == -1)))
182948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
183048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret |= ERROR;
183148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					Logger() << "Unexpected subroutine uniform \"" << name.str() << "\" location: expected " << expected
183248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 << ", got " << returned << ".";
183348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
183448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
183548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				reservedLocation = expected;
183648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
183748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			else
183848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
183948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				//Check if location > 0 if used;
184048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (used)
184148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
184248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (returned < 0)
184348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
184448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						ret |= ERROR;
184548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						Logger() << "Unexpected subroutine uniform \"" << name.str()
184648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								 << "\" location: expected positive value, got " << returned << ".";
184748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
184848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					else
184948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
185048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						reservedLocation = returned;
185148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
185248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
185348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
185448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
185548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (reservedLocation >= 0)
185648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
185748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				//check if location is unique
185848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (usedLocations.find(reservedLocation) != usedLocations.end())
185948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
186048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret |= ERROR;
186148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					Logger() << "Subroutine uniform \"" << name.str() << "\" location (" << reservedLocation
186248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 << ") is not unique.";
186348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
186448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				usedLocations.insert(reservedLocation);
186548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
186648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
186748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (returned >= 0)
186848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
186948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				//check if location is less than max
187048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
187148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (returned >= max)
187248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
187348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret |= ERROR;
187448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					Logger() << "Subroutine uniform \"" << name.str() << "\" returned location (" << returned
187548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 << ") is greater than implementation dependent limit (" << max << ").";
187648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
187748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
187848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
187948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret;
188048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
188148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
188248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long runQueryUniformSubroutineFunction(const CompiledProgram& program, GLenum stage,
188348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										   const SubroutineFunction& subroutineFunction, std::set<GLuint>& usedIndices,
188448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										   GLint max, bool used)
188548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
188648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		long ret = NO_ERROR;
188748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/*
188848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 glGetSubroutineIndex(program, shaderType, name)
188948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 Query passes if returned value is unique in current program stage,
189048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 matches explicit index (if passed in GLSL code) and is less than value
189148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 of GL_MAX_SUBROUTINES.
189248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
189348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 glGetProgramResourceIndex(program, GL_(VERTEX|FRAGMENT|COMPUTE|...
189448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 ..._SUBROUTINE, name)
189548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 Query passes if returned value matches value returned from
189648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 glGetSubroutineIndex().
189748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 */
189848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
189948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::string name = subroutineFunction.getName();
190048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
190148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLint returned = glGetSubroutineIndex(program.name, stage, name.c_str());
190248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
190348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLenum piqStage = 0;
190448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (stage)
190548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
190648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_VERTEX_SHADER:
190748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			piqStage = GL_VERTEX_SUBROUTINE;
190848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
190948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_FRAGMENT_SHADER:
191048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			piqStage = GL_FRAGMENT_SUBROUTINE;
191148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
191248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case GL_COMPUTE_SHADER:
191348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			piqStage = GL_COMPUTE_SUBROUTINE;
191448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
191548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
191648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			assert(0);
191748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
191848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
191948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLint returnedPIQ = glGetProgramResourceIndex(program.name, piqStage, name.c_str());
192048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
192148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (returned != returnedPIQ)
192248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
192348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ret |= ERROR;
192448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			Logger() << "Indices of subroutine function \"" << name
192548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					 << "\" returned by glGetSubroutineIndex and differ glGetProgramResourceIndex differ: " << returned
192648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					 << " != " << returnedPIQ << ".";
192748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
192848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
192948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLint reservedIndex = -1;
193048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
193148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!subroutineFunction.index.isImplicit(std::vector<glw::GLenum>(1, stage)))
193248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
193348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Validate uniform location against explicit value
193448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLint expected = subroutineFunction.index.val;
193548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!(expected == returned || (!used && returned == -1)))
193648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
193748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret |= ERROR;
193848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				Logger() << "Unexpected subroutine function \"" << name << "\" index: expected " << expected << ", got "
193948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						 << returned << ".";
194048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
194148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
194248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			reservedIndex = expected;
194348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
194448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
194548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
194648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//Check if location > 0 if used;
194748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (used)
194848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
194948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (returned < 0)
195048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
195148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret |= ERROR;
195248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					Logger() << "Unexpected subroutine function \"" << name << "\" index: expected positive value, got "
195348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 << returned << ".";
195448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
195548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				else
195648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
195748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					reservedIndex = returned;
195848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
195948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
196048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
196148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
196248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (reservedIndex >= 0)
196348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
196448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//check if location is unique
196548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (usedIndices.find(reservedIndex) != usedIndices.end())
196648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
196748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret |= ERROR;
196848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				Logger() << "Subroutine function \"" << name << "\" index (" << reservedIndex << ") is not unique.";
196948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
197048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			usedIndices.insert(reservedIndex);
197148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
197248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
197348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (returned >= 0)
197448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
197548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//check if location is less than max
197648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
197748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (returned >= max)
197848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
197948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret |= ERROR;
198048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				Logger() << "Subroutine function \"" << name << "\" returned index (" << returned
198148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						 << ") is greater than implementation dependent limit (" << max << ").";
198248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
198348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
198448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
198548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret;
198648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
198748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
198848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long runQueryProgram(const CompiledProgram& program, const std::vector<Uniform>& uniforms,
198948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						 const std::vector<SubroutineUniform>& subroutineUniforms)
199048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
199148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		long ret = NO_ERROR;
199248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
199348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
199448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::set<GLuint> usedLocations;
199548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
199648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLint max;
199748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
199848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
199948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t i = 0; i < uniforms.size(); i++)
200048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
200148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				ret |= runQueryUniform(program, uniforms[i], usedLocations, max);
200248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
200348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
200448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
200548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (subroutineUniforms.size())
200648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
200748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			GLint maxLocation, maxIndex;
200848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &maxLocation);
200948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glGetIntegerv(GL_MAX_SUBROUTINES, &maxIndex);
201048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
201148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (size_t stage = 0; stage < program.stages.size(); stage++)
201248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
201348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				std::set<GLuint> usedLocations;
201448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				std::set<GLuint> usedIndices;
201548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				for (size_t i = 0; i < subroutineUniforms.size(); i++)
201648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
201748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					ret |= runQueryUniformSubroutine(program, program.stages[stage], subroutineUniforms[i],
201848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos													 usedLocations, maxLocation);
201948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					for (size_t fn = 0; fn < subroutineUniforms[i].functions.fn.size(); fn++)
202048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
202148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						ret |= runQueryUniformSubroutineFunction(
202248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							program, program.stages[stage], subroutineUniforms[i].functions.fn[fn], usedIndices,
2023f1f97c069517c894a72fcc720da5e5bb5eb7226bAlexander Galazin							maxIndex,
2024f1f97c069517c894a72fcc720da5e5bb5eb7226bAlexander Galazin							subroutineUniforms[i].defOccurence.occurs(program.stages[stage]) &&
2025f1f97c069517c894a72fcc720da5e5bb5eb7226bAlexander Galazin								subroutineUniforms[i].used);
202648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
202748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
202848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
202948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
203048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
203148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret;
203248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
203348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
203448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprotected:
203548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformValueGenerator uniformValueGenerator;
203648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformStructCounter  uniformStructCounter;
203748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
203848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long doRun(std::vector<SubroutineUniform>& subroutineUniforms)
203948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
204048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		assert(subroutineUniforms.size());
204148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> noUniforms;
204248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(noUniforms, subroutineUniforms);
204348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
204448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
204548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long doRun(std::vector<Uniform>& uniforms)
204648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
204748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		assert(uniforms.size());
204848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> noSubroutineUniforms;
204948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms, noSubroutineUniforms);
205048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
205148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
205248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long doRunNegativeCompile(const std::string additionalDef)
205348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
205448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform>		   noUniforms;
205548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> noSubroutineUniforms;
205648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(noUniforms, noSubroutineUniforms, additionalDef, true);
205748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
205848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
205948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long doRunNegativeLink(std::vector<Uniform>& uniforms)
206048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
206148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> noSubroutineUniforms;
206248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms, noSubroutineUniforms, "", false, true);
206348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
206448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
206548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long doRunNegativeLink(std::vector<SubroutineUniform>& subroutineUniforms)
206648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
206748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> noUniforms;
206848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(noUniforms, subroutineUniforms, "", false, true);
206948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
207048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
207148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	long doRun(std::vector<Uniform>& uniforms, std::vector<SubroutineUniform>& subroutineUniforms,
207248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   std::string additionalDef = "", bool negativeCompile = false, bool negativeLink = false)
207348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
207448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		long		ret				  = NO_ERROR;
207548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::string parentUniformName = "";
207648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < uniforms.size(); i++)
207748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
207848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::ostringstream name;
207948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			name << "u" << i;
208048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			uniforms[i].setName(parentUniformName, name.str());
208148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
208248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int subroutineTypeCounter	 = 0;
208348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int subroutineFunctionCounter = 0;
208448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < subroutineUniforms.size(); i++)
208548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
208648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::ostringstream name;
208748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			name << "u" << i + uniforms.size();
208848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			subroutineUniforms[i].setName(name.str());
208948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!subroutineUniforms[i].functions.getTypeName().size())
209048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
209148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				subroutineUniforms[i].functions.setTypeName(subroutineTypeCounter++);
209248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				for (size_t fn = 0; fn < subroutineUniforms[i].functions.fn.size(); fn++)
209348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
209448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					subroutineUniforms[i].functions.fn[fn].setName(subroutineFunctionCounter++);
209548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
209648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
209748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
209848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
209948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLfloat coords[] = {
210048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
210148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		};
210248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
210348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLuint vbo, vao;
210448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glGenBuffers(1, &vbo);
210548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glBindBuffer(GL_ARRAY_BUFFER, vbo);
210648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glBufferData(GL_ARRAY_BUFFER, sizeof(coords), coords, GL_STATIC_DRAW);
210748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
210848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glGenVertexArrays(1, &vao);
210948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glBindVertexArray(vao);
211048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
211148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glEnableVertexAttribArray(0);
211248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
211348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<CompiledProgram> programs;
211448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ret |= CreatePrograms(programs, uniforms, subroutineUniforms, additionalDef, negativeCompile, negativeLink);
211548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
211648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < programs.size() && ret == NO_ERROR && !negativeCompile && !negativeLink; i++)
211748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
211848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ret |= runExecuteProgram(programs[i], uniforms, subroutineUniforms);
211948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ret |= runQueryProgram(programs[i], uniforms, subroutineUniforms);
212048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
212148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
212248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glUseProgram(0);
212348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
212448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		DeletePrograms(programs);
212548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
212648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glDeleteBuffers(1, &vbo);
212748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glDeleteVertexArrays(1, &vao);
212848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
212948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret;
213048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
213148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
213248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
213348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLoc : public ExplicitUniformLocationCaseBase
213448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
213548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
213648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
213748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform vec4 u0;
213848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
213948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH));
214048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
214148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
214248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
214348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
214448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocNonDec : public ExplicitUniformLocationCaseBase
214548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
214648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
214748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
214848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 0x0a) uniform vec4 u0;
214948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 010) uniform vec4  u1;
215048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
215148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(
215248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(0x0a, Loc::Hex), DefOccurence::FSH_OR_CSH));
215348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(
215448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(010, Loc::Oct), DefOccurence::FSH_OR_CSH));
215548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
215648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
215748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
215848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
215948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocMultipleStages : public ExplicitUniformLocationCaseBase
216048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
216148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
216248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
216348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform vec4 u0;
216448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
216548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2)));
216648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
216748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
216848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
216948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
217048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocMultipleUniforms : public ExplicitUniformLocationCaseBase
217148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
217248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
217348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
217448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform vec4 u0;
217548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 3) uniform vec4 u1;
217648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 5) uniform vec4 u2;
217748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
217848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2)));
217948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(3)));
218048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(5)));
218148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
218248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
218348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
218448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
218548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocTypesMix : public ExplicitUniformLocationCaseBase
218648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
218748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
218848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
218948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform float u0;
219048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 3) uniform vec3  u1;
219148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 0) uniform uint  u2;
219248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 1) uniform ivec3 u3;
219348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 4) uniform mat2  u4;
219448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 7) uniform mat2  u5;
219548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 5) uniform mat2  u6;
219648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 6) uniform mat3  u7;
219748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
219848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(2)));
219948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::C(3)));
220048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_UNSIGNED_INT, Loc::C(0)));
220148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_INT_VEC3, Loc::C(1)));
220248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(4)));
220348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(7)));
220448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(5)));
220548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT3, Loc::C(6)));
220648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
220748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
220848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
220948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
221048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocTypesMat : public ExplicitUniformLocationCaseBase
221148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
221248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
221348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
221448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
221548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 1) uniform mat2x3   u0;
221648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform mat3x2   u1;
221748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 0) uniform mat2     u2;
221848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 3) uniform imat3x4  u3;
221948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2x3, Loc::C(1)));
222048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT3x2, Loc::C(2)));
222148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(0)));
222248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT4x3, Loc::C(3)));
222348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
222448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
222548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
222648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
222748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocTypesSamplers : public ExplicitUniformLocationCaseBase
222848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
222948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
223048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
223148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 1) uniform sampler2D s0[3];
223248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 13) uniform sampler2D s1;
223348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
223448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_SAMPLER_2D, 3), Loc::C(1)));
223548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_SAMPLER_2D, Loc::C(13)));
223648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
223748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<GLuint>				   texUnits;
223848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<std::vector<GLubyte> > colors;
223948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
224048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < uniforms.size(); i++)
224148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
224248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int elem = 0; elem < uniforms[i].type.arraySize; elem++)
224348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
224448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				texUnits.push_back(uniforms[i].value.iValues[elem]);
224548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
224648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				std::vector<GLubyte> color(4);
224748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				color[0] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 0] + 0.5);
224848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				color[1] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 1] + 0.5);
224948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				color[2] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 2] + 0.5);
225048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				color[3] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 3] + 0.5);
225148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				colors.push_back(color);
225248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
225348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
225448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
225548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<GLuint> textures(texUnits.size());
225648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glGenTextures((GLsizei)(textures.size()), &textures[0]);
225748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
225848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (size_t i = 0; i < textures.size(); i++)
225948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
226048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glActiveTexture(GL_TEXTURE0 + texUnits[i]);
226148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glBindTexture(GL_TEXTURE_2D, textures[i]);
226248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
226348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &colors[i][0]);
226448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
226548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
226648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
226748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glActiveTexture(GL_TEXTURE0);
226848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		long ret = doRun(uniforms);
226948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glDeleteTextures((GLsizei)(textures.size()), &textures[0]);
227048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret;
227148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
227248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
227348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
227448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocTypesStructs : public ExplicitUniformLocationCaseBase
227548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
227648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
227748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
227848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
227948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/**
228048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 * This test case uses following uniform declarations:
228148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 *
228248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 * struct S {
228348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 *   vec4  u0;
228448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 *   float u1[2];
228548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 *   mat2  u2;
228648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 * };
228748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 * layout (location = 1) uniform S s0[3];
228848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 * layout (location = 13) uniform S s1;
228948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		 */
229048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
229148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<UniformType> members;
229248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		members.push_back(GL_FLOAT_VEC4);
229348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		members.push_back(UniformType(GL_FLOAT, 2));
229448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		members.push_back(GL_FLOAT_MAT2);
229548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
229648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(uniformStructCounter, members, 3), Loc::C(1)));
229748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(uniformStructCounter, members), Loc::C(13)));
229848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
229948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
230048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
230148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
230248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocArraysNonSpaced : public ExplicitUniformLocationCaseBase
230348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
230448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
230548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
230648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform float[3] u0;
230748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 5) uniform vec3[2]  u1;
230848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 7) uniform int[3]   u2;
230948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 10) uniform ivec4   u3;
231048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
231148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), Loc::C(2)));
231248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, 2), Loc::C(5)));
231348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT, 3), Loc::C(7)));
231448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_INT_VEC4, Loc::C(10)));
231548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
231648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
231748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
231848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
231948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocArraySpaced : public ExplicitUniformLocationCaseBase
232048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
232148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
232248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
232348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform float     u0;
232448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 5) uniform vec3[2]   u1;
232548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 8) uniform int[3]    u2;
232648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 12) uniform ivec4[1] u3;
232748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
232848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(2)));
232948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, 2), Loc::C(5)));
233048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT, 3), Loc::C(8)));
233148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT_VEC4, 1), Loc::C(12)));
233248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
233348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
233448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
233548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
233648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocArrayofArrays : public ExplicitUniformLocationCaseBase
233748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
233848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
233948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
234048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform float[2][3]  u0;
234148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 8) uniform vec3[2][2]   u1;
234248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 12) uniform float       u2;
234348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
234448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
234548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::vector<int> arraySizesSegmented(2);
234648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			arraySizesSegmented[0] = 2;
234748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			arraySizesSegmented[1] = 3;
234848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, arraySizesSegmented), Loc::C(2)));
234948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
235048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
235148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::vector<int> arraySizesSegmented(2);
235248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			arraySizesSegmented[0] = arraySizesSegmented[1] = 2;
235348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			uniforms.push_back(
235448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, arraySizesSegmented), Loc::C(8)));
235548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
235648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(12)));
235748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
235848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
235948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
236048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
236148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocMixWithImplicit : public ExplicitUniformLocationCaseBase
236248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
236348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
236448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
236548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 0) uniform float     u0;
236648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform vec3      u1;
236748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 3) uniform int       u2;
236848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
236948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//uniform float     u0;
237048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//uniform vec3      u1;
237148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//uniform int       u2;
237248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
237348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(0, DefOccurence::FSH_OR_CSH)));
237448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::C(2, DefOccurence::FSH_OR_CSH)));
237548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_INT, Loc::C(3, DefOccurence::FSH_OR_CSH)));
237648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
237748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
237848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
237948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
238048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocMixWithImplicit2 : public ExplicitUniformLocationCaseBase
238148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
238248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
238348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
238448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//uniform float[3] u0;
238548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 3) uniform vec3[2]  u1;
238648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//uniform int[3]   u2;
238748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 8) uniform ivec4   u3;
238848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
238948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), Loc::Implicit()));
239048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, 2), Loc::C(3)));
239148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT, 3), Loc::Implicit()));
239248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT_VEC4, 2), Loc::C(8)));
239348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
239448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
239548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
239648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
239748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocMixWithImplicit3 : public ExplicitUniformLocationCaseBase
239848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
239948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
240048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
240148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 0) uniform float     u0; //unused
240248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform vec3      u1; //unused
240348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 3) uniform int       u2; //unused
240448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
240548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//uniform float     u3;
240648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//uniform vec3      u4;
240748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//uniform int       u5;
240848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
240948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(
241048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(0), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
241148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(
241248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::C(2), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
241348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(
241448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			Uniform(uniformValueGenerator, GL_INT, Loc::C(3), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
241548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::Implicit()));
241648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::Implicit()));
241748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_INT, Loc::Implicit()));
241848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
241948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
242048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
242148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
242248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocMixWithImplicitMax : public ExplicitUniformLocationCaseBase
242348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
242448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
242548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
242648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		long ret = NO_ERROR;
242748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
242848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLint max;
242948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
243048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
243148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const int implicitCount = 1;
243248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
243348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int tests[3] = { 0, 3, max - implicitCount };
243448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
243548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int test = 0; test < 3; test++)
243648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
243748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::vector<Uniform> uniforms;
243848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
243948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//for performance reasons fill-up all avaliable locations with an unused arrays.
244048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (tests[test] > 0)
244148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
244248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				//[0..test - 1]
244348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, tests[test]), Loc::C(0),
244448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										   DefOccurence::ALL_SH, DefOccurence::NONE_SH));
244548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize ==
244648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					   tests[test]);
244748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
244848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
244948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (tests[test] < max - implicitCount)
245048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
245148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				//[test + 1..max]
245248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				uniforms.push_back(
245348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					Uniform(uniformValueGenerator, UniformType(GL_FLOAT, max - implicitCount - tests[test]),
245448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							Loc::C(tests[test] + implicitCount), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
245548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize ==
245648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					   max);
245748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
245848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
245948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::Implicit()));
246048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ret |= doRun(uniforms);
246148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
246248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret;
246348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
246448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
246548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
246648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocMixWithImplicitMaxArray : public ExplicitUniformLocationCaseBase
246748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
246848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
246948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
247048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		long ret = NO_ERROR;
247148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
247248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLint max;
247348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
247448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
247548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const int implicitCount = 3;
247648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
247748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int tests[3] = { 0, 3, max - 4 };
247848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
247948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int test = 0; test < 3; test++)
248048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
248148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::vector<Uniform> uniforms;
248248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
248348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//for performance reasons fill-up all avaliable locations with an unused arrays.
248448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (tests[test] > 0)
248548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
248648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				//[0..test - 1]
248748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, tests[test]), Loc::C(0),
248848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										   DefOccurence::ALL_SH, DefOccurence::NONE_SH));
248948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize ==
249048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					   tests[test]);
249148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
249248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
249348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (tests[test] < max - implicitCount)
249448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
249548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				//[test + 3 ..max]
249648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				uniforms.push_back(
249748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					Uniform(uniformValueGenerator, UniformType(GL_FLOAT, max - implicitCount - tests[test]),
249848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							Loc::C(tests[test] + implicitCount), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
249948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize ==
250048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					   max);
250148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
250248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, implicitCount), Loc::Implicit()));
250348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			ret |= doRun(uniforms);
250448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
250548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return ret;
250648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
250748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
250848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
250948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocImplicitInSomeStages : public ExplicitUniformLocationCaseBase
251048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
251148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
251248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
251348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//One shader: uniform float u0;
251448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Another shader: layout (location = 3) uniform float  u0;
251548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
251648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(3, DefOccurence::FSH_OR_CSH)));
251748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
251848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
251948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
252048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
252148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocImplicitInSomeStages2 : public ExplicitUniformLocationCaseBase
252248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
252348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
252448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
252548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//One shader: uniform float u0;
252648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Another shader: layout (location = 3) uniform float  u0; //not used!
252748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
252848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
252948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//location only in fsh, declaration in all shaders, usage in all shaders but fsh.
253048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(3, DefOccurence::FSH_OR_CSH),
253148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   DefOccurence::ALL_SH, DefOccurence::ALL_BUT_FSH));
253248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
253348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
253448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
253548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
253648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocImplicitInSomeStages3 : public ExplicitUniformLocationCaseBase
253748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
253848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
253948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
254048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
254148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
254248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//location only in fsh, declaration in all shaders, usage in all shaders but fsh.
254348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(3, DefOccurence::FSH_OR_CSH),
254448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   DefOccurence::ALL_SH, DefOccurence::ALL_BUT_FSH));
254548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
254648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//location in all but fsh, declaration in all shaders, usage in fsh.
254748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(2, DefOccurence::ALL_BUT_FSH),
254848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   DefOccurence::ALL_SH, DefOccurence::FSH_OR_CSH));
254948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
255048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//location only in fsh, declaration in all shaders, usage in all shaders but fsh.
255148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), Loc::C(7, DefOccurence::FSH_OR_CSH),
255248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   DefOccurence::ALL_SH, DefOccurence::ALL_BUT_FSH));
255348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
255448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//location in all but fsh, declaration in all shaders, usage in fsh.
255548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3),
255648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   Loc::C(4, DefOccurence::ALL_BUT_FSH), DefOccurence::ALL_SH,
255748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   DefOccurence::FSH_OR_CSH));
255848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
255948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//location only in vsh, declaration in all shaders, usage in all shaders but vsh.
256048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(0, DefOccurence::VSH), DefOccurence::ALL_SH,
256148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   DefOccurence::ALL_BUT_VSH));
256248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
256348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//location only in vsh, declaration in all shaders, usage in all shaders but vsh.
256448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(1, DefOccurence::ALL_BUT_FSH),
256548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   DefOccurence::ALL_SH, DefOccurence::ALL_BUT_VSH));
256648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
256748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(uniforms);
256848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
256948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
257048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
257148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocNegativeCompileNonNumberLiteral : public ExplicitUniformLocationCaseBase
257248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
257348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
257448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
257548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::string def = "layout (location = x) uniform float u0;";
257648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeCompile(def);
257748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
257848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
257948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
258048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocNegativeCompileNonConstLoc : public ExplicitUniformLocationCaseBase
258148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
258248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
258348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
258448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::string def = NL "const int i = 1;" NL "layout (location = i) uniform float u0;";
258548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeCompile(def);
258648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
258748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
258848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
258948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocNegativeLinkLocationReused1 : public ExplicitUniformLocationCaseBase
259048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
259148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
259248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
259348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform float u0;
259448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform float u1;
259548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
259648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH));
259748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH));
259848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeLink(uniforms);
259948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
260048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
260148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
260248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocNegativeLinkLocationReused2 : public ExplicitUniformLocationCaseBase
260348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
260448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
260548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
260648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		///layout (location = 2) uniform float u0;
260748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = 2) uniform float u1;
260848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
260948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH));
261048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::ALL_BUT_FSH));
261148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeLink(uniforms);
261248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
261348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
261448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
261548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocNegativeLinkMaxLocation : public ExplicitUniformLocationCaseBase
261648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
261748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
261848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
261948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout (location = X) uniform float u0;
262048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Where X is substituted with value of GL_MAX_UNIFORM_LOCATIONS.
262148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
262248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLint max;
262348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
262448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
262548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
262648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(max), DefOccurence::FSH_OR_CSH));
262748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
262848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeLink(uniforms);
262948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
263048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
263148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
263248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformLocNegativeLinkMaxMaxNumOfLocation : public ExplicitUniformLocationCaseBase
263348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
263448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
263548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
263648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
263748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLint max;
263848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
263948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<Uniform> uniforms;
264048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, max), Loc::C(0),
264148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   DefOccurence::FSH_OR_CSH, DefOccurence::NONE_SH));
264248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::Implicit(), DefOccurence::ALL_BUT_FSH));
264348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeLink(uniforms);
264448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
264548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
264648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
264748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubRoutineLoc : public ExplicitUniformLocationCaseBase
264848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
264948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
265048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
265148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
265248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//one shader:
265348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
265448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf0(float param) { .... };
265548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf1(float param) { .... };
265648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
265748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
265848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
265948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
266048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 2) subroutine uniform st0 u0;
266148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
266248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
266348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
266448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
266548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
266648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
266748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubRoutineLocNonDecimal : public ExplicitUniformLocationCaseBase
266848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
266948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
267048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
267148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//one shader:
267248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
267348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf0(float param) { .... };
267448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf1(float param) { .... };
267548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
267648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
267748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
267848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
267948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 0x0a) subroutine uniform st0 u0;
268048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(0x0a, Loc::Hex), 0,
268148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos													   DefOccurence::FSH_OR_CSH));
268248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 010 ) subroutine uniform st0 u1;
268348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(010, Loc::Oct), 0,
268448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos													   DefOccurence::FSH_OR_CSH));
268548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
268648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
268748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
268848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
268948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubRoutineLocAllStages : public ExplicitUniformLocationCaseBase
269048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
269148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
269248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
269348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
269448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf0(float param) { .... };
269548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf1(float param) { .... };
269648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
269748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
269848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
269948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
270048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 2) subroutine uniform st0 u0;
270148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2)));
270248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
270348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
270448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
270548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
270648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubRoutineLocArrays : public ExplicitUniformLocationCaseBase
270748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
270848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
270948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
271048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
271148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
271248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf0(float param) { .... };
271348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf1(float param) { .... };
271448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
271548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
271648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
271748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
271848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 1) subroutine uniform st0 u0[2];
271948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1), 2));
272048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
272148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
272248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
272348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
272448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubRoutineLocArraysMix : public ExplicitUniformLocationCaseBase
272548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
272648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
272748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
272848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
272948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf0(float param) { .... };
273048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf1(float param) { .... };
273148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
273248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
273348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st1(float param);
273448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st1) vec4 sf2(float param) { .... };
273548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st1) vec4 sf3(float param) { .... };
273648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st1(uniformValueGenerator, 2);
273748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
273848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
273948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
274048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 1) subroutine uniform st0 u0[2];
274148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1), 2));
274248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
274348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		////layout(location = 3) subroutine uniform st0 u1[2][3];
274448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<int> arraySizesSegmented(2);
274548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		arraySizesSegmented[0] = 2;
274648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		arraySizesSegmented[1] = 3;
274748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
274848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(3), arraySizesSegmented));
274948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
275048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 9) subroutine uniform st1 u2;
275148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st1, Loc::C(9)));
275248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
275348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
275448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
275548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
275648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
275748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubRoutineLocMixWithImplicit : public ExplicitUniformLocationCaseBase
275848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
275948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
276048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
276148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
276248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf0(float param) { .... };
276348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf1(float param) { .... };
276448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
276548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
276648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
276748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine uniform st0 u0;
276848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit()));
276948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 1 ) subroutine uniform st0 u1;
277048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(0)));
277148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 0 ) subroutine uniform st0 u2;
277248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1)));
277348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
277448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
277548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
277648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
277748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
277848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubRoutineLocCompilationNonNumberLiteral : public ExplicitUniformLocationCaseBase
277948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
278048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
278148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
278248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
278348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::string def =
278448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			NL "subroutine vec4 st0(float param);" NL "subroutine(st0) vec4 sf0(float param) { return param; }" NL
278548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			   "layout(location = x ) subroutine uniform st0 u0;";
278648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
278748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeCompile(def);
278848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
278948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
279048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
279148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubRoutineLocCompilationNonConstLoc : public ExplicitUniformLocationCaseBase
279248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
279348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
279448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
279548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::string def = NL "const int i = 1;" NL "subroutine vec4 st0(float param);" NL
279648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 "subroutine(st0) vec4 sf0(float param) { return param; }" NL
279748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 "layout(location = i ) subroutine uniform st0 u0;";
279848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeCompile(def);
279948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
280048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
280148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
280248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubRoutineLocLinkLocationReused1 : public ExplicitUniformLocationCaseBase
280348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
280448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
280548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
280648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 1) subroutine uniform st0 u0;
280748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 1) subroutine uniform st0 u0;
280848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet		   functions_st0(uniformValueGenerator, 2);
280948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
281048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
281148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
281248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
281348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
281448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeLink(subroutineUniforms);
281548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
281648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
281748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
281848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubRoutineLocLinkLocationMaxLocation : public ExplicitUniformLocationCaseBase
281948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
282048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
282148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
282248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = N) subroutine uniform st0 u0;
282348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//Where X is substituted with value of GL_MAX_UNIFORM_LOCATIONS.
282448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
282548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLint max;
282648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &max);
282748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet		   functions_st0(uniformValueGenerator, 2);
282848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
282948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
283048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(max), 0, DefOccurence::FSH_OR_CSH));
283148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeLink(subroutineUniforms);
283248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
283348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
283448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
283548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubRoutineLocLinkMaxNumOfLocations : public ExplicitUniformLocationCaseBase
283648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
283748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
283848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
283948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
284048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLint max;
284148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &max);
284248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet		   functions_st0(uniformValueGenerator, 2);
284348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
284448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
284548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(0), max, DefOccurence::FSH_OR_CSH, false));
284648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
284748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
284848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeLink(subroutineUniforms);
284948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
285048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
285148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
285248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineIndex : public ExplicitUniformLocationCaseBase
285348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
285448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
285548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
285648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//one shader:
285748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
285848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
285948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator);
286048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... };
286148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
286248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
286348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
286448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
286548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
286648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
286748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine uniform st0 u0;
286848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
286948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
287048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
287148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
287248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
287348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
287448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineIndexNonDecimal : public ExplicitUniformLocationCaseBase
287548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
287648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
287748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
287848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//one shader:
287948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
288048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
288148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator);
288248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 0x0a) subroutine(st0) vec4 sf0(float param) { .... };
288348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0x0a, Index::Hex)));
288448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 010 ) subroutine(st0) vec4 sf1(float param) { .... };
288548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(010, Index::Oct)));
288648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
288748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
288848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
288948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine uniform st0 u0;
289048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
289148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
289248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
289348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
289448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
289548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
289648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
289748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineIndexLoc : public ExplicitUniformLocationCaseBase
289848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
289948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
290048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
290148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
290248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//one shader:
290348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
290448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
290548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator);
290648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... };
290748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
290848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
290948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
291048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
291148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
291248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
291348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 3) subroutine uniform st0 u0;
291448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
291548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(3), 0, DefOccurence::FSH_OR_CSH));
291648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
291748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
291848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
291948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
292048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineIndexNonCont : public ExplicitUniformLocationCaseBase
292148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
292248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
292348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
292448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//one shader:
292548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
292648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
292748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator);
292848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 0) subroutine(st0) vec4 sf0(float param) { .... };
292948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0)));
293048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
293148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
293248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
293348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
293448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
293548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 2) subroutine uniform st0 u0;
293648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
293748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
293848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
293948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
294048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
294148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
294248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineIndexMultUniforms : public ExplicitUniformLocationCaseBase
294348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
294448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
294548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
294648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
294748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//one shader:
294848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
294948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
295048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator);
295148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... };
295248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
295348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 3) subroutine(st0) vec4 sf1(float param) { .... };
295448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(3)));
295548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
295648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st1(float param);
295748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st1(uniformValueGenerator);
295848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 2) subroutine(st1) vec4 sf2(float param) { .... };
295948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st1.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
296048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 0) subroutine(st1) vec4 sf3(float param) { .... };
296148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st1.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0)));
296248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
296348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
296448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 1) subroutine uniform st0 u0;
296548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
296648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1), 0, DefOccurence::FSH_OR_CSH));
296748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 9) subroutine uniform st1 u1;
296848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
296948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st1, Loc::C(9), 0, DefOccurence::FSH_OR_CSH));
297048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
297148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
297248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
297348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
297448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
297548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineIndexAllstages : public ExplicitUniformLocationCaseBase
297648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
297748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
297848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
297948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
298048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
298148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator);
298248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... };
298348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
298448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
298548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
298648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
298748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
298848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
298948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine uniform st0 u0;
299048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
299148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::ALL_SH));
299248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
299348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
299448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
299548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
299648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineIndexMixImplicit : public ExplicitUniformLocationCaseBase
299748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
299848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
299948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
300048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
300148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
300248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator);
300348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine(st0) vec4 sf0(float param) { .... };
300448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::Implicit()));
300548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 1) subroutine(st0) vec4 sf1(float param) { .... };
300648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
300748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 0) subroutine(st0) vec4 sf1(float param) { .... };
300848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0)));
300948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
301048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
301148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
301248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(location = 2) subroutine uniform st0 u0;
301348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
301448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
301548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRun(subroutineUniforms);
301648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
301748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
301848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
301948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineIndexNegativeCompilationNonNumberLiteral : public ExplicitUniformLocationCaseBase
302048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
302148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
302248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
302348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::string def = NL "subroutine vec4 st0(float param);" NL
302448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 "layout(index = x) subroutine(st0) vec4 sf1(float param) { return param; };";
302548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeCompile(def);
302648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
302748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
302848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
302948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineIndexNegativeCompilationNonConstIndex : public ExplicitUniformLocationCaseBase
303048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
303148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
303248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
303348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::string def =
303448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			NL "const int i = 1;" NL "layout(index = i) subroutine(st0) vec4 sf1(float param) { return param; };";
303548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeCompile(def);
303648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
303748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
303848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
303948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineIndexNegativeLinkIndexReused : public ExplicitUniformLocationCaseBase
304048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
304148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
304248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
304348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
304448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator);
304548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 2) subroutine(st0) vec4 sf0(float param) { .... };
304648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
304748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
304848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
304948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
305048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
305148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
305248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine uniform st0 u0;
305348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
305448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
305548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeLink(subroutineUniforms);
305648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
305748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
305848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
305948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineIndexNegativeLinkMaxIndex : public ExplicitUniformLocationCaseBase
306048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
306148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
306248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
306348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
306448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		GLint max;
306548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glGetIntegerv(GL_MAX_SUBROUTINES, &max);
306648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
306748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
306848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator);
306948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//layout(index = N) subroutine(st0) vec4 sf0(float param) { .... };
307048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(max)));
307148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
307248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
307348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
307448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine uniform st0 u0;
307548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
307648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
307748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeLink(subroutineUniforms);
307848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
307948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
308048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
308148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SubroutineIndexNegativeLinkMaxNumOfIndices : public ExplicitUniformLocationCaseBase
308248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
308348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual long Run()
308448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
308548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine vec4 st0(float param);
308648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		SubroutineFunctionSet functions_st0(uniformValueGenerator);
308748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
308848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLint max;
308948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glGetIntegerv(GL_MAX_SUBROUTINES, &max);
309048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
309148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int i = 0; i < max; i++)
309248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
309348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			//layout(index = N) subroutine(st0) vec4 sf0(float param) { .... };
309448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(i)));
309548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
309648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::Implicit()));
309748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
309848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<SubroutineUniform> subroutineUniforms;
309948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
310048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//subroutine uniform st0 u0;
310148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		subroutineUniforms.push_back(
310248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
310348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return doRunNegativeLink(subroutineUniforms);
310448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
310548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
310648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
310748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
310848087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosExplicitUniformLocationGLTests::ExplicitUniformLocationGLTests(glcts::Context& context)
310948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	: TestCaseGroup(context, "explicit_uniform_location", "")
311048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
311148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
311248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
311348087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosExplicitUniformLocationGLTests::~ExplicitUniformLocationGLTests(void)
311448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
311548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
311648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
311748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosvoid ExplicitUniformLocationGLTests::init()
311848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
311948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	using namespace glcts;
312048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
312148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Logger::setOutput(m_context.getTestContext().getLog());
312248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc", TestSubcase::Create<UniformLoc>));
312348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-nondecimal", TestSubcase::Create<UniformLocNonDec>));
312448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-all-stages", TestSubcase::Create<UniformLocMultipleStages>));
312548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(
312648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		new TestSubcase(m_context, "uniform-loc-multiple-uniforms", TestSubcase::Create<UniformLocMultipleUniforms>));
312748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-types-mix", TestSubcase::Create<UniformLocTypesMix>));
312848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-types-mat", TestSubcase::Create<UniformLocTypesMat>));
312948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-types-structs", TestSubcase::Create<UniformLocTypesStructs>));
313048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-types-samplers", TestSubcase::Create<UniformLocTypesSamplers>));
313148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(
313248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		new TestSubcase(m_context, "uniform-loc-arrays-nonspaced", TestSubcase::Create<UniformLocArraysNonSpaced>));
313348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-arrays-spaced", TestSubcase::Create<UniformLocArraySpaced>));
313448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
313548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-arrays-of-arrays", TestSubcase::Create<UniformLocArrayofArrays>));
313648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
313748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(
313848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		new TestSubcase(m_context, "uniform-loc-mix-with-implicit", TestSubcase::Create<UniformLocMixWithImplicit>));
313948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(
314048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		new TestSubcase(m_context, "uniform-loc-mix-with-implicit2", TestSubcase::Create<UniformLocMixWithImplicit2>));
314148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(
314248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		new TestSubcase(m_context, "uniform-loc-mix-with-implicit3", TestSubcase::Create<UniformLocMixWithImplicit3>));
314348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max",
314448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocMixWithImplicitMax>));
314548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max-array",
314648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocMixWithImplicitMaxArray>));
314748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
314848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages",
314948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocImplicitInSomeStages>));
315048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages2",
315148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocImplicitInSomeStages2>));
315248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages3",
315348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocImplicitInSomeStages3>));
315448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
315548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-non-number-literal",
315648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocNegativeCompileNonNumberLiteral>));
315748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-nonconst-loc",
315848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocNegativeCompileNonConstLoc>));
315948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused1",
316048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocNegativeLinkLocationReused1>));
316148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused2",
316248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocNegativeLinkLocationReused2>));
316348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-location",
316448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocNegativeLinkMaxLocation>));
316548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-num-of-locations",
316648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocNegativeLinkMaxMaxNumOfLocation>));
316748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
316848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-loc", TestSubcase::Create<SubRoutineLoc>));
316948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-loc-nondecimal", TestSubcase::Create<SubRoutineLocNonDecimal>));
317048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-loc-all-stages", TestSubcase::Create<SubRoutineLocAllStages>));
317148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-loc-arrays", TestSubcase::Create<SubRoutineLocArrays>));
317248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-loc-arrays-mix", TestSubcase::Create<SubRoutineLocArraysMix>));
317348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-loc-mix-with-implicit",
317448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<SubRoutineLocMixWithImplicit>));
317548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-loc-negative-compilation-non-number-literal",
317648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<SubRoutineLocCompilationNonNumberLiteral>));
317748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-loc-negative-compilation-nonconst-loc",
317848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<SubRoutineLocCompilationNonConstLoc>));
317948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-loc-negative-link-location-reused1",
318048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<SubRoutineLocLinkLocationReused1>));
318148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-loc-negative-link-location-max-location",
318248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<SubRoutineLocLinkLocationMaxLocation>));
318348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-loc-negative-link-max-num-of-locations",
318448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<SubRoutineLocLinkMaxNumOfLocations>));
318548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-index", TestSubcase::Create<SubroutineIndex>));
318648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-index-nondecimal", TestSubcase::Create<SubroutineIndexNonDecimal>));
318748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-index-loc", TestSubcase::Create<SubroutineIndexLoc>));
318848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(
318948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		new TestSubcase(m_context, "subroutine-index-non-continuous", TestSubcase::Create<SubroutineIndexNonCont>));
319048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-index-multiple-uniforms",
319148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<SubroutineIndexMultUniforms>));
319248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-index-all-stages", TestSubcase::Create<SubroutineIndexAllstages>));
319348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(
319448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		new TestSubcase(m_context, "subroutine-index-mix-implicit", TestSubcase::Create<SubroutineIndexMixImplicit>));
319548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-index-negative-compilation-non-number-literal",
319648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<SubroutineIndexNegativeCompilationNonNumberLiteral>));
319748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-index-negative-compilation-nonconst-index",
319848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<SubroutineIndexNegativeCompilationNonConstIndex>));
319948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-index-negative-link-index-reused",
320048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<SubroutineIndexNegativeLinkIndexReused>));
320148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-index-negative-link-location-maxindex",
320248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<SubroutineIndexNegativeLinkMaxIndex>));
320348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "subroutine-index-negative-link-max-num-of-indices",
320448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<SubroutineIndexNegativeLinkMaxNumOfIndices>));
320548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
320648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
320748087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosExplicitUniformLocationES31Tests::ExplicitUniformLocationES31Tests(glcts::Context& context)
320848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	: TestCaseGroup(context, "explicit_uniform_location", "")
320948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
321048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
321148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
321248087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosExplicitUniformLocationES31Tests::~ExplicitUniformLocationES31Tests(void)
321348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
321448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
321548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
321648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosvoid ExplicitUniformLocationES31Tests::init()
321748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
321848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	using namespace glcts;
321948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Logger::setOutput(m_context.getTestContext().getLog());
322048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc", TestSubcase::Create<UniformLoc>));
322148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-nondecimal", TestSubcase::Create<UniformLocNonDec>));
322248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-all-stages", TestSubcase::Create<UniformLocMultipleStages>));
322348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(
322448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		new TestSubcase(m_context, "uniform-loc-multiple-uniforms", TestSubcase::Create<UniformLocMultipleUniforms>));
322548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-types-mix", TestSubcase::Create<UniformLocTypesMix>));
322648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-types-mat", TestSubcase::Create<UniformLocTypesMat>));
322748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-types-structs", TestSubcase::Create<UniformLocTypesStructs>));
322848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-types-samplers", TestSubcase::Create<UniformLocTypesSamplers>));
322948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(
323048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		new TestSubcase(m_context, "uniform-loc-arrays-nonspaced", TestSubcase::Create<UniformLocArraysNonSpaced>));
323148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-arrays-spaced", TestSubcase::Create<UniformLocArraySpaced>));
323248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-arrays-of-arrays", TestSubcase::Create<UniformLocArrayofArrays>));
323348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(
323448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		new TestSubcase(m_context, "uniform-loc-mix-with-implicit", TestSubcase::Create<UniformLocMixWithImplicit>));
323548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(
323648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		new TestSubcase(m_context, "uniform-loc-mix-with-implicit2", TestSubcase::Create<UniformLocMixWithImplicit2>));
323748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(
323848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		new TestSubcase(m_context, "uniform-loc-mix-with-implicit3", TestSubcase::Create<UniformLocMixWithImplicit3>));
323948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max",
324048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocMixWithImplicitMax>));
324148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max-array",
324248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocMixWithImplicitMaxArray>));
324348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages",
324448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocImplicitInSomeStages>));
324548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages2",
324648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocImplicitInSomeStages2>));
324748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages3",
324848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocImplicitInSomeStages3>));
324948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-non-number-literal",
325048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocNegativeCompileNonNumberLiteral>));
325148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-nonconst-loc",
325248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocNegativeCompileNonConstLoc>));
325348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused1",
325448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocNegativeLinkLocationReused1>));
325548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused2",
325648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocNegativeLinkLocationReused2>));
325748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-location",
325848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocNegativeLinkMaxLocation>));
325948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-num-of-locations",
326048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 TestSubcase::Create<UniformLocNegativeLinkMaxMaxNumOfLocation>));
326148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
326248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
3263