Browse Source

Added Shader:getExternVariable(name).

Returns the base type name ('float', 'image', etc.), the number of components (2 for a vec2), and number of array elements (1 for a non-array variable) for the extern variable with the specified name in the shader.

Returns nil if the variable either doesn't exist or was optimized out by the driver's shader compiler.
Alex Szpakowski 11 years ago
parent
commit
f30a0d72f0

+ 44 - 6
src/modules/graphics/opengl/Shader.cpp

@@ -255,7 +255,7 @@ void Shader::mapActiveUniforms()
 		}
 		}
 
 
 		// If this is a built-in (LOVE-created) uniform, store the location.
 		// If this is a built-in (LOVE-created) uniform, store the location.
-		BuiltinExtern builtin;
+		BuiltinUniform builtin;
 		if (builtinNames.find(u.name.c_str(), builtin))
 		if (builtinNames.find(u.name.c_str(), builtin))
 			builtinUniforms[int(builtin)] = u.location;
 			builtinUniforms[int(builtin)] = u.location;
 
 
@@ -660,19 +660,36 @@ int Shader::getTextureUnit(const std::string &name)
 	return texunit;
 	return texunit;
 }
 }
 
 
+Shader::UniformType Shader::getExternVariable(const std::string &name, int &components, int &count)
+{
+	auto it = uniforms.find(name);
+
+	if (it == uniforms.end())
+	{
+		components = 0;
+		count = 0;
+		return UNIFORM_UNKNOWN;
+	}
+
+	components = getUniformTypeSize(it->second.type);
+	count = (int) it->second.count;
+
+	return it->second.baseType;
+}
+
 bool Shader::hasVertexAttrib(OpenGL::VertexAttrib attrib) const
 bool Shader::hasVertexAttrib(OpenGL::VertexAttrib attrib) const
 {
 {
 	return vertexAttributes[int(attrib)] != -1;
 	return vertexAttributes[int(attrib)] != -1;
 }
 }
 
 
-bool Shader::hasBuiltinExtern(BuiltinExtern builtin) const
+bool Shader::hasBuiltinUniform(BuiltinUniform builtin) const
 {
 {
 	return builtinUniforms[int(builtin)] != -1;
 	return builtinUniforms[int(builtin)] != -1;
 }
 }
 
 
-bool Shader::sendBuiltinFloat(BuiltinExtern builtin, int size, const GLfloat *vec, int count)
+bool Shader::sendBuiltinFloat(BuiltinUniform builtin, int size, const GLfloat *vec, int count)
 {
 {
-	if (!hasBuiltinExtern(builtin))
+	if (!hasBuiltinUniform(builtin))
 		return false;
 		return false;
 
 
 	GLint location = builtinUniforms[int(builtin)];
 	GLint location = builtinUniforms[int(builtin)];
@@ -766,6 +783,16 @@ bool Shader::isSupported()
 	return GLEE_VERSION_2_0 && getGLSLVersion() >= "1.2";
 	return GLEE_VERSION_2_0 && getGLSLVersion() >= "1.2";
 }
 }
 
 
+bool Shader::getConstant(const char *in, UniformType &out)
+{
+	return uniformTypes.find(in, out);
+}
+
+bool Shader::getConstant(UniformType in, const char *&out)
+{
+	return uniformTypes.find(in, out);
+}
+
 StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM>::Entry Shader::typeNameEntries[] =
 StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM>::Entry Shader::typeNameEntries[] =
 {
 {
 	{"vertex", Shader::TYPE_VERTEX},
 	{"vertex", Shader::TYPE_VERTEX},
@@ -774,6 +801,17 @@ StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM>::Entry Shader::typeNameEntr
 
 
 StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM> Shader::typeNames(Shader::typeNameEntries, sizeof(Shader::typeNameEntries));
 StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM> Shader::typeNames(Shader::typeNameEntries, sizeof(Shader::typeNameEntries));
 
 
+StringMap<Shader::UniformType, Shader::UNIFORM_MAX_ENUM>::Entry Shader::uniformTypeEntries[] =
+{
+	{"float", Shader::UNIFORM_FLOAT},
+	{"int", Shader::UNIFORM_INT},
+	{"bool", Shader::UNIFORM_BOOL},
+	{"image", Shader::UNIFORM_SAMPLER},
+	{"unknown", Shader::UNIFORM_UNKNOWN},
+};
+
+StringMap<Shader::UniformType, Shader::UNIFORM_MAX_ENUM> Shader::uniformTypes(Shader::uniformTypeEntries, sizeof(Shader::uniformTypeEntries));
+
 StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM>::Entry Shader::attribNameEntries[] =
 StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM>::Entry Shader::attribNameEntries[] =
 {
 {
 	{"love_PseudoInstanceID", OpenGL::ATTRIB_PSEUDO_INSTANCE_ID},
 	{"love_PseudoInstanceID", OpenGL::ATTRIB_PSEUDO_INSTANCE_ID},
@@ -781,12 +819,12 @@ StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM>::Entry Shader::attribNa
 
 
 StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM> Shader::attribNames(Shader::attribNameEntries, sizeof(Shader::attribNameEntries));
 StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM> Shader::attribNames(Shader::attribNameEntries, sizeof(Shader::attribNameEntries));
 
 
-StringMap<Shader::BuiltinExtern, Shader::BUILTIN_MAX_ENUM>::Entry Shader::builtinNameEntries[] =
+StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM>::Entry Shader::builtinNameEntries[] =
 {
 {
 	{"love_ScreenSize", Shader::BUILTIN_SCREEN_SIZE},
 	{"love_ScreenSize", Shader::BUILTIN_SCREEN_SIZE},
 };
 };
 
 
-StringMap<Shader::BuiltinExtern, Shader::BUILTIN_MAX_ENUM> Shader::builtinNames(Shader::builtinNameEntries, sizeof(Shader::builtinNameEntries));
+StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM> Shader::builtinNames(Shader::builtinNameEntries, sizeof(Shader::builtinNameEntries));
 
 
 } // opengl
 } // opengl
 } // graphics
 } // graphics

