<commit_before>
/* medea - an Open Source, WebGL-based 3d engine for next-generation browser games.
 * (or alternatively, for clumsy and mostly useless tech demos written solely for fun)
 *
 * medea is (c) 2011, <NAME>
 * licensed under the terms and conditions of a 3 clause BSD license.
 */

medea._addMod('shader',['filesystem','cpp.js'],function(undefined) {
	"use strict";
	var medea = this, gl = medea.gl;

	medea.SHADER_TYPE_PIXEL = gl.FRAGMENT_SHADER;
	medea.SHADER_TYPE_VERTEX = gl.VERTEX_SHADER;

	medea._initMod('filesystem');

	// cache for compiled shader objects
	var sh_cache = {
	};

	// predefined macros
	var default_defines = {
		'GL_ES' : ''
	};

	var re_toplevel = /^\s*toplevel\(\s*"\s*(.+)\s*"\s*\)\s*$/;

	medea.Shader = medea.Resource.extend( {

		init : function(src, defines, callback) {

			this.type = src.split('.').pop() == 'ps'
				? medea.SHADER_TYPE_PIXEL
				: medea.SHADER_TYPE_VERTEX;

			this.shader = 0;
			this.defines = medea.Merge(defines || {},default_defines);

			// trigger deferred loading
			this._super(src, callback);
		},

		OnDelayedInit : function(data) {
// #ifdef DEBUG
			medea.DebugAssert(typeof data === "string","got unexpected argument, perhaps "
				+ "the source for the shader was not a single resource?"
			);
// #endif
			this.source = data;

			var c = this._GetCacheName();
			var s = sh_cache[c];
			if(s !== undefined) {
				this.gen_source = s.gen_source;
				this.shader = s.shader;
				this._super();
				return;
			}

			var self = this;

			// additional top-level declarations are specified in-place using
			// #pragma toplevel. Each time cpp.js encounters one, it invokes
			// settings.pragma_func.
			var top_level_decls = [];

			// _super() is dynamically assigned and ceases to exist as soon
			// as OnDelayedInit returns, so we need to grab a ref.
			var call_outer_super = self._super;

			// preprocessing shaders is asynchronous
			var settings = {
				include_func : function(file, is_global, resumer) {
					if (!is_global) {
						file = medea._GetPath(self.src) + file;
					}

					medea.Fetch(file,
						function(data) {
							resumer(data);
						},
						function(error) {
							resumer(null);
						}
					);
				},

				completion_func : function(data) {
					// #ifdef DEBUG
					medea.DebugAssert(!!data,'unexpected null');
					// #endif
					self.gen_source = top_level_decls.join('\n') + '\n' + data;
					s = self.shader = gl.createShader(self.type);

					// create a new cache entry for this shader
					sh_cache[c] = {
						shader : self.shader,
						source : self.source,
						gen_source : self.gen_source
					};

					// compile the preprocessed shader
					gl.shaderSource(s,self.gen_source);
					gl.compileShader(s);

					if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) {
						medea.NotifyFatal("failure compiling shader " +  self.src
							+ ", error log: " + gl.getShaderInfoLog(s)
						);
						return;
					}

					// mark this resource as complete
					call_outer_super.apply(self);

					medea.LogDebug("successfully compiled shader "
						+ self.src
					);
				},

				error_func : function(message) {
					medea.NotifyFatal("failure preprocessing shader "
						+ ": " + message
					);
					return;
				},

				pragma_func : function(pragma_text) {
					var r = re_toplevel.exec(pragma_text);
					if (!r) {
						medea.NotifyFatal("syntax error in #pragma toplevel: " + pragma_text);
						return null;
					}

					top_level_decls.push(r[1]);
					return true;
				},
			};

			var cpp = cpp_js(settings);
			cpp.define_multiple(this.defines);<commit_msg>shader: avoid loading shaders multiple times by adding a waiting queue for other shader instances requiring the same shader object.<commit_after>
/* medea - an Open Source, WebGL-based 3d engine for next-generation browser games.
 * (or alternatively, for clumsy and mostly useless tech demos written solely for fun)
 *
 * medea is (c) 2011, <NAME>
 * licensed under the terms and conditions of a 3 clause BSD license.
 */

medea._addMod('shader',['filesystem','cpp.js'],function(undefined) {
	"use strict";
	var medea = this, gl = medea.gl;

	medea.SHADER_TYPE_PIXEL = gl.FRAGMENT_SHADER;
	medea.SHADER_TYPE_VERTEX = gl.VERTEX_SHADER;

	medea._initMod('filesystem');

	// cache for compiled shader objects
	var sh_cache = {
	};

	// predefined macros
	var default_defines = {
		'GL_ES' : ''
	};

	var re_toplevel = /^\s*toplevel\(\s*"\s*(.+)\s*"\s*\)\s*$/;

	medea.Shader = medea.Resource.extend( {

		init : function(src, defines, callback) {

			this.type = src.split('.').pop() == 'ps'
				? medea.SHADER_TYPE_PIXEL
				: medea.SHADER_TYPE_VERTEX;

			this.shader = 0;
			this.defines = medea.Merge(defines || {},default_defines);

			// trigger deferred loading
			this._super(src, callback);
		},

		OnDelayedInit : function(data) {
// #ifdef DEBUG
			medea.DebugAssert(typeof data === "string","got unexpected argument, perhaps "
				+ "the source for the shader was not a single resource?"
			);
// #endif
			this.source = data;

			// _super() is dynamically assigned and ceases to exist as soon
			// as OnDelayedInit returns, so we need to grab a ref.
			var self = this;
			var call_outer_super = self._super;
	

			// check if the shader has already been loaded or is currently
			// being fetched/compiled.
			var c = this._GetCacheName();
			var s = sh_cache[c];
			if(s !== undefined) {
				if(Array.isArray(s)) {
					// loading is in process, wait for it.
					s.push(function(s) {
						self.gen_source = s.gen_source;
						self.shader = s.shader;
						call_outer_super.apply(self);
					});
				}
				else {
					this.gen_source = s.gen_source;
					this.shader = s.shader;
					this._super();
				}
				return;
			}

			var waiters = sh_cache[c] = [];

			// additional top-level declarations are specified in-place using
			// #pragma toplevel. Each time cpp.js encounters one, it invokes
			// settings.pragma_func.
			var top_level_decls = [];


			// preprocessing shaders is asynchronous
			var settings = {
				include_func : function(file, is_global, resumer) {
					if (!is_global) {
						file = medea._GetPath(self.src) + file;
					}

					medea.Fetch(file,
						function(data) {
							resumer(data);
						},
						function(error) {
							resumer(null);
						}
					);
				},

				completion_func : function(data) {
					// #ifdef DEBUG
					medea.DebugAssert(!!data,'unexpected null');
					// #endif
					self.gen_source = top_level_decls.join('\n') + '\n' + data;
					s = self.shader = gl.createShader(self.type);

					// create a new cache entry for this shader
					var entry = sh_cache[c] = {
						shader : self.shader,
						source : self.source,
						gen_source : self.gen_source
					};

					// compile the preprocessed shader
					gl.shaderSource(s,self.gen_source);
					gl.compileShader(s);

					if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) {
						medea.NotifyFatal("failure compiling shader " +  self.src
							+ ", error log: " + gl.getShaderInfoLog(s)
						);
						return;
					}

					// mark this resource as complete
					call_outer_super.apply(self);

					// callback all waiters
					for (var i = 0, e = waiters.length; i < e; ++i) {
						waiters[i](entry);
					}

					medea.LogDebug("successfully compiled shader "
						+ self.src
					);
				},

				error_func : function(message) {
					medea.NotifyFatal("failure preprocessing shader "
						+ ": " + message
					);
					return;
				},

				pragma_func : function(pragma_text) {
					var r = re_toplevel.exec(pragma_text);
					if (!r) {
						medea.NotifyFatal("syntax error in #pragma toplevel: " + pragma_text);
						return null;
					}

					top_level_decls.push(r[1]);
					return true;
				},
			};

			var cpp = cpp_js(settings);
			cpp.define_multiple(this.defines);
{'fraction_non_alphanumeric': 0.13011152416356878, 'fraction_numerical': 0.0021792077938725804, 'mean_word_length': 2.6680771039022098, 'pattern_counts': {'":': 2, '<': 6, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '7181966', 'n_tokens_mistral': 3348, 'n_tokens_neox': 2573, 'n_words': 620}