Browse Source

Cleaned up some shader code.

--HG--
branch : minor
Alex Szpakowski 10 years ago
parent
commit
3fea174008

+ 1 - 1
src/modules/graphics/opengl/Canvas.cpp

@@ -389,7 +389,7 @@ void Canvas::setupGrab()
 
 
 	// bind the framebuffer object.
 	// bind the framebuffer object.
 	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
 	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
-	gl.setViewport(OpenGL::Viewport(0, 0, width, height));
+	gl.setViewport({0, 0, width, height});
 
 
 	// Set up the projection matrix
 	// Set up the projection matrix
 	gl.matrices.projection.push_back(Matrix::ortho(0.0, width, 0.0, height));
 	gl.matrices.projection.push_back(Matrix::ortho(0.0, width, 0.0, height));

+ 2 - 2
src/modules/graphics/opengl/Graphics.cpp

@@ -219,7 +219,7 @@ void Graphics::setViewportSize(int width, int height)
 	setCanvas();
 	setCanvas();
 
 
 	// Set the viewport to top-left corner.
 	// Set the viewport to top-left corner.
-	gl.setViewport(OpenGL::Viewport(0, 0, width, height));
+	gl.setViewport({0, 0, width, height});
 
 
 	// If a canvas was bound before this function was called, it needs to be
 	// If a canvas was bound before this function was called, it needs to be
 	// made aware of the new system viewport size.
 	// made aware of the new system viewport size.
@@ -512,7 +512,7 @@ bool Graphics::isCreated() const
 
 
 void Graphics::setScissor(int x, int y, int width, int height)
 void Graphics::setScissor(int x, int y, int width, int height)
 {
 {
-	OpenGL::Viewport box(x, y, width, height);
+	OpenGL::Viewport box = {x, y, width, height};
 
 
 	states.back().scissor = true;
 	states.back().scissor = true;
 	glEnable(GL_SCISSOR_TEST);
 	glEnable(GL_SCISSOR_TEST);

+ 30 - 17
src/modules/graphics/opengl/OpenGL.cpp

@@ -52,8 +52,9 @@ OpenGL::OpenGL()
 	, contextInitialized(false)
 	, contextInitialized(false)
 	, maxAnisotropy(1.0f)
 	, maxAnisotropy(1.0f)
 	, maxTextureSize(0)
 	, maxTextureSize(0)
-	, maxRenderTargets(0)
+	, maxRenderTargets(1)
 	, maxRenderbufferSamples(0)
 	, maxRenderbufferSamples(0)
+	, maxTextureUnits(1)
 	, vendor(VENDOR_UNKNOWN)
 	, vendor(VENDOR_UNKNOWN)
 	, state()
 	, state()
 {
 {
@@ -83,6 +84,8 @@ void OpenGL::setupContext()
 	if (!contextInitialized)
 	if (!contextInitialized)
 		return;
 		return;
 
 
+	initMaxValues();
+
 	state.color = Color(255, 255, 255, 255);
 	state.color = Color(255, 255, 255, 255);
 	GLfloat glcolor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
 	GLfloat glcolor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
 	glVertexAttrib4fv(ATTRIB_COLOR, glcolor);
 	glVertexAttrib4fv(ATTRIB_COLOR, glcolor);
@@ -102,11 +105,7 @@ void OpenGL::setupContext()
 
 
 	// Initialize multiple texture unit support for shaders.
 	// Initialize multiple texture unit support for shaders.
 	state.boundTextures.clear();
 	state.boundTextures.clear();
-
-	GLint maxtextureunits;
-	glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxtextureunits);
-
-	state.boundTextures.resize(maxtextureunits, 0);
+	state.boundTextures.resize(maxTextureUnits, 0);
 
 
 	GLenum curgltextureunit;
 	GLenum curgltextureunit;
 	glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *) &curgltextureunit);
 	glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *) &curgltextureunit);
@@ -125,7 +124,6 @@ void OpenGL::setupContext()
 	BlendState blend = {GL_ONE, GL_ONE, GL_ZERO, GL_ZERO, GL_FUNC_ADD};
 	BlendState blend = {GL_ONE, GL_ONE, GL_ZERO, GL_ZERO, GL_FUNC_ADD};
 	setBlendState(blend);
 	setBlendState(blend);
 
 
-	initMaxValues();
 	createDefaultTexture();
 	createDefaultTexture();
 
 
 	// Invalidate the cached matrices by setting some elements to NaN.
 	// Invalidate the cached matrices by setting some elements to NaN.
@@ -257,6 +255,8 @@ void OpenGL::initMaxValues()
 	}
 	}
 	else
 	else
 		maxRenderbufferSamples = 0;
 		maxRenderbufferSamples = 0;
