Răsfoiți Sursa

Added GL vertex array object support.

bkaradzic 13 ani în urmă
părinte
comite
9e562eed97
5 a modificat fișierele cu 228 adăugiri și 82 ștergeri
  1. 0 1
      README.md
  2. 31 31
      examples/common/math.h
  3. 4 0
      src/glimports.h
  4. 126 50
      src/renderer_gl.cpp
  5. 67 0
      src/renderer_gl.h

+ 0 - 1
README.md

@@ -206,7 +206,6 @@ Todo
  - OSX and iOS platforms.
  - DX11: MSAA.
  - GL: MSAA.
- - GL: ARB_vertex_array_object + OES_vertex_array_object.
 
 Notice
 ------

+ 31 - 31
examples/common/math.h

@@ -12,21 +12,21 @@
 #include <math.h>
 #include <string.h>
 
-inline float fmin(float _a, float _b)
-{
-	return _a < _b ? _a : _b;
-}
-
-inline float fmax(float _a, float _b)
-{
-	return _a > _b ? _a : _b;
-}
-
-inline float flerp(float _a, float _b, float _t)
-{
-	return _a + (_b - _a) * _t;
-}
-
+inline float fmin(float _a, float _b)
+{
+	return _a < _b ? _a : _b;
+}
+
+inline float fmax(float _a, float _b)
+{
+	return _a > _b ? _a : _b;
+}
+
+inline float flerp(float _a, float _b, float _t)
+{
+	return _a + (_b - _a) * _t;
+}
+
 inline void vec3Add(float* __restrict _result, const float* __restrict _a, const float* __restrict _b)
 {
 	_result[0] = _a[0] + _b[0];
@@ -224,13 +224,13 @@ inline void mtxRotateXYZ(float* _result, float _ax, float _ay, float _az)
 	_result[ 0] = cy*cz;
 	_result[ 1] = -cy*sz;
 	_result[ 2] = sy;
-	_result[ 4] = cz*sx*sy + cx*sz;
-	_result[ 5] = cx*cz - sx*sy*sz;
+	_result[ 4] = cz*sx*sy + cx*sz;
+	_result[ 5] = cx*cz - sx*sy*sz;
 	_result[ 6] = -cy*sx;
-	_result[ 8] = -cx*cz*sy + sx*sz;
-	_result[ 9] = cz*sx + cx*sy*sz;
-	_result[10] = cx*cy;
-	_result[15] = 1.0f;
+	_result[ 8] = -cx*cz*sy + sx*sz;
+	_result[ 9] = cz*sx + cx*sy*sz;
+	_result[10] = cx*cy;
+	_result[15] = 1.0f;
 }
 
 inline void mtxRotateZYX(float* _result, float _ax, float _ay, float _az)
@@ -243,16 +243,16 @@ inline void mtxRotateZYX(float* _result, float _ax, float _ay, float _az)
 	float cz = cosf(_az);
 
 	memset(_result, 0, sizeof(float)*16);
-	_result[ 0] = cy*cz;
-	_result[ 1] = cz*sx*sy-cx*sz;
-	_result[ 2] = cx*cz*sy+sx*sz;
-	_result[ 4] = cy*sz;
-	_result[ 5] = cx*cz + sx*sy*sz;
-	_result[ 6] = -cz*sx + cx*sy*sz;
-	_result[ 8] = -sy;
-	_result[ 9] = cy*sx;
-	_result[10] = cx*cy;
-	_result[15] = 1.0f;
+	_result[ 0] = cy*cz;
+	_result[ 1] = cz*sx*sy-cx*sz;
+	_result[ 2] = cx*cz*sy+sx*sz;
+	_result[ 4] = cy*sz;
+	_result[ 5] = cx*cz + sx*sy*sz;
+	_result[ 6] = -cz*sx + cx*sy*sz;
+	_result[ 8] = -sy;
+	_result[ 9] = cy*sx;
+	_result[10] = cx*cy;
+	_result[15] = 1.0f;
 };
 
 inline void vec3MulMtx(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat)

+ 4 - 0
src/glimports.h

