<commit_before>/*
 * Copyright 2015-2016 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SPIRV_GLSL_HPP
#define SPIRV_GLSL_HPP

#include "spirv_cross.hpp"
#include <sstream>
#include <unordered_set>
#include <unordered_map>
#include <utility>

namespace spirv_cross
{
enum PlsFormat
{
	PlsNone = 0,

	PlsR11FG11FB10F,
	PlsR32F,
	PlsRG16F,
	PlsRGB10A2,
	PlsRGBA8,
	PlsRG16,

	PlsRGBA8I,
	PlsRG16I,

	PlsRGB10A2UI,
	PlsRGBA8UI,
	PlsRG16UI,
	PlsR32UI
};

struct PlsRemap
{
	uint32_t id;
	PlsFormat format;
};

class CompilerGLSL : public Compiler
{
public:
	struct Options
	{
		uint32_t version = 450;
		bool es = false;
		bool force_temporary = false;

		// If true, Vulkan GLSL features are used instead of GL-compatible features.
		// Mostly useful for debugging SPIR-V files.
		bool vulkan_semantics = false;

		enum Precision
		{
			DontCare,
			Lowp,
			Mediump,
			Highp
		};

		struct
		{
			// In vertex shaders, rewrite [0, w] depth (Vulkan/D3D style) to [-w, w] depth (GL style).
			bool fixup_clipspace = true;
		} vertex;

		struct
		{
			// Add precision mediump float in ES targets when emitting GLES source.
			// Add precision highp int in ES targets when emitting GLES source.
			Precision default_float_precision = Mediump;
			Precision default_int_precision = Highp;
		} fragment;
	};

	void remap_pixel_local_storage(std::vector<PlsRemap> inputs, std::vector<PlsRemap> outputs)
	{
		pls_inputs = std::move(inputs);
		pls_outputs = std::move(outputs);
		remap_pls_variables();
	}

	CompilerGLSL(std::vector<uint32_t> spirv_)
	    : Compiler(move(spirv_))
	{
		if (source.known)
		{
			options.es = source.es;
			options.version = source.version;
		}
	}

	const Options &get_options() const
	{
		return options;
	}
	void set_options(Options &opts)
	{
		options = opts;
	}
	std::string compile() override;

protected:
	void reset();
	void emit_function(SPIRFunction &func, uint64_t return_flags);

	// Virtualize methods which need to be overridden by subclass targets like C++ and such.
	virtual void emit_function_prototype(SPIRFunction &func, uint64_t return_flags);
	virtual void emit_header();
	virtual void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id);
	virtual void emit_texture_op(const Instruction &i);
	virtual std::string type_to_glsl(const SPIRType &type);
	virtual std::string builtin_to_glsl(spv::BuiltIn builtin);
	virtual std::string member_decl(const SPIRType &type, const SPIRType &member_type, uint32_t member);
	virtual std::string image_type_glsl(const SPIRType &type);
	virtual std::string constant_expression(const SPIRConstant &c);
	virtual std::string constant_expression_vector(const SPIRConstant &c, uint32_t vector);
	virtual void emit_fixup();

	std::unique_ptr<std::ostringstream> buffer;

	template <typename T>
	inline void statement_inner(T &&t)
	{
		(*buffer) << std::forward<T>(t);
		statement_count++;
	}

	template <typename T, typename... Ts>
	inline void statement_inner(T &&t, Ts &&... ts)
	{
		(*buffer) << std::forward<T>(t);
		statement_count++;
		statement_inner(std::forward<Ts>(ts)...);
	}

	template <typename... Ts>
	inline void statement(Ts &&... ts)
	{
		if (redirect_statement)
			redirect_statement->push_back(join(std::forward<Ts>(ts)...));
		else
		{
			for (uint32_t i = 0; i < indent; i++)
				(*buffer) << "    ";

			statement_inner(std::forward<Ts>(ts)...);
			(*buffer) << '\n';
		}
	}

	template <typename... Ts>
	inline void statement_no_indent(Ts &&... ts)
	{
		auto old_indent = indent;
		indent = 0;
		statement(std::forward<Ts>(ts)...);
		indent = old_indent;
	}

	// Used for implementing continue blocks where
	// we want to obtain a list of statements we can merge
	// on a single line separated by comma.
	std::vector<std::string> *redirect_statement = nullptr;
	const SPIRBlock *current_continue_block = nullptr;

	void begin_scope();
	void end_scope();
	void end_scope_decl();
	void end_scope_decl(const std::string &decl);

	Options options;

	std::string type_to_array_glsl(const SPIRType &type);
	std::string variable_decl(const SPIRVariable &variable);

	void add_local_variable_name(uint32_t id);
	void add_resource_name(uint32_t id);
	void add_member_name(SPIRType &type, uint32_t name);
	std::unordered_set<std::string> local_variable_names;
	std::unordered_set<std::string> resource_names;
	std::unordered_set<std::string> interface_block_names;

	bool processing_entry_point = false;

	// Can be overriden by subclass backends for trivial things which
	// shouldn't need polymorphism.
	struct BackendVariations
	{
		bool float_literal_suffix = false;
		bool uint32_t_literal_suffix = true;
		const char *basic_int_type = "int";
		const char *basic_uint_type = "uint";
		bool swizzle_is_function = false;
		bool shared_is_implied = false;
		bool flexible_member_array_supported = true;<commit_msg>Remove unused interface_block_names member.<commit_after>/*
 * Copyright 2015-2016 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SPIRV_GLSL_HPP
#define SPIRV_GLSL_HPP

#include "spirv_cross.hpp"
#include <sstream>
#include <unordered_set>
#include <unordered_map>
#include <utility>

namespace spirv_cross
{
enum PlsFormat
{
	PlsNone = 0,

	PlsR11FG11FB10F,
	PlsR32F,
	PlsRG16F,
	PlsRGB10A2,
	PlsRGBA8,
	PlsRG16,

	PlsRGBA8I,
	PlsRG16I,

	PlsRGB10A2UI,
	PlsRGBA8UI,
	PlsRG16UI,
	PlsR32UI
};

struct PlsRemap
{
	uint32_t id;
	PlsFormat format;
};

class CompilerGLSL : public Compiler
{
public:
	struct Options
	{
		uint32_t version = 450;
		bool es = false;
		bool force_temporary = false;

		// If true, Vulkan GLSL features are used instead of GL-compatible features.
		// Mostly useful for debugging SPIR-V files.
		bool vulkan_semantics = false;

		enum Precision
		{
			DontCare,
			Lowp,
			Mediump,
			Highp
		};

		struct
		{
			// In vertex shaders, rewrite [0, w] depth (Vulkan/D3D style) to [-w, w] depth (GL style).
			bool fixup_clipspace = true;
		} vertex;

		struct
		{
			// Add precision mediump float in ES targets when emitting GLES source.
			// Add precision highp int in ES targets when emitting GLES source.
			Precision default_float_precision = Mediump;
			Precision default_int_precision = Highp;
		} fragment;
	};

	void remap_pixel_local_storage(std::vector<PlsRemap> inputs, std::vector<PlsRemap> outputs)
	{
		pls_inputs = std::move(inputs);
		pls_outputs = std::move(outputs);
		remap_pls_variables();
	}

	CompilerGLSL(std::vector<uint32_t> spirv_)
	    : Compiler(move(spirv_))
	{
		if (source.known)
		{
			options.es = source.es;
			options.version = source.version;
		}
	}

	const Options &get_options() const
	{
		return options;
	}
	void set_options(Options &opts)
	{
		options = opts;
	}
	std::string compile() override;

protected:
	void reset();
	void emit_function(SPIRFunction &func, uint64_t return_flags);

	// Virtualize methods which need to be overridden by subclass targets like C++ and such.
	virtual void emit_function_prototype(SPIRFunction &func, uint64_t return_flags);
	virtual void emit_header();
	virtual void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id);
	virtual void emit_texture_op(const Instruction &i);
	virtual std::string type_to_glsl(const SPIRType &type);
	virtual std::string builtin_to_glsl(spv::BuiltIn builtin);
	virtual std::string member_decl(const SPIRType &type, const SPIRType &member_type, uint32_t member);
	virtual std::string image_type_glsl(const SPIRType &type);
	virtual std::string constant_expression(const SPIRConstant &c);
	virtual std::string constant_expression_vector(const SPIRConstant &c, uint32_t vector);
	virtual void emit_fixup();

	std::unique_ptr<std::ostringstream> buffer;

	template <typename T>
	inline void statement_inner(T &&t)
	{
		(*buffer) << std::forward<T>(t);
		statement_count++;
	}

	template <typename T, typename... Ts>
	inline void statement_inner(T &&t, Ts &&... ts)
	{
		(*buffer) << std::forward<T>(t);
		statement_count++;
		statement_inner(std::forward<Ts>(ts)...);
	}

	template <typename... Ts>
	inline void statement(Ts &&... ts)
	{
		if (redirect_statement)
			redirect_statement->push_back(join(std::forward<Ts>(ts)...));
		else
		{
			for (uint32_t i = 0; i < indent; i++)
				(*buffer) << "    ";

			statement_inner(std::forward<Ts>(ts)...);
			(*buffer) << '\n';
		}
	}

	template <typename... Ts>
	inline void statement_no_indent(Ts &&... ts)
	{
		auto old_indent = indent;
		indent = 0;
		statement(std::forward<Ts>(ts)...);
		indent = old_indent;
	}

	// Used for implementing continue blocks where
	// we want to obtain a list of statements we can merge
	// on a single line separated by comma.
	std::vector<std::string> *redirect_statement = nullptr;
	const SPIRBlock *current_continue_block = nullptr;

	void begin_scope();
	void end_scope();
	void end_scope_decl();
	void end_scope_decl(const std::string &decl);

	Options options;

	std::string type_to_array_glsl(const SPIRType &type);
	std::string variable_decl(const SPIRVariable &variable);

	void add_local_variable_name(uint32_t id);
	void add_resource_name(uint32_t id);
	void add_member_name(SPIRType &type, uint32_t name);
	std::unordered_set<std::string> local_variable_names;
	std::unordered_set<std::string> resource_names;

	bool processing_entry_point = false;

	// Can be overriden by subclass backends for trivial things which
	// shouldn't need polymorphism.
	struct BackendVariations
	{
		bool float_literal_suffix = false;
		bool uint32_t_literal_suffix = true;
		const char *basic_int_type = "int";
		const char *basic_uint_type = "uint";
		bool swizzle_is_function = false;
		bool shared_is_implied = false;
		bool flexible_member_array_supported = true;
{'fraction_non_alphanumeric': 0.10782122905027933, 'fraction_numerical': 0.014711359404096834, 'mean_word_length': 4.542311661506708, 'pattern_counts': {'":': 0, '<': 64, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5166409', 'n_tokens_mistral': 3985, 'n_tokens_neox': 3623, 'n_words': 1008}