+ 36 - 16
src/modules/graphics/opengl/Shader.h

@@ -56,13 +56,24 @@ public:
 		TYPE_MAX_ENUM
 		TYPE_MAX_ENUM
 	};
 	};
 
 
-	// Built-in extern (uniform) variables.
-	enum BuiltinExtern
+	// Built-in uniform (extern) variables.
+	enum BuiltinUniform
 	{
 	{
 		BUILTIN_SCREEN_SIZE,
 		BUILTIN_SCREEN_SIZE,
 		BUILTIN_MAX_ENUM
 		BUILTIN_MAX_ENUM
 	};
 	};
 
 
+	// Types of potential uniform (extern) variables used in love's shaders.
+	enum UniformType
+	{
+		UNIFORM_FLOAT,
+		UNIFORM_INT,
+		UNIFORM_BOOL,
+		UNIFORM_SAMPLER,
+		UNIFORM_UNKNOWN,
+		UNIFORM_MAX_ENUM
+	};
+
 	// Type for a list of shader source codes in the form of sources[shadertype] = code
 	// Type for a list of shader source codes in the form of sources[shadertype] = code
 	typedef std::map<ShaderType, std::string> ShaderSources;
 	typedef std::map<ShaderType, std::string> ShaderSources;
 
 
@@ -135,12 +146,25 @@ public:
 	 **/
 	 **/
 	void sendTexture(const std::string &name, Texture *texture);
 	void sendTexture(const std::string &name, Texture *texture);
 
 
+	/**
+	 * Gets the type, number of components, and number of array elements of
+	 * an active 'extern' (uniform) variable in the shader. If a uniform
+	 * variable with the specified name doesn't exist, returns UNIFORM_UNKNOWN
+	 * and sets the 'components' and 'count' values to 0.
+	 *
+	 * @param name The name of the uniform variable in the source code.
+	 * @param[out] components Number of components of the variable (2 for vec2.)
+	 * @param[out] count Number of array elements, if the variable is an array.
+	 * @return The base type of the uniform variable.
+	 **/
+	UniformType getExternVariable(const std::string &name, int &components, int &count);
+
 	/**
 	/**
 	 * Internal use only.
 	 * Internal use only.
 	 **/
 	 **/
 	bool hasVertexAttrib(OpenGL::VertexAttrib attrib) const;
 	bool hasVertexAttrib(OpenGL::VertexAttrib attrib) const;
-	bool hasBuiltinExtern(BuiltinExtern builtin) const;
-	bool sendBuiltinFloat(BuiltinExtern builtin, int size, const GLfloat *m, int count);
+	bool hasBuiltinUniform(BuiltinUniform builtin) const;
+	bool sendBuiltinFloat(BuiltinUniform builtin, int size, const GLfloat *m, int count);
 	void checkSetScreenParams();
 	void checkSetScreenParams();
 
 
 	const std::map<std::string, Object *> &getBoundRetainables() const;
 	const std::map<std::string, Object *> &getBoundRetainables() const;
@@ -148,17 +172,10 @@ public:
 	static std::string getGLSLVersion();
 	static std::string getGLSLVersion();
 	static bool isSupported();
 	static bool isSupported();
 
 