@@ -154,6 +154,10 @@ GL_IMPORT(true,  PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC, glGetTranslatedShaderS
 GL_IMPORT(true,  PFNGLGETPROGRAMBINARYOESPROC,            glGetProgramBinaryOES);
 GL_IMPORT(true,  PFNGLPROGRAMBINARYOESPROC,               glProgramBinaryOES);
 
+GL_IMPORT(true,  PFNGLBINDVERTEXARRAYOESPROC,             glBindVertexArray);
+GL_IMPORT(true,  PFNGLDELETEVERTEXARRAYSOESPROC,          glDeleteVertexArrays);
+GL_IMPORT(true,  PFNGLGENVERTEXARRAYSOESPROC,             glGenVertexArrays);
+
 #endif // BGFX_CONFIG_RENDERER_
 
 #if !BGFX_CONFIG_RENDERER_OPENGLES3

+ 126 - 50
src/renderer_gl.cpp

@@ -10,20 +10,6 @@
 #	include <bx/timer.h>
 #	include <bx/uint32_t.h>
 
-#if !BGFX_CONFIG_RENDERER_OPENGL
-#	define glClearDepth glClearDepthf
-#endif // !BGFX_CONFIG_RENDERER_OPENGL
-
-#if BGFX_CONFIG_RENDERER_OPENGLES2
-#	define glProgramBinary glProgramBinaryOES
-#	define glGetProgramBinary glGetProgramBinaryOES
-#	define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES
-#	define GL_HALF_FLOAT GL_HALF_FLOAT_OES
-#	define GL_RGB10_A2 GL_RGB10_A2_EXT
-#	define GL_UNSIGNED_INT_2_10_10_10_REV GL_UNSIGNED_INT_2_10_10_10_REV_EXT
-#	define GL_SAMPLER_3D GL_SAMPLER_3D_OES
-#endif // BGFX_CONFIG_RENDERER_OPENGLES2
-
 namespace bgfx
 {
 	struct Extension
@@ -64,6 +50,7 @@ namespace bgfx
 			OES_vertex_type_10_10_10_2,
 			EXT_occlusion_query_boolean,
 			ARB_vertex_array_object,
+			OES_vertex_array_object,
 			ATI_meminfo,
 			NVX_gpu_memory_info,
 
@@ -111,6 +98,7 @@ namespace bgfx
 		{ "GL_OES_vertex_type_10_10_10_2",        false, true },
 		{ "GL_EXT_occlusion_query_boolean",       false, true },
 		{ "GL_ARB_vertex_array_object",           false, true },
+		{ "OES_vertex_array_object",              false, true },
 		{ "GL_ATI_meminfo",                       false, true },
 		{ "GL_NVX_gpu_memory_info",               false, true },
 	};
@@ -187,6 +175,7 @@ namespace bgfx
 			, m_captureSize(0)
 			, m_maxAnisotropy(0.0f)
 			, m_dxtSupport(false)
+			, m_vaoSupport(false)
 			, m_programBinarySupport(false)
 			, m_textureSwizzleSupport(false)
 			, m_flip(false)
@@ -613,6 +602,11 @@ namespace bgfx
 			}
 		}
 