+
+	glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
 }
 }
 
 
 void OpenGL::initMatrices()
 void OpenGL::initMatrices()
@@ -484,21 +484,29 @@ void OpenGL::bindTexture(GLuint texture)
 	}
 	}
 }
 }
 
 
-void OpenGL::bindTextureToUnit(GLuint texture, int textureunit, bool restoreprev)
+void OpenGL::bindTextures(GLuint first, GLsizei count, const GLuint *textures)
 {
 {
-	if (textureunit < 0 || (size_t) textureunit >= state.boundTextures.size())
-		throw love::Exception("Invalid texture unit index.");
+	if (first + count > (GLuint) maxTextureUnits)
+		return;
 
 
-	if (texture != state.boundTextures[textureunit])
+	if (GLAD_VERSION_4_4 || GLAD_ARB_multi_bind)
+		glBindTextures(first, count, textures);
+	else
 	{
 	{
-		int oldtextureunit = state.curTextureUnit;
-		setTextureUnit(textureunit);
+		for (GLint i = 0; i < count; i++)
+		{
+			GLuint texture = textures != nullptr ? textures[i] : 0;
 
 
-		state.boundTextures[textureunit] = texture;
-		glBindTexture(GL_TEXTURE_2D, texture);
+			if (state.boundTextures[first + i] != texture)
+			{
+				glActiveTexture(GL_TEXTURE0 + first + i);
+				glBindTexture(GL_TEXTURE_2D, texture);
+
+				state.boundTextures[first + i] = texture;
+			}
+		}
 
 
-		if (restoreprev)
-			setTextureUnit(oldtextureunit);
+		glActiveTexture(GL_TEXTURE0 + state.curTextureUnit);
 	}
 	}
 }
 }
 
 
@@ -598,6 +606,11 @@ int OpenGL::getMaxRenderbufferSamples() const
 	return maxRenderbufferSamples;
 	return maxRenderbufferSamples;
 }
 }
 
 
+int OpenGL::getMaxTextureUnits() const
+{
+	return maxTextureUnits;
+}
+
 void OpenGL::updateTextureMemorySize(size_t oldsize, size_t newsize)
 void OpenGL::updateTextureMemorySize(size_t oldsize, size_t newsize)
 {
 {
 	int64 memsize = (int64) stats.textureMemory + ((int64 )newsize -  (int64) oldsize);
 	int64 memsize = (int64) stats.textureMemory + ((int64 )newsize -  (int64) oldsize);

+ 9 - 14
src/modules/graphics/opengl/OpenGL.h

@@ -55,7 +55,6 @@ enum VertexAttribID
 	ATTRIB_POS = 0,
 	ATTRIB_POS = 0,
 	ATTRIB_TEXCOORD,
 	ATTRIB_TEXCOORD,
 	ATTRIB_COLOR,
 	ATTRIB_COLOR,
-	ATTRIB_PSEUDO_INSTANCE_ID, // Instance ID used with pseudo-instancing.
 	ATTRIB_MAX_ENUM
 	ATTRIB_MAX_ENUM
 };
 };
 
 
@@ -93,14 +92,6 @@ public:
 		int x, y;
 		int x, y;
 		int w, h;
 		int w, h;
 
 