-private:
+	static bool getConstant(const char *in, UniformType &out);
+	static bool getConstant(UniformType in, const char *&out);
 
 
-	// Types of potential uniform variables used in love's shaders.
-	enum UniformType
-	{
-		UNIFORM_FLOAT,
-		UNIFORM_INT,
-		UNIFORM_BOOL,
-		UNIFORM_SAMPLER,
-		UNIFORM_UNKNOWN
-	};
+private:
 
 
 	// Represents a single uniform/extern shader variable.
 	// Represents a single uniform/extern shader variable.
 	struct Uniform
 	struct Uniform
@@ -227,13 +244,16 @@ private:
 	static StringMap<ShaderType, TYPE_MAX_ENUM>::Entry typeNameEntries[];
 	static StringMap<ShaderType, TYPE_MAX_ENUM>::Entry typeNameEntries[];
 	static StringMap<ShaderType, TYPE_MAX_ENUM> typeNames;
 	static StringMap<ShaderType, TYPE_MAX_ENUM> typeNames;
 
 
+	static StringMap<UniformType, UNIFORM_MAX_ENUM>::Entry uniformTypeEntries[];
+	static StringMap<UniformType, UNIFORM_MAX_ENUM> uniformTypes;
+
 	// Names for the generic vertex attributes used by love.
 	// Names for the generic vertex attributes used by love.
 	static StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM>::Entry attribNameEntries[];
 	static StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM>::Entry attribNameEntries[];
 	static StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM> attribNames;
 	static StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM> attribNames;
 
 
 	// Names for the built-in uniform variables.
 	// Names for the built-in uniform variables.
-	static StringMap<BuiltinExtern, BUILTIN_MAX_ENUM>::Entry builtinNameEntries[];
-	static StringMap<BuiltinExtern, BUILTIN_MAX_ENUM> builtinNames;
+	static StringMap<BuiltinUniform, BUILTIN_MAX_ENUM>::Entry builtinNameEntries[];
+	static StringMap<BuiltinUniform, BUILTIN_MAX_ENUM> builtinNames;
 };
 };
 
 
 } // opengl
 } // opengl

+ 33 - 0
src/modules/graphics/opengl/wrap_Shader.cpp

@@ -346,6 +346,38 @@ int w_Shader_send(lua_State *L)
 	return luaL_argerror(L, 3, "number, boolean, table, image, or canvas expected");
 	return luaL_argerror(L, 3, "number, boolean, table, image, or canvas expected");
 }
 }
 
 
+int w_Shader_getExternVariable(lua_State *L)
+{
+	Shader *shader = luax_checkshader(L, 1);
+	const char *name = luaL_checkstring(L, 2);
+
+	int components = 0;
+	int arrayelements = 0;
+	Shader::UniformType type = Shader::UNIFORM_UNKNOWN;
+
+	type = shader->getExternVariable(name, components, arrayelements);
+
+	// Check if the variable exists (function will set components to 0 if not.)
+	if (components > 0)
+	{
+		const char *tname = nullptr;
+		if (!Shader::getConstant(type, tname))
+			return luaL_error(L, "Unknown extern variable type name.");
+
+		lua_pushstring(L, tname);
+		lua_pushinteger(L, components);
+		lua_pushinteger(L, arrayelements);
+	}
+	else
+	{
+		lua_pushnil(L);
+		lua_pushnil(L);
+		lua_pushnil(L);
+	}
+
+	return 3;
+}
+
 static const luaL_Reg functions[] =
 static const luaL_Reg functions[] =
 {
 {
 	{ "getWarnings", w_Shader_getWarnings },
 	{ "getWarnings", w_Shader_getWarnings },
@@ -355,6 +387,7 @@ static const luaL_Reg functions[] =
 	{ "sendMatrix",  w_Shader_sendMatrix },
 	{ "sendMatrix",  w_Shader_sendMatrix },
 	{ "sendTexture", w_Shader_sendTexture },
 	{ "sendTexture", w_Shader_sendTexture },
 	{ "send",        w_Shader_send },
 	{ "send",        w_Shader_send },
+	{ "getExternVariable", w_Shader_getExternVariable },
 
 
 	// Deprecated since 0.9.1.
 	// Deprecated since 0.9.1.
 	{ "sendImage",   w_Shader_sendTexture },
 	{ "sendImage",   w_Shader_sendTexture },

+ 1 - 0
src/modules/graphics/opengl/wrap_Shader.h

@@ -38,6 +38,7 @@ int w_Shader_sendFloat(lua_State *L);
 int w_Shader_sendMatrix(lua_State *L);
 int w_Shader_sendMatrix(lua_State *L);
 int w_Shader_sendTexture(lua_State *L);
 int w_Shader_sendTexture(lua_State *L);
 int w_Shader_send(lua_State *L);
 int w_Shader_send(lua_State *L);
+int w_Shader_getExternVariable(lua_State *L);
 extern "C" int luaopen_shader(lua_State *L);
 extern "C" int luaopen_shader(lua_State *L);
 
 
 } // opengl
 } // opengl