+		void invalidateCache()
+		{
+			m_vaoCache.invalidate();
+		}
+
 		void updateCapture()
 		{
 			if (m_resolution.m_flags&BGFX_RESET_CAPTURE)
@@ -695,6 +689,8 @@ namespace bgfx
 
 		void shutdown()
 		{
+			invalidateCache();
+
 #if BGFX_CONFIG_RENDERER_OPENGL
 			m_queries.destroy();
 #endif // BGFX_CONFIG_RENDERER_OPENGL
@@ -731,6 +727,8 @@ namespace bgfx
 		Queries m_queries;
 #endif // BGFX_CONFIG_RENDERER_OPENGL
 
+		VaoCache m_vaoCache;
+
 		TextVideoMem m_textVideoMem;
 
 		Resolution m_resolution;
@@ -738,6 +736,7 @@ namespace bgfx
 		uint32_t m_captureSize;
 		float m_maxAnisotropy;
 		bool m_dxtSupport;
+		bool m_vaoSupport;
 		bool m_programBinarySupport;
 		bool m_textureSwizzleSupport;
 		bool m_flip;
@@ -2054,6 +2053,11 @@ namespace bgfx
 
 	void TextVideoMemBlitter::setup()
 	{
+		if (s_renderCtx.m_vaoSupport)
+		{
+			GL_CHECK(glBindVertexArray(0) );
+		}
+
 		uint32_t width = s_renderCtx.m_resolution.m_width;
 		uint32_t height = s_renderCtx.m_resolution.m_height;
 
@@ -2223,6 +2227,11 @@ namespace bgfx
 				s_extension[Extension::EXT_texture_compression_s3tc].m_supported
 				;
 
+			s_renderCtx.m_vaoSupport = !!BGFX_CONFIG_RENDERER_OPENGLES3
+				|| s_extension[Extension::ARB_vertex_array_object].m_supported
+				|| s_extension[Extension::OES_vertex_array_object].m_supported
+				;
+
 			s_renderCtx.m_programBinarySupport = !!BGFX_CONFIG_RENDERER_OPENGLES3
 				|| s_extension[Extension::ARB_get_program_binary].m_supported
 				|| s_extension[Extension::OES_get_program_binary].m_supported
@@ -2903,57 +2912,124 @@ namespace bgfx
 						}
 					}
 
-					if (currentState.m_vertexBuffer.idx != state.m_vertexBuffer.idx || programChanged)
+					if (s_renderCtx.m_vaoSupport)
 					{
-						currentState.m_vertexBuffer = state.m_vertexBuffer;
-
-						uint16_t handle = state.m_vertexBuffer.idx;
-						if (invalidHandle != handle)
+						if (programChanged
+						||  currentState.m_vertexBuffer.idx != state.m_vertexBuffer.idx
+						||  baseVertex != state.m_startVertex
+						||  currentState.m_indexBuffer.idx != state.m_indexBuffer.idx)
 						{
-							VertexBuffer& vb = s_renderCtx.m_vertexBuffers[handle];
-							GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) );
-							bindAttribs = true;
-						}
-						else
-						{
-							GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) );
+							uint64_t hash = (uint64_t(state.m_vertexBuffer.idx)<<48)
+								| (uint64_t(state.m_indexBuffer.idx)<<32)
+								| (uint64_t(state.m_instanceDataBuffer.idx)<<16)
+								| programIdx
+								;
+							hash ^= state.m_startVertex;
+
+							currentState.m_vertexBuffer = state.m_vertexBuffer;
+							currentState.m_indexBuffer = state.m_indexBuffer;
+							baseVertex = state.m_startVertex;
+
+							GLuint id = s_renderCtx.m_vaoCache.find(hash);
+							if (UINT32_MAX != id)
+							{
+								GL_CHECK(glBindVertexArray(id) );
+							}
+							else
+							{
+								id = s_renderCtx.m_vaoCache.add(hash);
+								GL_CHECK(glBindVertexArray(id) );
+
+								if (invalidHandle != state.m_vertexBuffer.idx)
+								{
+									VertexBuffer& vb = s_renderCtx.m_vertexBuffers[state.m_vertexBuffer.idx];
+									GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) );
+
+									uint16_t decl = vb.m_decl.idx == invalidHandle ? state.m_vertexDecl.idx : vb.m_decl.idx;
+									const Program& program = s_renderCtx.m_program[programIdx];
+									program.bindAttributes(s_renderCtx.m_vertexDecls[decl], state.m_startVertex);
+
+									if (invalidHandle != state.m_instanceDataBuffer.idx)
+									{
+										GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, s_renderCtx.m_vertexBuffers[state.m_instanceDataBuffer.idx].m_id) );
+										program.bindInstanceData(state.m_instanceDataStride, state.m_instanceDataOffset);
+									}
+								}
+								else
+								{
+									GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) );
+								}
+
+								if (invalidHandle != state.m_indexBuffer.idx)
+								{
+									IndexBuffer& ib = s_renderCtx.m_indexBuffers[state.m_indexBuffer.idx];
+									GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.m_id) );
+								}
+								else
+								{
+									GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) );
+								}
+							}
 						}
 					}
-
-					if (currentState.m_indexBuffer.idx != state.m_indexBuffer.idx)
+					else
 					{
-						currentState.m_indexBuffer = state.m_indexBuffer;
-
-						uint16_t handle = state.m_indexBuffer.idx;
-						if (invalidHandle != handle)
+						if (programChanged
+						||  currentState.m_vertexBuffer.idx != state.m_vertexBuffer.idx)
 						{
-							IndexBuffer& ib = s_renderCtx.m_indexBuffers[handle];
-							GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.m_id) );
+							currentState.m_vertexBuffer = state.m_vertexBuffer;
+
+							uint16_t handle = state.m_vertexBuffer.idx;
+							if (invalidHandle != handle)
+							{
+								VertexBuffer& vb = s_renderCtx.m_vertexBuffers[handle];
+								GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) );
+								bindAttribs = true;
+							}
+							else
+							{
+								GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) );
+							}
 						}
-						else
+
+						if (currentState.m_indexBuffer.idx != state.m_indexBuffer.idx)
 						{
-							GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) );
+							currentState.m_indexBuffer = state.m_indexBuffer;
+
+							uint16_t handle = state.m_indexBuffer.idx;
+							if (invalidHandle != handle)
+							{
+								IndexBuffer& ib = s_renderCtx.m_indexBuffers[handle];
+								GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.m_id) );
+							}
+							else
+							{
+								GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) );
+							}
 						}
-					}
 