-		Viewport()
-			: x(0), y(0), w(0), h(0)
-		{}
-
-		Viewport(int _x, int _y, int _w, int _h)
-			: x(_x), y(_y), w(_w), h(_h)
-		{}
-
 		bool operator == (const Viewport &rhs) const
 		bool operator == (const Viewport &rhs) const
 		{
 		{
 			return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
 			return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
@@ -271,12 +262,10 @@ public:
 	void bindTexture(GLuint texture);
 	void bindTexture(GLuint texture);
 
 
 	/**
 	/**
-	 * Helper for binding a texture to a specific texture unit.
-	 *
-	 * @param textureunit Index in the range of [0, maxtextureunits-1]
-	 * @param restoreprev Restore previously bound texture unit when done.
+	 * Binds multiple textures to texture units without changing the active
+	 * texture unit. Equivalent to glBindTextures.
 	 **/
 	 **/
-	void bindTextureToUnit(GLuint texture, int textureunit, bool restoreprev);
+	void bindTextures(GLuint first, GLsizei count, const GLuint *textures);
 
 
 	/**
 	/**
 	 * Helper for deleting an OpenGL texture.
 	 * Helper for deleting an OpenGL texture.
@@ -311,6 +300,11 @@ public:
 	 **/
 	 **/
 	int getMaxRenderbufferSamples() const;
 	int getMaxRenderbufferSamples() const;
 
 
+	/**
+	 * Returns the maximum number of accessible texture units.
+	 **/
+	int getMaxTextureUnits() const;
+
 	void updateTextureMemorySize(size_t oldsize, size_t newsize);
 	void updateTextureMemorySize(size_t oldsize, size_t newsize);
 
 
 	/**
 	/**
@@ -337,6 +331,7 @@ private:
 	int maxTextureSize;
 	int maxTextureSize;
 	int maxRenderTargets;
 	int maxRenderTargets;
 	int maxRenderbufferSamples;
 	int maxRenderbufferSamples;
+	int maxTextureUnits;
 
 
 	Vendor vendor;
 	Vendor vendor;
 
 

+ 7 - 34
src/modules/graphics/opengl/Shader.cpp

@@ -66,7 +66,6 @@ Shader *Shader::defaultShader = nullptr;
 
 
 Shader::ShaderSource Shader::defaultCode[Graphics::RENDERER_MAX_ENUM];
 Shader::ShaderSource Shader::defaultCode[Graphics::RENDERER_MAX_ENUM];
 
 
-GLint Shader::maxTexUnits = 0;
 std::vector<int> Shader::textureCounters;
 std::vector<int> Shader::textureCounters;
 
 
 Shader::Shader(const ShaderSource &source)
 Shader::Shader(const ShaderSource &source)
@@ -80,16 +79,9 @@ Shader::Shader(const ShaderSource &source)
 	if (source.vertex.empty() && source.pixel.empty())
 	if (source.vertex.empty() && source.pixel.empty())
 		throw love::Exception("Cannot create shader: no source code!");
 		throw love::Exception("Cannot create shader: no source code!");
 
 
-	if (maxTexUnits <= 0)
-	{
-		GLint maxtexunits;
-		glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxtexunits);
-		maxTexUnits = std::max(maxtexunits - 1, 0);
-	}
-
 	// initialize global texture id counters if needed
 	// initialize global texture id counters if needed
-	if (textureCounters.size() < (size_t) maxTexUnits)
-		textureCounters.resize(maxTexUnits, 0);
+	if ((int) textureCounters.size() < gl.getMaxTextureUnits())
+		textureCounters.resize(gl.getMaxTextureUnits(), 0);
 
 
 	// load shader source and create program object
 	// load shader source and create program object
 	loadVolatile();
 	loadVolatile();
@@ -224,7 +216,7 @@ bool Shader::loadVolatile()
 
 
 	// zero out active texture list
 	// zero out active texture list
 	activeTexUnits.clear();
 	activeTexUnits.clear();
-	activeTexUnits.insert(activeTexUnits.begin(), maxTexUnits, 0);
+	activeTexUnits.insert(activeTexUnits.begin(), gl.getMaxTextureUnits(), 0);
 
 
 	std::vector<GLuint> shaderids;
 	std::vector<GLuint> shaderids;
 
 
@@ -263,16 +255,8 @@ bool Shader::loadVolatile()
 	// Bind generic vertex attribute indices to names in the shader.
 	// Bind generic vertex attribute indices to names in the shader.
 	for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++)
 	for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++)
 	{
 	{
-		VertexAttribID attrib = (VertexAttribID) i;
-
-		// FIXME: We skip this both because pseudo-instancing is temporarily
-		// disabled (see graphics.lua), and because binding a non-existant
-		// attribute name to a location causes a shader linker warning.
-		if (attrib == ATTRIB_PSEUDO_INSTANCE_ID)
-			continue;
-
 		const char *name = nullptr;
 		const char *name = nullptr;
-		if (attribNames.find(attrib, name))
+		if (attribNames.find((VertexAttribID) i, name))
 			glBindAttribLocation(program, i, (const GLchar *) name);
 			glBindAttribLocation(program, i, (const GLchar *) name);
 	}
 	}
 
 
@@ -336,7 +320,7 @@ void Shader::unloadVolatile()
 
 
 	// active texture list is probably invalid, clear it
 	// active texture list is probably invalid, clear it
 	activeTexUnits.clear();
 	activeTexUnits.clear();
-	activeTexUnits.resize(maxTexUnits, 0);
+	activeTexUnits.resize(gl.getMaxTextureUnits(), 0);
 
 
 	// same with uniform location list
 	// same with uniform location list
 	uniforms.clear();
 	uniforms.clear();
@@ -398,14 +382,7 @@ void Shader::attach(bool temporary)
 	{
 	{
 		// make sure all sent textures are properly bound to their respective texture units
 		// make sure all sent textures are properly bound to their respective texture units
 		// note: list potentially contains texture ids of deleted/invalid textures!
 		// note: list potentially contains texture ids of deleted/invalid textures!
-		for (size_t i = 0; i < activeTexUnits.size(); ++i)
-		{
-			if (activeTexUnits[i] > 0)
-				gl.bindTextureToUnit(activeTexUnits[i], (int) i + 1, false);
-		}
-
-		// We always want to use texture unit 0 for everyhing else.
-		gl.setTextureUnit(0);
+		gl.bindTextures(1, (GLsizei) activeTexUnits.size(), &activeTexUnits[0]);
 	}
 	}
 }
 }
 
 
@@ -546,13 +523,10 @@ void Shader::sendTexture(const std::string &name, Texture *texture)
 	checkSetUniformError(u, 1, 1, UNIFORM_SAMPLER);
 	checkSetUniformError(u, 1, 1, UNIFORM_SAMPLER);
 
 
 	// bind texture to assigned texture unit and send uniform to shader program
 	// bind texture to assigned texture unit and send uniform to shader program
-	gl.bindTextureToUnit(gltex, texunit, false);
+	gl.bindTextures(texunit, 1, &gltex);
 
 
 	glUniform1i(u.location, texunit);
 	glUniform1i(u.location, texunit);
 
 
-	// reset texture unit
-	gl.setTextureUnit(0);
-
 	// increment global shader texture id counter for this texture unit, if we haven't already
 	// increment global shader texture id counter for this texture unit, if we haven't already
 	if (activeTexUnits[texunit-1] == 0)
 	if (activeTexUnits[texunit-1] == 0)
 		++textureCounters[texunit-1];
 		++textureCounters[texunit-1];
@@ -849,7 +823,6 @@ StringMap<VertexAttribID, ATTRIB_MAX_ENUM>::Entry Shader::attribNameEntries[] =
 	{"VertexPosition", ATTRIB_POS},
 	{"VertexPosition", ATTRIB_POS},
 	{"VertexTexCoord", ATTRIB_TEXCOORD},
 	{"VertexTexCoord", ATTRIB_TEXCOORD},
 	{"VertexColor", ATTRIB_COLOR},
 	{"VertexColor", ATTRIB_COLOR},
-	{"love_PseudoInstanceID", ATTRIB_PSEUDO_INSTANCE_ID},
 };
 };
 
 
 StringMap<VertexAttribID, ATTRIB_MAX_ENUM> Shader::attribNames(Shader::attribNameEntries, sizeof(Shader::attribNameEntries));
 StringMap<VertexAttribID, ATTRIB_MAX_ENUM> Shader::attribNames(Shader::attribNameEntries, sizeof(Shader::attribNameEntries));

+ 0 - 3
src/modules/graphics/opengl/Shader.h

@@ -250,9 +250,6 @@ private:
 	Canvas *lastCanvas;
 	Canvas *lastCanvas;
 	OpenGL::Viewport lastViewport;
 	OpenGL::Viewport lastViewport;
 
 
-	// Max GPU texture units available for sent images
-	static GLint maxTexUnits;
-
 	// Counts total number of textures bound to each texture unit in all shaders
 	// Counts total number of textures bound to each texture unit in all shaders
 	static std::vector<int> textureCounters;
 	static std::vector<int> textureCounters;
 
 

+ 2 - 8
src/modules/graphics/opengl/wrap_Image.cpp

@@ -94,15 +94,9 @@ int w_Image_getData(lua_State *L)
 	Image *i = luax_checkimage(L, 1);
 	Image *i = luax_checkimage(L, 1);
 
 
 	if (i->isCompressed())
 	if (i->isCompressed())
-	{
-		love::image::CompressedData *t = i->getCompressedData();
-		luax_pushtype(L, IMAGE_COMPRESSED_DATA_ID, t);
-	}
+		luax_pushtype(L, IMAGE_COMPRESSED_DATA_ID, i->getCompressedData());
 	else
 	else
-	{
-		love::image::ImageData *t = i->getImageData();
-		luax_pushtype(L, IMAGE_IMAGE_DATA_ID, t);
-	}
+		luax_pushtype(L, IMAGE_IMAGE_DATA_ID, i->getImageData());
 
 
 	return 1;
 	return 1;
 }
 }

+ 1 - 1
src/modules/graphics/opengl/wrap_Shader.cpp

@@ -308,7 +308,7 @@ int w_Shader_send(lua_State *L)
 		// Texture (Image or Canvas).
 		// Texture (Image or Canvas).
 		p = (Proxy *) lua_touserdata(L, 3);
 		p = (Proxy *) lua_touserdata(L, 3);
 
 
-		if (typeFlags[p->type][GRAPHICS_TEXT_ID])
+		if (typeFlags[p->type][GRAPHICS_TEXTURE_ID])
 			return w_Shader_sendTexture(L);
 			return w_Shader_sendTexture(L);
 
 
 		break;
 		break;