From 3cf263ec86da5c68956836c2b1cb8aca8ec70bc0 Mon Sep 17 00:00:00 2001 From: bkaradzic Date: Thu, 12 Dec 2013 22:35:27 -0800 Subject: [PATCH] GLES2: Added support for 3D texture extension. Added shader patching to enable extensions. --- src/glimports.h | 4 ++ src/renderer_gl.cpp | 152 ++++++++++++++++++++++++++++++++++++++------ src/renderer_gl.h | 59 ++++------------- 3 files changed, 151 insertions(+), 64 deletions(-) diff --git a/src/glimports.h b/src/glimports.h index 57abf5b7..d9d25ab7 100644 --- a/src/glimports.h +++ b/src/glimports.h @@ -181,6 +181,10 @@ GL_IMPORT____(true, PFNGLFRAMETERMINATORGREMEDYPROC, glFrameTerminat GL_IMPORT____(true, PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC, glGetTranslatedShaderSourceANGLE); GL_IMPORT____(true, PFNGLGETPROGRAMBINARYOESPROC, glGetProgramBinaryOES); GL_IMPORT____(true, PFNGLPROGRAMBINARYOESPROC, glProgramBinaryOES); +GL_IMPORT____(true, PFNGLTEXIMAGE3DOESPROC, glTexImage3DOES); +GL_IMPORT____(true, PFNGLTEXSUBIMAGE3DOESPROC, glTexSubImage3DOES); +GL_IMPORT____(true, PFNGLCOMPRESSEDTEXIMAGE3DOESPROC, glCompressedTexImage3DOES); +GL_IMPORT____(true, PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC, glCompressedTexSubImage3DOES); GL_IMPORT____(true, PFNGLBINDVERTEXARRAYOESPROC, glBindVertexArrayOES); GL_IMPORT____(true, PFNGLDELETEVERTEXARRAYSOESPROC, glDeleteVertexArraysOES); diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 2e6897a6..417606c3 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -279,6 +279,7 @@ namespace bgfx OES_read_format, OES_rgb8_rgba8, OES_standard_derivatives, + OES_texture_3D, OES_texture_float, OES_texture_float_linear, OES_texture_half_float, @@ -352,6 +353,7 @@ namespace bgfx { "GL_OES_read_format", false, true }, { "GL_OES_rgb8_rgba8", false, true }, { "GL_OES_standard_derivatives", false, true }, + { "GL_OES_texture_3D", false, true }, { "GL_OES_texture_float", false, true }, { "GL_OES_texture_float_linear", false, true }, { "GL_OES_texture_half_float", false, true }, @@ -396,13 +398,17 @@ namespace bgfx #endif // BGFX_CONFIG_DEBUG_GREMEDY #if BX_PLATFORM_IOS - PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES = NULL; - PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES = NULL; - PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES = NULL; - PFNGLPROGRAMBINARYOESPROC glProgramBinaryOES = NULL; - PFNGLGETPROGRAMBINARYOESPROC glGetProgramBinaryOES = NULL; - PFLGLDRAWARRAYSINSTANCEDANGLEPROC glDrawArraysInstanced = NULL; - PFLGLDRAWELEMENTSINSTANCEDANGLEPROC glDrawElementsInstanced = NULL; + PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES = NULL; + PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES = NULL; + PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES = NULL; + PFNGLPROGRAMBINARYOESPROC glProgramBinaryOES = NULL; + PFNGLGETPROGRAMBINARYOESPROC glGetProgramBinaryOES = NULL; + PFNGLTEXIMAGE3DOESPROC glTexImage3DOES = NULL; + PFNGLTEXSUBIMAGE3DOESPROC glTexSubImage3DOES = NULL; + PFNGLCOMPRESSEDTEXIMAGE3DOESPROC glCompressedTexImage3DOES = NULL; + PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC glCompressedTexSubImage3DOES = NULL; + PFLGLDRAWARRAYSINSTANCEDANGLEPROC glDrawArraysInstanced = NULL; + PFLGLDRAWELEMENTSINSTANCEDANGLEPROC glDrawElementsInstanced = NULL; #endif // BX_PLATFORM_IOS typedef void (*PostSwapBuffersFn)(uint32_t _width, uint32_t _height); @@ -1276,13 +1282,11 @@ namespace bgfx _internalFormat = _format; // GLES wants internal format to match format... #endif // !BGFX_CONFIG_RENDERER_OPENGL -#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 if (_target == GL_TEXTURE_3D) { GL_CHECK(glTexImage3D(_target, _level, _internalFormat, _width, _height, _depth, _border, _format, _type, _data) ); } else -#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 { BX_UNUSED(_depth); GL_CHECK(glTexImage2D(_target, _level, _internalFormat, _width, _height, _border, _format, _type, _data) ); @@ -1291,13 +1295,11 @@ namespace bgfx static void texSubImage(GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset, GLint _zoffset, GLsizei _width, GLsizei _height, GLsizei _depth, GLenum _format, GLenum _type, const GLvoid* _data) { -#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 if (_target == GL_TEXTURE_3D) { GL_CHECK(glTexSubImage3D(_target, _level, _xoffset, _yoffset, _zoffset, _width, _height, _depth, _format, _type, _data) ); } else -#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 { BX_UNUSED(_zoffset, _depth); GL_CHECK(glTexSubImage2D(_target, _level, _xoffset, _yoffset, _width, _height, _format, _type, _data) ); @@ -1306,13 +1308,11 @@ namespace bgfx static void compressedTexImage(GLenum _target, GLint _level, GLenum _internalformat, GLsizei _width, GLsizei _height, GLsizei _depth, GLint _border, GLsizei _imageSize, const GLvoid* _data) { -#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 if (_target == GL_TEXTURE_3D) { GL_CHECK(glCompressedTexImage3D(_target, _level, _internalformat, _width, _height, _depth, _border, _imageSize, _data) ); } else -#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 { BX_UNUSED(_depth); GL_CHECK(glCompressedTexImage2D(_target, _level, _internalformat, _width, _height, _border, _imageSize, _data) ); @@ -1321,13 +1321,11 @@ namespace bgfx static void compressedTexSubImage(GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset, GLint _zoffset, GLsizei _width, GLsizei _height, GLsizei _depth, GLenum _format, GLsizei _imageSize, const GLvoid* _data) { -#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 if (_target == GL_TEXTURE_3D) { GL_CHECK(glCompressedTexSubImage3D(_target, _level, _xoffset, _yoffset, _zoffset, _width, _height, _depth, _format, _imageSize, _data) ); } else -#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 { BX_UNUSED(_zoffset, _depth); GL_CHECK(glCompressedTexSubImage2D(_target, _level, _xoffset, _yoffset, _width, _height, _format, _imageSize, _data) ); @@ -1387,12 +1385,10 @@ namespace bgfx { target = GL_TEXTURE_CUBE_MAP; } -#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 else if (imageContainer.m_depth > 1) { target = GL_TEXTURE_3D; } -#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 init(target , imageContainer.m_format @@ -1717,12 +1713,12 @@ namespace bgfx #if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 GL_CHECK(glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, numMips-1) ); +#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 if (target == GL_TEXTURE_3D) { GL_CHECK(glTexParameteri(target, GL_TEXTURE_WRAP_R, s_textureAddress[(flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT]) ); } -#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 uint32_t mag = (flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT; uint32_t min = (flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT; @@ -1764,6 +1760,124 @@ namespace bgfx #endif // BGFX_CONFIG_RENDERER_* } + void writeString(bx::WriterI* _writer, const char* _str) + { + bx::write(_writer, _str, strlen(_str) ); + } + + const char* findMatch(const char* _str, const char* _word) + { + size_t len = strlen(_word); + const char* ptr = strstr(_str, _word); + for (; NULL != ptr; ptr = strstr(ptr + len, _word) ) + { + if (ptr != _str) + { + char ch = *(ptr - 1); + if (isalnum(ch) || '_' == ch) + { + continue; + } + } + + char ch = ptr[len]; + if (isalnum(ch) || '_' == ch) + { + continue; + } + + return ptr; + } + + return ptr; + } + + void Shader::create(GLenum _type, Memory* _mem) + { + m_id = glCreateShader(_type); + m_type = _type; + + bx::MemoryReader reader(_mem->data, _mem->size); + m_hash = bx::hashMurmur2A(_mem->data, _mem->size); + + uint32_t magic; + bx::read(&reader, magic); + + uint32_t iohash; + bx::read(&reader, iohash); + + const char* code = (const char*)reader.getDataPtr(); + + if (0 != m_id) + { +#if BGFX_CONFIG_RENDERER_OPENGLES2 + bool usesDerivatives = s_extension[Extension::OES_standard_derivatives].m_supported && + ( findMatch(code, "dFdx") + || findMatch(code, "dFdy") + || findMatch(code, "fwidth") + ); + + bool usesTexture3D = s_extension[Extension::OES_texture_3D].m_supported && + ( findMatch(code, "texture3D") + || findMatch(code, "texture3DProj") + || findMatch(code, "texture3DLod") + || findMatch(code, "texture3DProjLod") + ); + + if (usesDerivatives + || usesTexture3D) + { + size_t codeLen = strlen(code); + size_t tempLen = codeLen + 1024; + char* temp = (char*)alloca(tempLen); + bx::StaticMemoryBlockWriter writer(temp, tempLen); + + if (usesDerivatives) + { + writeString(&writer, "#extension GL_OES_standard_derivatives : enable\n"); + } + + if (usesTexture3D) + { + writeString(&writer, "#extension GL_OES_texture_3D : enable\n"); + } + + bx::write(&writer, code, codeLen); + bx::write(&writer, '\0'); + + code = temp; + } +#endif // BGFX_CONFIG_RENDERER_OPENGLES2 + + GL_CHECK(glShaderSource(m_id, 1, (const GLchar**)&code, NULL) ); + GL_CHECK(glCompileShader(m_id) ); + + GLint compiled = 0; + GL_CHECK(glGetShaderiv(m_id, GL_COMPILE_STATUS, &compiled) ); + + if (0 == compiled) + { + BX_TRACE("\n####\n%s\n####", code); + + char log[1024]; + GL_CHECK(glGetShaderInfoLog(m_id, sizeof(log), NULL, log) ); + BX_TRACE("Failed to compile shader. %d: %s", compiled, log); + + GL_CHECK(glDeleteShader(m_id) ); + BGFX_FATAL(false, bgfx::Fatal::InvalidShader, "Failed to compile shader."); + } + } + } + + void Shader::destroy() + { + if (0 != m_id) + { + GL_CHECK(glDeleteShader(m_id) ); + m_id = 0; + } + } + void RenderTarget::create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) { BX_TRACE("Create render target %dx%d 0x%02x", _width, _height, _flags); @@ -2413,7 +2527,7 @@ namespace bgfx | ptc1Supported ? BGFX_CAPS_TEXTURE_FORMAT_PTC12|BGFX_CAPS_TEXTURE_FORMAT_PTC14|BGFX_CAPS_TEXTURE_FORMAT_PTC14A|BGFX_CAPS_TEXTURE_FORMAT_PTC12A : 0 | ptc2Supported ? BGFX_CAPS_TEXTURE_FORMAT_PTC22|BGFX_CAPS_TEXTURE_FORMAT_PTC24 : 0 ); - g_caps.supported |= !!(BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3) + g_caps.supported |= !!(BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3)|s_extension[Extension::OES_texture_3D].m_supported ? BGFX_CAPS_TEXTURE_3D : 0 ; diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 138bc561..2c35a0b1 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -55,12 +55,18 @@ typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arra typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array); typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length); +typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); typedef void (GL_APIENTRYP PFLGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); typedef void (GL_APIENTRYP PFLGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); typedef void (GL_APIENTRYP PFLGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor); //#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6 #define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368 +#define GL_TEXTURE_3D_OES 0x806F #define GL_SAMPLER_3D_OES 0x8B5F +#define GL_TEXTURE_WRAP_R_OES 0x8072 #define GL_PROGRAM_BINARY_LENGTH_OES 0x8741 # else # include @@ -69,6 +75,10 @@ typedef void (GL_APIENTRYP PFLGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLu # endif // BX_PLATFORM_ # define glProgramBinary glProgramBinaryOES # define glGetProgramBinary glGetProgramBinaryOES +# define glTexImage3D glTexImage3DOES +# define glTexSubImage3D glTexSubImage3DOES +# define glCompressedTexImage3D glCompressedTexImage3DOES +# define glCompressedTexSubImage3D glCompressedTexSubImage3DOES # define glBindVertexArray glBindVertexArrayOES # define glDeleteVertexArrays glDeleteVertexArraysOES # define glGenVertexArrays glGenVertexArraysOES @@ -79,7 +89,9 @@ typedef void (GL_APIENTRYP PFLGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLu # define GL_R16F GL_R16F_EXT # define GL_R32F GL_R32F_EXT # define GL_UNSIGNED_INT_2_10_10_10_REV GL_UNSIGNED_INT_2_10_10_10_REV_EXT +# define GL_TEXTURE_3D GL_TEXTURE_3D_OES # define GL_SAMPLER_3D GL_SAMPLER_3D_OES +# define GL_TEXTURE_WRAP_R GL_TEXTURE_WRAP_R_OES # define GL_MIN GL_MIN_EXT # define GL_MAX GL_MAX_EXT # elif BGFX_CONFIG_RENDERER_OPENGLES3 @@ -571,51 +583,8 @@ namespace bgfx { } - void create(GLenum _type, Memory* _mem) - { - m_id = glCreateShader(_type); - m_type = _type; - - bx::MemoryReader reader(_mem->data, _mem->size); - m_hash = bx::hashMurmur2A(_mem->data, _mem->size); - - uint32_t magic; - bx::read(&reader, magic); - - uint32_t iohash; - bx::read(&reader, iohash); - - const uint8_t* code = reader.getDataPtr(); - - if (0 != m_id) - { - GL_CHECK(glShaderSource(m_id, 1, (const GLchar**)&code, NULL) ); - GL_CHECK(glCompileShader(m_id) ); - - GLint compiled = 0; - GL_CHECK(glGetShaderiv(m_id, GL_COMPILE_STATUS, &compiled) ); - - if (0 == compiled) - { - char log[1024]; - GL_CHECK(glGetShaderInfoLog(m_id, sizeof(log), NULL, log) ); - BX_TRACE("Failed to compile shader. %d: %s", compiled, log); - BX_TRACE("\n####\n%s\n####", code); - - GL_CHECK(glDeleteShader(m_id) ); - BGFX_FATAL(false, bgfx::Fatal::InvalidShader, "Failed to compile shader."); - } - } - } - - void destroy() - { - if (0 != m_id) - { - GL_CHECK(glDeleteShader(m_id) ); - m_id = 0; - } - } + void create(GLenum _type, Memory* _mem); + void destroy(); GLuint m_id; GLenum m_type;