-					if (invalidHandle != currentState.m_vertexBuffer.idx)
-					{
-						if (baseVertex != state.m_startVertex
-						||  bindAttribs)
+						if (invalidHandle != currentState.m_vertexBuffer.idx)
 						{
-							baseVertex = state.m_startVertex;
-							const VertexBuffer& vb = s_renderCtx.m_vertexBuffers[state.m_vertexBuffer.idx];
-							uint16_t decl = vb.m_decl.idx == invalidHandle ? state.m_vertexDecl.idx : vb.m_decl.idx;
-							const Program& program = s_renderCtx.m_program[programIdx];
-							program.bindAttributes(s_renderCtx.m_vertexDecls[decl], state.m_startVertex);
-							
-							if (invalidHandle != state.m_instanceDataBuffer.idx)
+							if (baseVertex != state.m_startVertex
+							||  bindAttribs)
 							{
-								GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, s_renderCtx.m_vertexBuffers[state.m_instanceDataBuffer.idx].m_id) );
-								program.bindInstanceData(state.m_instanceDataStride, state.m_instanceDataOffset);
+								baseVertex = state.m_startVertex;
+								const VertexBuffer& vb = s_renderCtx.m_vertexBuffers[state.m_vertexBuffer.idx];
+								uint16_t decl = vb.m_decl.idx == invalidHandle ? state.m_vertexDecl.idx : vb.m_decl.idx;
+								const Program& program = s_renderCtx.m_program[programIdx];
+								program.bindAttributes(s_renderCtx.m_vertexDecls[decl], state.m_startVertex);
+
+								if (invalidHandle != state.m_instanceDataBuffer.idx)
+								{
+									GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, s_renderCtx.m_vertexBuffers[state.m_instanceDataBuffer.idx].m_id) );
+									program.bindInstanceData(state.m_instanceDataStride, state.m_instanceDataOffset);
+								}
 							}
 						}
+					}
 
+					if (invalidHandle != currentState.m_vertexBuffer.idx)
+					{
 						uint32_t numVertices = state.m_numVertices;
 						if (UINT32_C(0xffffffff) == numVertices)
 						{

+ 67 - 0
src/renderer_gl.h

@@ -196,6 +196,23 @@ typedef void (APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum z
 #   define GL_APIENTRYP GL_APIENTRY*
 #endif // GL_APIENTRYP
 
+#if !BGFX_CONFIG_RENDERER_OPENGL
+#	define glClearDepth glClearDepthf
+#endif // !BGFX_CONFIG_RENDERER_OPENGL
+
+#if BGFX_CONFIG_RENDERER_OPENGLES2
+#	define glProgramBinary glProgramBinaryOES
+#	define glGetProgramBinary glGetProgramBinaryOES
+#	define glBindVertexArray glBindVertexArrayOES
+#	define glDeleteVertexArrays glDeleteVertexArraysOES
+#	define glGenVertexArrays glGenVertexArraysOES
+#	define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES
+#	define GL_HALF_FLOAT GL_HALF_FLOAT_OES
+#	define GL_RGB10_A2 GL_RGB10_A2_EXT
+#	define GL_UNSIGNED_INT_2_10_10_10_REV GL_UNSIGNED_INT_2_10_10_10_REV_EXT
+#	define GL_SAMPLER_3D GL_SAMPLER_3D_OES
+#endif // BGFX_CONFIG_RENDERER_OPENGLES2
+
 namespace bgfx
 {
 	typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORBGFXPROC)(GLuint _index, GLuint _divisor);
@@ -331,6 +348,56 @@ namespace bgfx
 		VertexDeclHandle m_decl;
 	};
 
+	class VaoCache
+	{
+	public:
+		GLuint add(uint64_t _hash)
+		{
+			invalidate(_hash);
+
+			GLuint arrayId;
+			GL_CHECK(glGenVertexArrays(1, &arrayId) );
+
+			m_hashMap.insert(stl::make_pair(_hash, arrayId) );
+
+			return arrayId;
+		}
+
+		GLuint find(uint64_t _hash)
+		{
+			HashMap::iterator it = m_hashMap.find(_hash);
+			if (it != m_hashMap.end() )
+			{
+				return it->second;
+			}
+
+			return UINT32_MAX;
+		}
+
+		void invalidate(uint64_t _hash)
+		{
+			HashMap::iterator it = m_hashMap.find(_hash);
+			if (it != m_hashMap.end() )
+			{
+				GL_CHECK(glDeleteVertexArrays(1, &it->second) );
+				m_hashMap.erase(it);
+			}
+		}
+
+		void invalidate()
+		{
+			for (HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd; ++it)
+			{
+				GL_CHECK(glDeleteVertexArrays(1, &it->second) );
+			}
+			m_hashMap.clear();
+		}
+
+	private:
+		typedef stl::unordered_map<uint64_t, GLuint> HashMap;
+		HashMap m_hashMap;
+	};
+
 	struct Texture
 	{
 		Texture()