浏览代码

GL: Added support for texture array.

Branimir Karadžić 9 年之前
父节点
当前提交
7537b705e5

+ 1 - 1
examples/07-callback/callback.cpp

@@ -139,7 +139,7 @@ struct BgfxCallback : public bgfx::CallbackI
 	virtual void traceVargs(const char* _filePath, uint16_t _line, const char* _format, va_list _argList) BX_OVERRIDE
 	{
 		dbgPrintf("%s (%d): ", _filePath, _line);
-		dbgPrintfVargs(_format, _argList);
+		dbgPrintf(_format, _argList);
 	}
 
 	virtual uint32_t cacheReadSize(uint64_t _id) BX_OVERRIDE

+ 2 - 2
examples/08-update/update.cpp

@@ -109,7 +109,7 @@ static void updateTextureCubeRectBgra8(bgfx::TextureHandle _handle, uint8_t _sid
 		data += 4;
 	}
 
-	bgfx::updateTextureCube(_handle, _side, 0, _x, _y, _width, _height, mem);
+	bgfx::updateTextureCube(_handle, 0, _side, 0, _x, _y, _width, _height, mem);
 }
 
 static const uint32_t m_textureside   = 512;
@@ -409,7 +409,7 @@ public:
 
 					// Pitch here makes possible to pass data from source to destination
 					// without need for m_textures and allocated memory to be the same size.
-					bgfx::updateTexture2D(m_texture2d, 0, tx, ty, tw, th, mem, pitch);
+					bgfx::updateTexture2D(m_texture2d, 0, 0, tx, ty, tw, th, mem, pitch);
 				}
 			}
 

+ 1 - 1
examples/27-terrain/terrain.cpp

@@ -278,7 +278,7 @@ class ExampleTerrain : public entry::AppI
 			}
 
 			mem = bgfx::makeRef(&m_terrain.m_heightMap[0], sizeof(uint8_t) * s_terrainSize * s_terrainSize);
-			bgfx::updateTexture2D(m_heightTexture, 0, 0, 0, s_terrainSize, s_terrainSize, mem);
+			bgfx::updateTexture2D(m_heightTexture, 0, 0, 0, 0, s_terrainSize, s_terrainSize, mem);
 			break;
 		}
 	}

+ 1 - 1
examples/common/cube_atlas.cpp

@@ -443,7 +443,7 @@ void Atlas::updateRegion(const AtlasRegion& _region, const uint8_t* _bitmapBuffe
 			}
 		}
 
-		bgfx::updateTextureCube(m_textureHandle, (uint8_t)_region.getFaceIndex(), 0, _region.x, _region.y, _region.width, _region.height, mem);
+		bgfx::updateTextureCube(m_textureHandle, 0, (uint8_t)_region.getFaceIndex(), 0, _region.x, _region.y, _region.width, _region.height, mem);
 	}
 }
 

+ 21 - 17
examples/common/nanovg/nanovg_bgfx.cpp

@@ -337,14 +337,16 @@ namespace
 
 		if (NULL != mem)
 		{
-			bgfx::updateTexture2D(tex->id
-					, 0
-					, 0
-					, 0
-					, tex->width
-					, tex->height
-					, mem
-					);
+			bgfx::updateTexture2D(
+				  tex->id
+				, 0
+				, 0
+				, 0
+				, 0
+				, tex->width
+				, tex->height
+				, mem
+				);
 		}
 
 		return bgfx::isValid(tex->id) ? tex->id.idx : 0;
@@ -368,15 +370,17 @@ namespace
 		uint32_t bytesPerPixel = NVG_TEXTURE_RGBA == tex->type ? 4 : 1;
 		uint32_t pitch = tex->width * bytesPerPixel;
 
-		bgfx::updateTexture2D(tex->id
-				, 0
-				, x
-				, y
-				, w
-				, h
-				, bgfx::copy(data + y*pitch + x*bytesPerPixel, h*pitch)
-				, pitch
-				);
+		bgfx::updateTexture2D(
+			  tex->id
+			, 0
+			, 0
+			, x
+			, y
+			, w
+			, h
+			, bgfx::copy(data + y*pitch + x*bytesPerPixel, h*pitch)
+			, pitch
+			);
 
 		return 1;
 	}

+ 4 - 0
include/bgfx/bgfx.h

@@ -1686,6 +1686,7 @@ namespace bgfx
 	/// Update 2D texture.
 	///
 	/// @param[in] _handle Texture handle.
+	/// @param[in] _layer Layers in texture array.
 	/// @param[in] _mip Mip level.
 	/// @param[in] _x X offset in texture.
 	/// @param[in] _y Y offset in texture.
@@ -1699,6 +1700,7 @@ namespace bgfx
 	///
 	void updateTexture2D(
 		  TextureHandle _handle
+		, uint16_t _layer
 		, uint8_t _mip
 		, uint16_t _x
 		, uint16_t _y
@@ -1737,6 +1739,7 @@ namespace bgfx
 	/// Update Cube texture.
 	///
 	/// @param[in] _handle Texture handle.
+	/// @param[in] _layer Layers in texture array.
 	/// @param[in] _side Cubemap side `BGFX_CUBE_MAP_<POSITIVE or NEGATIVE>_<X, Y or Z>`,
 	///   where 0 is +X, 1 is -X, 2 is +Y, 3 is -Y, 4 is +Z, and 5 is -Z.
 	///
@@ -1770,6 +1773,7 @@ namespace bgfx
 	///
 	void updateTextureCube(
 		  TextureHandle _handle
+		, uint16_t _layer
 		, uint8_t _side
 		, uint8_t _mip
 		, uint16_t _x

+ 1 - 1
include/bgfx/bgfxdefines.h

@@ -6,7 +6,7 @@
 #ifndef BGFX_DEFINES_H_HEADER_GUARD
 #define BGFX_DEFINES_H_HEADER_GUARD
 
-#define BGFX_API_VERSION UINT32_C(18)
+#define BGFX_API_VERSION UINT32_C(19)
 
 ///
 #define BGFX_STATE_RGB_WRITE               UINT64_C(0x0000000000000001) //!< Enable RGB write.

+ 2 - 2
include/bgfx/c99/bgfx.h

@@ -674,13 +674,13 @@ BGFX_C_API bgfx_texture_handle_t bgfx_create_texture_3d(uint16_t _width, uint16_
 BGFX_C_API bgfx_texture_handle_t bgfx_create_texture_cube(uint16_t _size, bool _hasMips, uint16_t _numLayers, bgfx_texture_format_t _format, uint32_t _flags, const bgfx_memory_t* _mem);
 
 /**/
-BGFX_C_API void bgfx_update_texture_2d(bgfx_texture_handle_t _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch);
+BGFX_C_API void bgfx_update_texture_2d(bgfx_texture_handle_t _handle, uint16_t _layer, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch);
 
 /**/
 BGFX_C_API void bgfx_update_texture_3d(bgfx_texture_handle_t _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _z, uint16_t _width, uint16_t _height, uint16_t _depth, const bgfx_memory_t* _mem);
 
 /**/
-BGFX_C_API void bgfx_update_texture_cube(bgfx_texture_handle_t _handle, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch);
+BGFX_C_API void bgfx_update_texture_cube(bgfx_texture_handle_t _handle, uint16_t _layer, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch);
 
 /**/
 BGFX_C_API uint32_t bgfx_read_texture(bgfx_texture_handle_t _handle, void* _data);

+ 3 - 2
include/bgfx/c99/bgfxplatform.h

@@ -98,6 +98,7 @@ typedef struct bgfx_interface_vtbl
     void (*set_debug)(uint32_t _debug);
     void (*dbg_text_clear)(uint8_t _attr, bool _small);
     void (*dbg_text_printf)(uint16_t _x, uint16_t _y, uint8_t _attr, const char* _format, ...);
+    void (*dbg_text_vprintf)(uint16_t _x, uint16_t _y, uint8_t _attr, const char* _format, va_list _argList);
     void (*dbg_text_image)(uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const void* _data, uint16_t _pitch);
     bgfx_index_buffer_handle_t (*create_index_buffer)(const bgfx_memory_t* _mem, uint16_t _flags);
     void (*destroy_index_buffer)(bgfx_index_buffer_handle_t _handle);
@@ -133,9 +134,9 @@ typedef struct bgfx_interface_vtbl
     bgfx_texture_handle_t (*create_texture_2d_scaled)(bgfx_backbuffer_ratio_t _ratio, bool _hasMips, uint16_t _numLayers, bgfx_texture_format_t _format, uint32_t _flags);
     bgfx_texture_handle_t (*create_texture_3d)(uint16_t _width, uint16_t _height, uint16_t _depth, bool _hasMips, bgfx_texture_format_t _format, uint32_t _flags, const bgfx_memory_t* _mem);
     bgfx_texture_handle_t (*create_texture_cube)(uint16_t _size, bool _hasMips, uint16_t _numLayers, bgfx_texture_format_t _format, uint32_t _flags, const bgfx_memory_t* _mem);
-    void (*update_texture_2d)(bgfx_texture_handle_t _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch);
+    void (*update_texture_2d)(bgfx_texture_handle_t _handle, uint16_t _layer, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch);
     void (*update_texture_3d)(bgfx_texture_handle_t _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _z, uint16_t _width, uint16_t _height, uint16_t _depth, const bgfx_memory_t* _mem);
-    void (*update_texture_cube)(bgfx_texture_handle_t _handle, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch);
+    void (*update_texture_cube)(bgfx_texture_handle_t _handle, uint16_t _layer, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch);
     void (*destroy_texture)(bgfx_texture_handle_t _handle);
     bgfx_frame_buffer_handle_t (*create_frame_buffer)(uint16_t _width, uint16_t _height, bgfx_texture_format_t _format, uint32_t _textureFlags);
     bgfx_frame_buffer_handle_t (*create_frame_buffer_scaled)(bgfx_backbuffer_ratio_t _ratio, bgfx_texture_format_t _format, uint32_t _textureFlags);

+ 13 - 10
src/bgfx.cpp

@@ -1101,6 +1101,8 @@ namespace bgfx
 		CAPS_FLAGS(BGFX_CAPS_OCCLUSION_QUERY),
 		CAPS_FLAGS(BGFX_CAPS_ALPHA_TO_COVERAGE),
 		CAPS_FLAGS(BGFX_CAPS_CONSERVATIVE_RASTER),
+		CAPS_FLAGS(BGFX_CAPS_TEXTURE_2D_ARRAY),
+		CAPS_FLAGS(BGFX_CAPS_TEXTURE_CUBE_ARRAY),
 #undef CAPS_FLAGS
 	};
 
@@ -2977,7 +2979,7 @@ error:
 		tc.m_width     = _width;
 		tc.m_height    = _height;
 		tc.m_depth     = 0;
-		tc.m_numLayers = 1;
+		tc.m_numLayers = _numLayers;
 		tc.m_numMips   = numMips;
 		tc.m_format    = _format;
 		tc.m_cubeMap   = false;
@@ -3076,7 +3078,7 @@ error:
 		tc.m_width     = _size;
 		tc.m_height    = _size;
 		tc.m_depth     = 0;
-		tc.m_numLayers = 1;
+		tc.m_numLayers = _numLayers;
 		tc.m_numMips   = numMips;
 		tc.m_format    = _format;
 		tc.m_cubeMap   = true;
@@ -3092,7 +3094,7 @@ error:
 		s_ctx->destroyTexture(_handle);
 	}
 
-	void updateTexture2D(TextureHandle _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const Memory* _mem, uint16_t _pitch)
+	void updateTexture2D(TextureHandle _handle, uint16_t _layer, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const Memory* _mem, uint16_t _pitch)
 	{
 		BGFX_CHECK_MAIN_THREAD();
 		BX_CHECK(NULL != _mem, "_mem can't be NULL");
@@ -3103,7 +3105,7 @@ error:
 		}
 		else
 		{
-			s_ctx->updateTexture(_handle, 0, _mip, _x, _y, 0, _width, _height, 1, _pitch, _mem);
+			s_ctx->updateTexture(_handle, 0, _mip, _x, _y, _layer, _width, _height, 1, _pitch, _mem);
 		}
 	}
 
@@ -3125,7 +3127,7 @@ error:
 		}
 	}
 
-	void updateTextureCube(TextureHandle _handle, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const Memory* _mem, uint16_t _pitch)
+	void updateTextureCube(TextureHandle _handle, uint16_t _layer, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const Memory* _mem, uint16_t _pitch)
 	{
 		BGFX_CHECK_MAIN_THREAD();
 		BX_CHECK(NULL != _mem, "_mem can't be NULL");
@@ -3137,7 +3139,7 @@ error:
 		}
 		else
 		{
-			s_ctx->updateTexture(_handle, _side, _mip, _x, _y, 0, _width, _height, 1, _pitch, _mem);
+			s_ctx->updateTexture(_handle, _side, _mip, _x, _y, _layer, _width, _height, 1, _pitch, _mem);
 		}
 	}
 
@@ -4186,10 +4188,10 @@ BGFX_C_API bgfx_texture_handle_t bgfx_create_texture_cube(uint16_t _size, bool _
 	return handle.c;
 }
 
-BGFX_C_API void bgfx_update_texture_2d(bgfx_texture_handle_t _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch)
+BGFX_C_API void bgfx_update_texture_2d(bgfx_texture_handle_t _handle, uint16_t _layer, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch)
 {
 	union { bgfx_texture_handle_t c; bgfx::TextureHandle cpp; } handle = { _handle };
-	bgfx::updateTexture2D(handle.cpp, _mip, _x, _y, _width, _height, (const bgfx::Memory*)_mem, _pitch);
+	bgfx::updateTexture2D(handle.cpp, _layer, _mip, _x, _y, _width, _height, (const bgfx::Memory*)_mem, _pitch);
 }
 
 BGFX_C_API void bgfx_update_texture_3d(bgfx_texture_handle_t _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _z, uint16_t _width, uint16_t _height, uint16_t _depth, const bgfx_memory_t* _mem)
@@ -4198,10 +4200,10 @@ BGFX_C_API void bgfx_update_texture_3d(bgfx_texture_handle_t _handle, uint8_t _m
 	bgfx::updateTexture3D(handle.cpp, _mip, _x, _y, _z, _width, _height, _depth, (const bgfx::Memory*)_mem);
 }
 
-BGFX_C_API void bgfx_update_texture_cube(bgfx_texture_handle_t _handle, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch)
+BGFX_C_API void bgfx_update_texture_cube(bgfx_texture_handle_t _handle, uint16_t _layer, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch)
 {
 	union { bgfx_texture_handle_t c; bgfx::TextureHandle cpp; } handle = { _handle };
-	bgfx::updateTextureCube(handle.cpp, _side, _mip, _x, _y, _width, _height, (const bgfx::Memory*)_mem, _pitch);
+	bgfx::updateTextureCube(handle.cpp, _layer, _side, _mip, _x, _y, _width, _height, (const bgfx::Memory*)_mem, _pitch);
 }
 
 BGFX_C_API uint32_t bgfx_read_texture(bgfx_texture_handle_t _handle, void* _data)
@@ -4650,6 +4652,7 @@ BGFX_C_API bgfx_interface_vtbl_t* bgfx_get_interface(uint32_t _version)
 	BGFX_IMPORT_FUNC(set_debug) \
 	BGFX_IMPORT_FUNC(dbg_text_clear) \
 	BGFX_IMPORT_FUNC(dbg_text_printf) \
+	BGFX_IMPORT_FUNC(dbg_text_vprintf) \
 	BGFX_IMPORT_FUNC(dbg_text_image) \
 	BGFX_IMPORT_FUNC(create_index_buffer) \
 	BGFX_IMPORT_FUNC(destroy_index_buffer) \

+ 14 - 2
src/bgfx_p.h

@@ -3215,7 +3215,19 @@ namespace bgfx
 			}
 		}
 
-		BGFX_API_FUNC(void updateTexture(TextureHandle _handle, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _z, uint16_t _width, uint16_t _height, uint16_t _depth, uint16_t _pitch, const Memory* _mem) )
+		BGFX_API_FUNC(void updateTexture(
+			  TextureHandle _handle
+			, uint8_t _side
+			, uint8_t _mip
+			, uint16_t _x
+			, uint16_t _y
+			, uint16_t _z
+			, uint16_t _width
+			, uint16_t _height
+			, uint16_t _depth
+			, uint16_t _pitch
+			, const Memory* _mem
+		) )
 		{
 			CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::UpdateTexture);
 			cmdbuf.write(_handle);
@@ -3224,7 +3236,7 @@ namespace bgfx
 			Rect rect;
 			rect.m_x = _x;
 			rect.m_y = _y;
-			rect.m_width = _width;
+			rect.m_width  = _width;
 			rect.m_height = _height;
 			cmdbuf.write(rect);
 			cmdbuf.write(_z);

+ 12 - 36
src/bgfx_shader.sh

@@ -380,50 +380,26 @@ vec4  mod(vec4  _a, vec4  _b) { return _a - _b * floor(_a / _b); }
 #	define atan2(_x, _y) atan(_x, _y)
 #	define mul(_a, _b) ( (_a) * (_b) )
 #	define saturate(_x) clamp(_x, 0.0, 1.0)
-#	define SAMPLER2D(_name, _reg) uniform sampler2D _name
-#	define SAMPLER2DMS(_name, _reg) uniform sampler2DMS _name
-#	define SAMPLER3D(_name, _reg) uniform sampler3D _name
-#	define SAMPLERCUBE(_name, _reg) uniform samplerCube _name
+#	define SAMPLER2D(_name, _reg)       uniform sampler2D _name
+#	define SAMPLER2DMS(_name, _reg)     uniform sampler2DMS _name
+#	define SAMPLER3D(_name, _reg)       uniform sampler3D _name
+#	define SAMPLERCUBE(_name, _reg)     uniform samplerCube _name
 #	define SAMPLER2DSHADOW(_name, _reg) uniform sampler2DShadow _name
 
+#	define SAMPLER2DARRAY(_name, _reg)       uniform sampler2DArray _name
+#	define SAMPLER2DMSARRAY(_name, _reg)     uniform sampler2DMSArray _name
+#	define SAMPLERCUBEARRAY(_name, _reg)     uniform samplerCubeArray _name
+#	define SAMPLER2DARRAYSHADOW(_name, _reg) uniform sampler2DArrayShadow _name
+
 #	if BGFX_SHADER_LANGUAGE_GLSL >= 130
 #		define ISAMPLER2D(_name, _reg) uniform isampler2D _name
 #		define USAMPLER2D(_name, _reg) uniform usampler2D _name
 #		define ISAMPLER3D(_name, _reg) uniform isampler3D _name
 #		define USAMPLER3D(_name, _reg) uniform usampler3D _name
 
-vec4 bgfxTexture2D(sampler2D _sampler, vec2 _coord)
-{
-	return texture(_sampler, _coord);
-}
-
-ivec4 bgfxTexture2D(isampler2D _sampler, vec2 _coord)
-{
-	return texture(_sampler, _coord);
-}
-
-uvec4 bgfxTexture2D(usampler2D _sampler, vec2 _coord)
-{
-	return texture(_sampler, _coord);
-}
-
-vec4 bgfxTexture3D(sampler3D _sampler, vec3 _coord)
-{
-	return texture(_sampler, _coord);
-}
-
-ivec4 bgfxTexture3D(isampler3D _sampler, vec3 _coord)
-{
-	return texture(_sampler, _coord);
-}
-
-uvec4 bgfxTexture3D(usampler3D _sampler, vec3 _coord)
-{
-	return texture(_sampler, _coord);
-}
-
-#		define texture2D(_sampler, _coord) bgfxTexture2D(_sampler, _coord)
-#		define texture3D(_sampler, _coord) bgfxTexture3D(_sampler, _coord)
+#		define texture2D(_sampler, _coord)      texture(_sampler, _coord)
+#		define texture2DArray(_sampler, _coord) texture(_sampler, _coord)
+#		define texture3D(_sampler, _coord)      texture(_sampler, _coord)
 #	endif // BGFX_SHADER_LANGUAGE_GLSL >= 130
 
 vec3 instMul(vec3 _vec, mat3 _mtx) { return mul(_vec, _mtx); }

+ 66 - 61
src/image.cpp

@@ -2509,19 +2509,20 @@ namespace bgfx
 		uint32_t size = imageGetSize(_format, _width, _height, 0, false, numMips);
 		const Memory* image = alloc(size);
 
-		_imageContainer.m_data     = image->data;
-		_imageContainer.m_format   = _format;
-		_imageContainer.m_size     = image->size;
-		_imageContainer.m_offset   = 0;
-		_imageContainer.m_width    = _width;
-		_imageContainer.m_height   = _height;
-		_imageContainer.m_depth    = _depth;
-		_imageContainer.m_numMips  = numMips;
-		_imageContainer.m_hasAlpha = false;
-		_imageContainer.m_cubeMap  = _cubeMap;
-		_imageContainer.m_ktx      = false;
-		_imageContainer.m_ktxLE    = false;
-		_imageContainer.m_srgb     = false;
+		_imageContainer.m_data      = image->data;
+		_imageContainer.m_format    = _format;
+		_imageContainer.m_size      = image->size;
+		_imageContainer.m_offset    = 0;
+		_imageContainer.m_width     = _width;
+		_imageContainer.m_height    = _height;
+		_imageContainer.m_depth     = _depth;
+		_imageContainer.m_numLayers = 1;
+		_imageContainer.m_numMips   = numMips;
+		_imageContainer.m_hasAlpha  = false;
+		_imageContainer.m_cubeMap   = _cubeMap;
+		_imageContainer.m_ktx       = false;
+		_imageContainer.m_ktxLE     = false;
+		_imageContainer.m_srgb      = false;
 
 		return image;
 	}
@@ -2872,19 +2873,20 @@ namespace bgfx
 			}
 		}
 
-		_imageContainer.m_data     = NULL;
-		_imageContainer.m_size     = 0;
-		_imageContainer.m_offset   = (uint32_t)bx::seek(_reader);
-		_imageContainer.m_width    = width;
-		_imageContainer.m_height   = height;
-		_imageContainer.m_depth    = depth;
-		_imageContainer.m_format   = format;
-		_imageContainer.m_numMips  = uint8_t( (caps[0] & DDSCAPS_MIPMAP) ? mips : 1);
-		_imageContainer.m_hasAlpha = hasAlpha;
-		_imageContainer.m_cubeMap  = cubeMap;
-		_imageContainer.m_ktx      = false;
-		_imageContainer.m_ktxLE    = false;
-		_imageContainer.m_srgb     = srgb;
+		_imageContainer.m_data      = NULL;
+		_imageContainer.m_size      = 0;
+		_imageContainer.m_offset    = (uint32_t)bx::seek(_reader);
+		_imageContainer.m_width     = width;
+		_imageContainer.m_height    = height;
+		_imageContainer.m_depth     = depth;
+		_imageContainer.m_format    = format;
+		_imageContainer.m_numLayers = 1;
+		_imageContainer.m_numMips   = uint8_t( (caps[0] & DDSCAPS_MIPMAP) ? mips : 1);
+		_imageContainer.m_hasAlpha  = hasAlpha;
+		_imageContainer.m_cubeMap   = cubeMap;
+		_imageContainer.m_ktx       = false;
+		_imageContainer.m_ktxLE     = false;
+		_imageContainer.m_srgb      = srgb;
 
 		return TextureFormat::Unknown != format;
 	}
@@ -3178,19 +3180,20 @@ namespace bgfx
 			}
 		}
 
-		_imageContainer.m_data     = NULL;
-		_imageContainer.m_size     = 0;
-		_imageContainer.m_offset   = (uint32_t)offset;
-		_imageContainer.m_width    = width;
-		_imageContainer.m_height   = height;
-		_imageContainer.m_depth    = depth;
-		_imageContainer.m_format   = format;
-		_imageContainer.m_numMips  = uint8_t(bx::uint32_max(numMips, 1) );
-		_imageContainer.m_hasAlpha = hasAlpha;
-		_imageContainer.m_cubeMap  = numFaces > 1;
-		_imageContainer.m_ktx      = true;
-		_imageContainer.m_ktxLE    = fromLittleEndian;
-		_imageContainer.m_srgb     = false;
+		_imageContainer.m_data      = NULL;
+		_imageContainer.m_size      = 0;
+		_imageContainer.m_offset    = (uint32_t)offset;
+		_imageContainer.m_width     = width;
+		_imageContainer.m_height    = height;
+		_imageContainer.m_depth     = depth;
+		_imageContainer.m_format    = format;
+		_imageContainer.m_numLayers = 1;
+		_imageContainer.m_numMips   = uint8_t(bx::uint32_max(numMips, 1) );
+		_imageContainer.m_hasAlpha  = hasAlpha;
+		_imageContainer.m_cubeMap   = numFaces > 1;
+		_imageContainer.m_ktx       = true;
+		_imageContainer.m_ktxLE     = fromLittleEndian;
+		_imageContainer.m_srgb      = false;
 
 		return TextureFormat::Unknown != format;
 	}
@@ -3327,19 +3330,20 @@ namespace bgfx
 			}
 		}
 
-		_imageContainer.m_data     = NULL;
-		_imageContainer.m_size     = 0;
-		_imageContainer.m_offset   = (uint32_t)offset;
-		_imageContainer.m_width    = width;
-		_imageContainer.m_height   = height;
-		_imageContainer.m_depth    = depth;
-		_imageContainer.m_format   = format;
-		_imageContainer.m_numMips  = uint8_t(bx::uint32_max(numMips, 1) );
-		_imageContainer.m_hasAlpha = hasAlpha;
-		_imageContainer.m_cubeMap  = numFaces > 1;
-		_imageContainer.m_ktx      = false;
-		_imageContainer.m_ktxLE    = false;
-		_imageContainer.m_srgb     = colorSpace > 0;
+		_imageContainer.m_data      = NULL;
+		_imageContainer.m_size      = 0;
+		_imageContainer.m_offset    = (uint32_t)offset;
+		_imageContainer.m_width     = width;
+		_imageContainer.m_height    = height;
+		_imageContainer.m_depth     = depth;
+		_imageContainer.m_format    = format;
+		_imageContainer.m_numLayers = 1;
+		_imageContainer.m_numMips   = uint8_t(bx::uint32_max(numMips, 1) );
+		_imageContainer.m_hasAlpha  = hasAlpha;
+		_imageContainer.m_cubeMap   = numFaces > 1;
+		_imageContainer.m_ktx       = false;
+		_imageContainer.m_ktxLE     = false;
+		_imageContainer.m_srgb      = colorSpace > 0;
 
 		return TextureFormat::Unknown != format;
 	}
@@ -3378,15 +3382,16 @@ namespace bgfx
 				_imageContainer.m_data = tc.m_mem->data;
 				_imageContainer.m_size = tc.m_mem->size;
 			}
-			_imageContainer.m_width    = tc.m_width;
-			_imageContainer.m_height   = tc.m_height;
-			_imageContainer.m_depth    = tc.m_depth;
-			_imageContainer.m_numMips  = tc.m_numMips;
-			_imageContainer.m_hasAlpha = false;
-			_imageContainer.m_cubeMap  = tc.m_cubeMap;
-			_imageContainer.m_ktx      = false;
-			_imageContainer.m_ktxLE    = false;
-			_imageContainer.m_srgb     = false;
+			_imageContainer.m_width     = tc.m_width;
+			_imageContainer.m_height    = tc.m_height;
+			_imageContainer.m_depth     = tc.m_depth;
+			_imageContainer.m_numLayers = tc.m_numLayers;
+			_imageContainer.m_numMips   = tc.m_numMips;
+			_imageContainer.m_hasAlpha  = false;
+			_imageContainer.m_cubeMap   = tc.m_cubeMap;
+			_imageContainer.m_ktx       = false;
+			_imageContainer.m_ktxLE     = false;
+			_imageContainer.m_srgb      = false;
 
 			return true;
 		}

+ 1 - 0
src/image.h

@@ -19,6 +19,7 @@ namespace bgfx
 		uint32_t m_width;
 		uint32_t m_height;
 		uint32_t m_depth;
+		uint16_t m_numLayers;
 		uint8_t  m_numMips;
 		bool     m_hasAlpha;
 		bool     m_cubeMap;

+ 453 - 223
src/renderer_gl.cpp

@@ -500,6 +500,7 @@ namespace bgfx { namespace gl
 			ARB_shader_texture_lod,
 			ARB_texture_compression_bptc,
 			ARB_texture_compression_rgtc,
+			ARB_texture_cube_map_array,
 			ARB_texture_float,
 			ARB_texture_multisample,
 			ARB_texture_rg,
@@ -555,6 +556,7 @@ namespace bgfx { namespace gl
 			EXT_texture_compression_latc,
 			EXT_texture_compression_rgtc,
 			EXT_texture_compression_s3tc,
+			EXT_texture_cube_map_array,
 			EXT_texture_filter_anisotropic,
 			EXT_texture_format_BGRA8888,
 			EXT_texture_rg,
@@ -614,6 +616,7 @@ namespace bgfx { namespace gl
 			OES_texture_half_float,
 			OES_texture_half_float_linear,
 			OES_texture_stencil8,
+			OES_texture_storage_multisample_2d_array,
 			OES_vertex_array_object,
 			OES_vertex_half_float,
 			OES_vertex_type_10_10_10_2,
@@ -659,185 +662,188 @@ namespace bgfx { namespace gl
 	//
 	static Extension s_extension[] =
 	{
-		{ "AMD_conservative_depth",                false,                             true  },
-		{ "AMD_multi_draw_indirect",               false,                             true  },
-
-		{ "ANGLE_depth_texture",                   false,                             true  },
-		{ "ANGLE_framebuffer_blit",                false,                             true  },
-		{ "ANGLE_framebuffer_multisample",         false,                             false },
-		{ "ANGLE_instanced_arrays",                false,                             true  },
-		{ "ANGLE_texture_compression_dxt1",        false,                             true  },
-		{ "ANGLE_texture_compression_dxt3",        false,                             true  },
-		{ "ANGLE_texture_compression_dxt5",        false,                             true  },
-		{ "ANGLE_timer_query",                     false,                             true  },
-		{ "ANGLE_translated_shader_source",        false,                             true  },
-
-		{ "APPLE_texture_format_BGRA8888",         false,                             true  },
-		{ "APPLE_texture_max_level",               false,                             true  },
-
-		{ "ARB_clip_control",                      BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
-		{ "ARB_compute_shader",                    BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
-		{ "ARB_conservative_depth",                BGFX_CONFIG_RENDERER_OPENGL >= 42, true  },
-		{ "ARB_copy_image",                        BGFX_CONFIG_RENDERER_OPENGL >= 42, true  },
-		{ "ARB_debug_label",                       false,                             true  },
-		{ "ARB_debug_output",                      BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
-		{ "ARB_depth_buffer_float",                BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
-		{ "ARB_depth_clamp",                       BGFX_CONFIG_RENDERER_OPENGL >= 32, true  },
-		{ "ARB_draw_buffers_blend",                BGFX_CONFIG_RENDERER_OPENGL >= 40, true  },
-		{ "ARB_draw_indirect",                     BGFX_CONFIG_RENDERER_OPENGL >= 40, true  },
-		{ "ARB_draw_instanced",                    BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
-		{ "ARB_ES3_compatibility",                 BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
-		{ "ARB_framebuffer_object",                BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "ARB_framebuffer_sRGB",                  BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "ARB_get_program_binary",                BGFX_CONFIG_RENDERER_OPENGL >= 41, true  },
-		{ "ARB_half_float_pixel",                  BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "ARB_half_float_vertex",                 BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "ARB_instanced_arrays",                  BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
-		{ "ARB_internalformat_query",              BGFX_CONFIG_RENDERER_OPENGL >= 42, true  },
-		{ "ARB_internalformat_query2",             BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
-		{ "ARB_invalidate_subdata",                BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
-		{ "ARB_map_buffer_range",                  BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "ARB_multi_draw_indirect",               BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
-		{ "ARB_multisample",                       false,                             true  },
-		{ "ARB_occlusion_query",                   BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
-		{ "ARB_occlusion_query2",                  BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
-		{ "ARB_program_interface_query",           BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
-		{ "ARB_sampler_objects",                   BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
-		{ "ARB_seamless_cube_map",                 BGFX_CONFIG_RENDERER_OPENGL >= 32, true  },
-		{ "ARB_shader_bit_encoding",               BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
-		{ "ARB_shader_image_load_store",           BGFX_CONFIG_RENDERER_OPENGL >= 42, true  },
-		{ "ARB_shader_storage_buffer_object",      BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
-		{ "ARB_shader_texture_lod",                BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "ARB_texture_compression_bptc",          BGFX_CONFIG_RENDERER_OPENGL >= 44, true  },
-		{ "ARB_texture_compression_rgtc",          BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "ARB_texture_float",                     BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "ARB_texture_multisample",               BGFX_CONFIG_RENDERER_OPENGL >= 32, true  },
-		{ "ARB_texture_rg",                        BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "ARB_texture_rgb10_a2ui",                BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
-		{ "ARB_texture_stencil8",                  false,                             true  },
-		{ "ARB_texture_storage",                   BGFX_CONFIG_RENDERER_OPENGL >= 42, true  },
-		{ "ARB_texture_swizzle",                   BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
-		{ "ARB_timer_query",                       BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
-		{ "ARB_uniform_buffer_object",             BGFX_CONFIG_RENDERER_OPENGL >= 31, true  },
-		{ "ARB_vertex_array_object",               BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "ARB_vertex_type_2_10_10_10_rev",        false,                             true  },
-
-		{ "ATI_meminfo",                           false,                             true  },
-
-		{ "CHROMIUM_color_buffer_float_rgb",       false,                             true  },
-		{ "CHROMIUM_color_buffer_float_rgba",      false,                             true  },
-		{ "CHROMIUM_depth_texture",                false,                             true  },
-		{ "CHROMIUM_framebuffer_multisample",      false,                             true  },
-		{ "CHROMIUM_texture_compression_dxt3",     false,                             true  },
-		{ "CHROMIUM_texture_compression_dxt5",     false,                             true  },
-
-		{ "EXT_bgra",                              false,                             true  },
-		{ "EXT_blend_color",                       BGFX_CONFIG_RENDERER_OPENGL >= 31, true  },
-		{ "EXT_blend_minmax",                      BGFX_CONFIG_RENDERER_OPENGL >= 14, true  },
-		{ "EXT_blend_subtract",                    BGFX_CONFIG_RENDERER_OPENGL >= 14, true  },
-		{ "EXT_color_buffer_half_float",           false,                             true  }, // GLES2 extension.
-		{ "EXT_color_buffer_float",                false,                             true  }, // GLES2 extension.
-		{ "EXT_copy_image",                        false,                             true  }, // GLES2 extension.
-		{ "EXT_compressed_ETC1_RGB8_sub_texture",  false,                             true  }, // GLES2 extension.
-		{ "EXT_debug_label",                       false,                             true  },
-		{ "EXT_debug_marker",                      false,                             true  },
-		{ "EXT_debug_tool",                        false,                             true  }, // RenderDoc extension.
-		{ "EXT_discard_framebuffer",               false,                             true  }, // GLES2 extension.
-		{ "EXT_disjoint_timer_query",              false,                             true  }, // GLES2 extension.
-		{ "EXT_draw_buffers",                      false,                             true  }, // GLES2 extension.
-		{ "EXT_draw_instanced",                    false,                             true  }, // GLES2 extension.
-		{ "EXT_instanced_arrays",                  false,                             true  }, // GLES2 extension.
-		{ "EXT_frag_depth",                        false,                             true  }, // GLES2 extension.
-		{ "EXT_framebuffer_blit",                  BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "EXT_framebuffer_object",                BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "EXT_framebuffer_sRGB",                  BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "EXT_gpu_shader4",                       false,                             true  },
-		{ "EXT_multi_draw_indirect",               false,                             true  }, // GLES3.1 extension.
-		{ "EXT_occlusion_query_boolean",           false,                             true  }, // GLES2 extension.
-		{ "EXT_packed_float",                      BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
-		{ "EXT_read_format_bgra",                  false,                             true  },
-		{ "EXT_shader_image_load_store",           false,                             true  },
-		{ "EXT_shader_texture_lod",                false,                             true  }, // GLES2 extension.
-		{ "EXT_shadow_samplers",                   false,                             true  },
-		{ "EXT_sRGB_write_control",                false,                             true  }, // GLES2 extension.
-		{ "EXT_texture_array",                     BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "EXT_texture_compression_dxt1",          false,                             true  },
-		{ "EXT_texture_compression_latc",          false,                             true  },
-		{ "EXT_texture_compression_rgtc",          BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "EXT_texture_compression_s3tc",          false,                             true  },
-		{ "EXT_texture_filter_anisotropic",        false,                             true  },
-		{ "EXT_texture_format_BGRA8888",           false,                             true  },
-		{ "EXT_texture_rg",                        false,                             true  }, // GLES2 extension.
-		{ "EXT_texture_shared_exponent",           false,                             true  },
-		{ "EXT_texture_snorm",                     BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
-		{ "EXT_texture_sRGB",                      false,                             true  },
-		{ "EXT_texture_storage",                   false,                             true  },
-		{ "EXT_texture_swizzle",                   false,                             true  },
-		{ "EXT_texture_type_2_10_10_10_REV",       false,                             true  },
-		{ "EXT_timer_query",                       BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
-		{ "EXT_unpack_subimage",                   false,                             true  },
-
-		{ "GOOGLE_depth_texture",                  false,                             true  },
-
-		{ "GREMEDY_string_marker",                 false,                             true  },
-		{ "GREMEDY_frame_terminator",              false,                             true  },
-
-		{ "IMG_multisampled_render_to_texture",    false,                             true  },
-		{ "IMG_read_format",                       false,                             true  },
-		{ "IMG_shader_binary",                     false,                             true  },
-		{ "IMG_texture_compression_pvrtc",         false,                             true  },
-		{ "IMG_texture_compression_pvrtc2",        false,                             true  },
-		{ "IMG_texture_format_BGRA8888",           false,                             true  },
-
-		{ "INTEL_fragment_shader_ordering",        false,                             true  },
-
-		{ "KHR_debug",                             BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
-		{ "KHR_no_error",                          false,                             true  },
-
-		{ "MOZ_WEBGL_compressed_texture_s3tc",     false,                             true  },
-		{ "MOZ_WEBGL_depth_texture",               false,                             true  },
-
-		{ "NV_conservative_raster",                false,                             true  },
-		{ "NV_copy_image",                         false,                             true  },
-		{ "NV_draw_buffers",                       false,                             true  }, // GLES2 extension.
-		{ "NV_occlusion_query",                    false,                             true  },
-		{ "NV_texture_border_clamp",               false,                             true  }, // GLES2 extension.
-		{ "NVX_gpu_memory_info",                   false,                             true  },
-
-		{ "OES_copy_image",                        false,                             true  },
-		{ "OES_compressed_ETC1_RGB8_texture",      false,                             true  },
-		{ "OES_depth24",                           false,                             true  },
-		{ "OES_depth32",                           false,                             true  },
-		{ "OES_depth_texture",                     false,                             true  },
-		{ "OES_element_index_uint",                false,                             true  },
-		{ "OES_fragment_precision_high",           false,                             true  },
-		{ "OES_get_program_binary",                false,                             true  },
-		{ "OES_required_internalformat",           false,                             true  },
-		{ "OES_packed_depth_stencil",              false,                             true  },
-		{ "OES_read_format",                       false,                             true  },
-		{ "OES_rgb8_rgba8",                        false,                             true  },
-		{ "OES_standard_derivatives",              false,                             true  },
-		{ "OES_texture_3D",                        false,                             true  },
-		{ "OES_texture_float",                     false,                             true  },
-		{ "OES_texture_float_linear",              false,                             true  },
-		{ "OES_texture_npot",                      false,                             true  },
-		{ "OES_texture_half_float",                false,                             true  },
-		{ "OES_texture_half_float_linear",         false,                             true  },
-		{ "OES_texture_stencil8",                  false,                             true  },
-		{ "OES_vertex_array_object",               false,                             !BX_PLATFORM_IOS },
-		{ "OES_vertex_half_float",                 false,                             true  },
-		{ "OES_vertex_type_10_10_10_2",            false,                             true  },
-
-		{ "WEBGL_color_buffer_float",              false,                             true  },
-		{ "WEBGL_compressed_texture_etc1",         false,                             true  },
-		{ "WEBGL_compressed_texture_s3tc",         false,                             true  },
-		{ "WEBGL_compressed_texture_pvrtc",        false,                             true  },
-		{ "WEBGL_depth_texture",                   false,                             true  },
-		{ "WEBGL_draw_buffers",                    false,                             true  },
-
-		{ "WEBKIT_EXT_texture_filter_anisotropic", false,                             true  },
-		{ "WEBKIT_WEBGL_compressed_texture_s3tc",  false,                             true  },
-		{ "WEBKIT_WEBGL_depth_texture",            false,                             true  },
+		{ "AMD_conservative_depth",                   false,                             true  },
+		{ "AMD_multi_draw_indirect",                  false,                             true  },
+
+		{ "ANGLE_depth_texture",                      false,                             true  },
+		{ "ANGLE_framebuffer_blit",                   false,                             true  },
+		{ "ANGLE_framebuffer_multisample",            false,                             false },
+		{ "ANGLE_instanced_arrays",                   false,                             true  },
+		{ "ANGLE_texture_compression_dxt1",           false,                             true  },
+		{ "ANGLE_texture_compression_dxt3",           false,                             true  },
+		{ "ANGLE_texture_compression_dxt5",           false,                             true  },
+		{ "ANGLE_timer_query",                        false,                             true  },
+		{ "ANGLE_translated_shader_source",           false,                             true  },
+
+		{ "APPLE_texture_format_BGRA8888",            false,                             true  },
+		{ "APPLE_texture_max_level",                  false,                             true  },
+
+		{ "ARB_clip_control",                         BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
+		{ "ARB_compute_shader",                       BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
+		{ "ARB_conservative_depth",                   BGFX_CONFIG_RENDERER_OPENGL >= 42, true  },
+		{ "ARB_copy_image",                           BGFX_CONFIG_RENDERER_OPENGL >= 42, true  },
+		{ "ARB_debug_label",                          false,                             true  },
+		{ "ARB_debug_output",                         BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
+		{ "ARB_depth_buffer_float",                   BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
+		{ "ARB_depth_clamp",                          BGFX_CONFIG_RENDERER_OPENGL >= 32, true  },
+		{ "ARB_draw_buffers_blend",                   BGFX_CONFIG_RENDERER_OPENGL >= 40, true  },
+		{ "ARB_draw_indirect",                        BGFX_CONFIG_RENDERER_OPENGL >= 40, true  },
+		{ "ARB_draw_instanced",                       BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
+		{ "ARB_ES3_compatibility",                    BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
+		{ "ARB_framebuffer_object",                   BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "ARB_framebuffer_sRGB",                     BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "ARB_get_program_binary",                   BGFX_CONFIG_RENDERER_OPENGL >= 41, true  },
+		{ "ARB_half_float_pixel",                     BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "ARB_half_float_vertex",                    BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "ARB_instanced_arrays",                     BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
+		{ "ARB_internalformat_query",                 BGFX_CONFIG_RENDERER_OPENGL >= 42, true  },
+		{ "ARB_internalformat_query2",                BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
+		{ "ARB_invalidate_subdata",                   BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
+		{ "ARB_map_buffer_range",                     BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "ARB_multi_draw_indirect",                  BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
+		{ "ARB_multisample",                          false,                             true  },
+		{ "ARB_occlusion_query",                      BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
+		{ "ARB_occlusion_query2",                     BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
+		{ "ARB_program_interface_query",              BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
+		{ "ARB_sampler_objects",                      BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
+		{ "ARB_seamless_cube_map",                    BGFX_CONFIG_RENDERER_OPENGL >= 32, true  },
+		{ "ARB_shader_bit_encoding",                  BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
+		{ "ARB_shader_image_load_store",              BGFX_CONFIG_RENDERER_OPENGL >= 42, true  },
+		{ "ARB_shader_storage_buffer_object",         BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
+		{ "ARB_shader_texture_lod",                   BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "ARB_texture_compression_bptc",             BGFX_CONFIG_RENDERER_OPENGL >= 44, true  },
+		{ "ARB_texture_compression_rgtc",             BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "ARB_texture_cube_map_array",               BGFX_CONFIG_RENDERER_OPENGL >= 40, true  },
+		{ "ARB_texture_float",                        BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "ARB_texture_multisample",                  BGFX_CONFIG_RENDERER_OPENGL >= 32, true  },
+		{ "ARB_texture_rg",                           BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "ARB_texture_rgb10_a2ui",                   BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
+		{ "ARB_texture_stencil8",                     false,                             true  },
+		{ "ARB_texture_storage",                      BGFX_CONFIG_RENDERER_OPENGL >= 42, true  },
+		{ "ARB_texture_swizzle",                      BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
+		{ "ARB_timer_query",                          BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
+		{ "ARB_uniform_buffer_object",                BGFX_CONFIG_RENDERER_OPENGL >= 31, true  },
+		{ "ARB_vertex_array_object",                  BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "ARB_vertex_type_2_10_10_10_rev",           false,                             true  },
+
+		{ "ATI_meminfo",                              false,                             true  },
+
+		{ "CHROMIUM_color_buffer_float_rgb",          false,                             true  },
+		{ "CHROMIUM_color_buffer_float_rgba",         false,                             true  },
+		{ "CHROMIUM_depth_texture",                   false,                             true  },
+		{ "CHROMIUM_framebuffer_multisample",         false,                             true  },
+		{ "CHROMIUM_texture_compression_dxt3",        false,                             true  },
+		{ "CHROMIUM_texture_compression_dxt5",        false,                             true  },
+
+		{ "EXT_bgra",                                 false,                             true  },
+		{ "EXT_blend_color",                          BGFX_CONFIG_RENDERER_OPENGL >= 31, true  },
+		{ "EXT_blend_minmax",                         BGFX_CONFIG_RENDERER_OPENGL >= 14, true  },
+		{ "EXT_blend_subtract",                       BGFX_CONFIG_RENDERER_OPENGL >= 14, true  },
+		{ "EXT_color_buffer_half_float",              false,                             true  }, // GLES2 extension.
+		{ "EXT_color_buffer_float",                   false,                             true  }, // GLES2 extension.
+		{ "EXT_copy_image",                           false,                             true  }, // GLES2 extension.
+		{ "EXT_compressed_ETC1_RGB8_sub_texture",     false,                             true  }, // GLES2 extension.
+		{ "EXT_debug_label",                          false,                             true  },
+		{ "EXT_debug_marker",                         false,                             true  },
+		{ "EXT_debug_tool",                           false,                             true  }, // RenderDoc extension.
+		{ "EXT_discard_framebuffer",                  false,                             true  }, // GLES2 extension.
+		{ "EXT_disjoint_timer_query",                 false,                             true  }, // GLES2 extension.
+		{ "EXT_draw_buffers",                         false,                             true  }, // GLES2 extension.
+		{ "EXT_draw_instanced",                       false,                             true  }, // GLES2 extension.
+		{ "EXT_instanced_arrays",                     false,                             true  }, // GLES2 extension.
+		{ "EXT_frag_depth",                           false,                             true  }, // GLES2 extension.
+		{ "EXT_framebuffer_blit",                     BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "EXT_framebuffer_object",                   BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "EXT_framebuffer_sRGB",                     BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "EXT_gpu_shader4",                          false,                             true  },
+		{ "EXT_multi_draw_indirect",                  false,                             true  }, // GLES3.1 extension.
+		{ "EXT_occlusion_query_boolean",              false,                             true  }, // GLES2 extension.
+		{ "EXT_packed_float",                         BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
+		{ "EXT_read_format_bgra",                     false,                             true  },
+		{ "EXT_shader_image_load_store",              false,                             true  },
+		{ "EXT_shader_texture_lod",                   false,                             true  }, // GLES2 extension.
+		{ "EXT_shadow_samplers",                      false,                             true  },
+		{ "EXT_sRGB_write_control",                   false,                             true  }, // GLES2 extension.
+		{ "EXT_texture_array",                        BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "EXT_texture_compression_dxt1",             false,                             true  },
+		{ "EXT_texture_compression_latc",             false,                             true  },
+		{ "EXT_texture_compression_rgtc",             BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "EXT_texture_compression_s3tc",             false,                             true  },
+		{ "EXT_texture_cube_map_array",               false,                             true  }, // GLES3.1 extension.
+		{ "EXT_texture_filter_anisotropic",           false,                             true  },
+		{ "EXT_texture_format_BGRA8888",              false,                             true  },
+		{ "EXT_texture_rg",                           false,                             true  }, // GLES2 extension.
+		{ "EXT_texture_shared_exponent",              false,                             true  },
+		{ "EXT_texture_snorm",                        BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "EXT_texture_sRGB",                         false,                             true  },
+		{ "EXT_texture_storage",                      false,                             true  },
+		{ "EXT_texture_swizzle",                      false,                             true  },
+		{ "EXT_texture_type_2_10_10_10_REV",          false,                             true  },
+		{ "EXT_timer_query",                          BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
+		{ "EXT_unpack_subimage",                      false,                             true  },
+
+		{ "GOOGLE_depth_texture",                     false,                             true  },
+
+		{ "GREMEDY_string_marker",                    false,                             true  },
+		{ "GREMEDY_frame_terminator",                 false,                             true  },
+
+		{ "IMG_multisampled_render_to_texture",       false,                             true  },
+		{ "IMG_read_format",                          false,                             true  },
+		{ "IMG_shader_binary",                        false,                             true  },
+		{ "IMG_texture_compression_pvrtc",            false,                             true  },
+		{ "IMG_texture_compression_pvrtc2",           false,                             true  },
+		{ "IMG_texture_format_BGRA8888",              false,                             true  },
+
+		{ "INTEL_fragment_shader_ordering",           false,                             true  },
+
+		{ "KHR_debug",                                BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
+		{ "KHR_no_error",                             false,                             true  },
+
+		{ "MOZ_WEBGL_compressed_texture_s3tc",        false,                             true  },
+		{ "MOZ_WEBGL_depth_texture",                  false,                             true  },
+
+		{ "NV_conservative_raster",                   false,                             true  },
+		{ "NV_copy_image",                            false,                             true  },
+		{ "NV_draw_buffers",                          false,                             true  }, // GLES2 extension.
+		{ "NV_occlusion_query",                       false,                             true  },
+		{ "NV_texture_border_clamp",                  false,                             true  }, // GLES2 extension.
+		{ "NVX_gpu_memory_info",                      false,                             true  },
+
+		{ "OES_copy_image",                           false,                             true  },
+		{ "OES_compressed_ETC1_RGB8_texture",         false,                             true  },
+		{ "OES_depth24",                              false,                             true  },
+		{ "OES_depth32",                              false,                             true  },
+		{ "OES_depth_texture",                        false,                             true  },
+		{ "OES_element_index_uint",                   false,                             true  },
+		{ "OES_fragment_precision_high",              false,                             true  },
+		{ "OES_get_program_binary",                   false,                             true  },
+		{ "OES_required_internalformat",              false,                             true  },
+		{ "OES_packed_depth_stencil",                 false,                             true  },
+		{ "OES_read_format",                          false,                             true  },
+		{ "OES_rgb8_rgba8",                           false,                             true  },
+		{ "OES_standard_derivatives",                 false,                             true  },
+		{ "OES_texture_3D",                           false,                             true  },
+		{ "OES_texture_float",                        false,                             true  },
+		{ "OES_texture_float_linear",                 false,                             true  },
+		{ "OES_texture_npot",                         false,                             true  },
+		{ "OES_texture_half_float",                   false,                             true  },
+		{ "OES_texture_half_float_linear",            false,                             true  },
+		{ "OES_texture_stencil8",                     false,                             true  },
+		{ "OES_texture_storage_multisample_2d_array", false,                             true  },
+		{ "OES_vertex_array_object",                  false,                             !BX_PLATFORM_IOS },
+		{ "OES_vertex_half_float",                    false,                             true  },
+		{ "OES_vertex_type_10_10_10_2",               false,                             true  },
+
+		{ "WEBGL_color_buffer_float",                 false,                             true  },
+		{ "WEBGL_compressed_texture_etc1",            false,                             true  },
+		{ "WEBGL_compressed_texture_s3tc",            false,                             true  },
+		{ "WEBGL_compressed_texture_pvrtc",           false,                             true  },
+		{ "WEBGL_depth_texture",                      false,                             true  },
+		{ "WEBGL_draw_buffers",                       false,                             true  },
+
+		{ "WEBKIT_EXT_texture_filter_anisotropic",    false,                             true  },
+		{ "WEBKIT_WEBGL_compressed_texture_s3tc",     false,                             true  },
+		{ "WEBKIT_WEBGL_depth_texture",               false,                             true  },
 	};
 	BX_STATIC_ASSERT(Extension::Count == BX_COUNTOF(s_extension) );
 
@@ -910,6 +916,15 @@ namespace bgfx { namespace gl
 		NULL
 	};
 
+	static const char* s_textureArray[] =
+	{
+		"sampler2DArray",
+		"sampler2DMSArray",
+		"samplerCubeArray",
+		"sampler2DArrayShadow",
+		NULL
+	};
+
 	static const char* s_ARB_texture_multisample[] =
 	{
 		"sampler2DMS",
@@ -1863,6 +1878,21 @@ namespace bgfx { namespace gl
 				: 0
 				;
 
+			g_caps.supported |= false
+				|| s_extension[Extension::EXT_texture_array].m_supported
+				|| s_extension[Extension::EXT_gpu_shader4].m_supported
+				|| !!(BGFX_CONFIG_RENDERER_OPENGLES >= 30)
+				? BGFX_CAPS_TEXTURE_2D_ARRAY
+				: 0
+				;
+
+			g_caps.supported |= false
+				|| s_extension[Extension::ARB_texture_cube_map_array].m_supported
+				|| s_extension[Extension::EXT_texture_cube_map_array].m_supported
+				? BGFX_CAPS_TEXTURE_CUBE_ARRAY
+				: 0
+				;
+
 			g_caps.maxTextureSize = uint16_t(glGet(GL_MAX_TEXTURE_SIZE) );
 
 			if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL)
@@ -3621,8 +3651,19 @@ namespace bgfx { namespace gl
 			GLSL_TYPE(GL_FLOAT_MAT4);
 
 			GLSL_TYPE(GL_SAMPLER_2D);
+			GLSL_TYPE(GL_SAMPLER_2D_ARRAY);
+			GLSL_TYPE(GL_SAMPLER_2D_MULTISAMPLE);
+
 			GLSL_TYPE(GL_INT_SAMPLER_2D);
+			GLSL_TYPE(GL_INT_SAMPLER_2D_ARRAY);
+			GLSL_TYPE(GL_INT_SAMPLER_2D_MULTISAMPLE);
+
 			GLSL_TYPE(GL_UNSIGNED_INT_SAMPLER_2D);
+			GLSL_TYPE(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY);
+			GLSL_TYPE(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE);
+
+			GLSL_TYPE(GL_SAMPLER_2D_SHADOW);
+			GLSL_TYPE(GL_SAMPLER_2D_ARRAY_SHADOW);
 
 			GLSL_TYPE(GL_SAMPLER_3D);
 			GLSL_TYPE(GL_INT_SAMPLER_3D);
@@ -3632,12 +3673,6 @@ namespace bgfx { namespace gl
 			GLSL_TYPE(GL_INT_SAMPLER_CUBE);
 			GLSL_TYPE(GL_UNSIGNED_INT_SAMPLER_CUBE);
 
-			GLSL_TYPE(GL_SAMPLER_2D_MULTISAMPLE);
-			GLSL_TYPE(GL_INT_SAMPLER_2D_MULTISAMPLE);
-			GLSL_TYPE(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE);
-
-			GLSL_TYPE(GL_SAMPLER_2D_SHADOW);
-
 			GLSL_TYPE(GL_IMAGE_1D);
 			GLSL_TYPE(GL_INT_IMAGE_1D);
 			GLSL_TYPE(GL_UNSIGNED_INT_IMAGE_1D);
@@ -3713,8 +3748,19 @@ namespace bgfx { namespace gl
 			return UniformType::Mat4;
 
 		case GL_SAMPLER_2D:
+		case GL_SAMPLER_2D_ARRAY:
+		case GL_SAMPLER_2D_MULTISAMPLE:
+
 		case GL_INT_SAMPLER_2D:
+		case GL_INT_SAMPLER_2D_ARRAY:
+		case GL_INT_SAMPLER_2D_MULTISAMPLE:
+
 		case GL_UNSIGNED_INT_SAMPLER_2D:
+		case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+		case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+
+		case GL_SAMPLER_2D_SHADOW:
+		case GL_SAMPLER_2D_ARRAY_SHADOW:
 
 		case GL_SAMPLER_3D:
 		case GL_INT_SAMPLER_3D:
@@ -3724,12 +3770,6 @@ namespace bgfx { namespace gl
 		case GL_INT_SAMPLER_CUBE:
 		case GL_UNSIGNED_INT_SAMPLER_CUBE:
 
-		case GL_SAMPLER_2D_SHADOW:
-
-		case GL_SAMPLER_2D_MULTISAMPLE:
-		case GL_INT_SAMPLER_2D_MULTISAMPLE:
-		case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
-
 		case GL_IMAGE_1D:
 		case GL_INT_IMAGE_1D:
 		case GL_UNSIGNED_INT_IMAGE_1D:
@@ -3968,8 +4008,19 @@ namespace bgfx { namespace gl
 			switch (gltype)
 			{
 			case GL_SAMPLER_2D:
+			case GL_SAMPLER_2D_ARRAY:
+			case GL_SAMPLER_2D_MULTISAMPLE:
+
 			case GL_INT_SAMPLER_2D:
+			case GL_INT_SAMPLER_2D_ARRAY:
+			case GL_INT_SAMPLER_2D_MULTISAMPLE:
+
 			case GL_UNSIGNED_INT_SAMPLER_2D:
+			case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+			case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+
+			case GL_SAMPLER_2D_SHADOW:
+			case GL_SAMPLER_2D_ARRAY_SHADOW:
 
 			case GL_SAMPLER_3D:
 			case GL_INT_SAMPLER_3D:
@@ -3979,8 +4030,6 @@ namespace bgfx { namespace gl
 			case GL_INT_SAMPLER_CUBE:
 			case GL_UNSIGNED_INT_SAMPLER_CUBE:
 
-			case GL_SAMPLER_2D_SHADOW:
-
 			case GL_IMAGE_1D:
 			case GL_INT_IMAGE_1D:
 			case GL_UNSIGNED_INT_IMAGE_1D:
@@ -4211,60 +4260,214 @@ namespace bgfx { namespace gl
 		m_vcref.invalidate(s_renderGL->m_vaoStateCache);
 	}
 
-	static void texImage(GLenum _target, uint32_t _msaaQuality, GLint _level, GLint _internalFormat, GLsizei _width, GLsizei _height, GLsizei _depth, GLint _border, GLenum _format, GLenum _type, const GLvoid* _data)
+	static void texImage(
+		  GLenum _target
+		, uint32_t _msaaQuality
+		, GLint _level
+		, GLint _internalFormat
+		, GLsizei _width
+		, GLsizei _height
+		, GLsizei _depth
+		, GLint _border
+		, GLenum _format
+		, GLenum _type
+		, const GLvoid* _data
+	)
 	{
-		if (_target == GL_TEXTURE_3D)
+		if (_target == GL_TEXTURE_3D
+		||  _target == GL_TEXTURE_2D_ARRAY
+		||  _target == GL_TEXTURE_CUBE_MAP_ARRAY)
+		{
+			GL_CHECK(glTexImage3D(
+				  _target
+				, _level
+				, _internalFormat
+				, _width
+				, _height
+				, _depth
+				, _border
+				, _format
+				, _type
+				, _data
+				) );
+		}
+		else if (_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
 		{
-			GL_CHECK(glTexImage3D(_target, _level, _internalFormat, _width, _height, _depth, _border, _format, _type, _data) );
 		}
 		else if (_target == GL_TEXTURE_2D_MULTISAMPLE)
 		{
-			GL_CHECK(glTexImage2DMultisample(_target, _msaaQuality, _internalFormat, _width, _height, false) );
+			GL_CHECK(glTexImage2DMultisample(
+				  _target
+				, _msaaQuality
+				, _internalFormat
+				, _width
+				, _height
+				, false
+				) );
 		}
 		else
 		{
-			GL_CHECK(glTexImage2D(_target, _level, _internalFormat, _width, _height, _border, _format, _type, _data) );
+			GL_CHECK(glTexImage2D(
+				  _target
+				, _level
+				, _internalFormat
+				, _width
+				, _height
+				, _border
+				, _format
+				, _type
+				, _data
+				) );
 		}
 
 		BX_UNUSED(_msaaQuality, _depth, _border, _data);
 	}
 
-	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)
+	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 (_target == GL_TEXTURE_3D)
+		if (_target == GL_TEXTURE_3D
+		||  _target == GL_TEXTURE_2D_ARRAY
+		||  _target == GL_TEXTURE_CUBE_MAP_ARRAY)
+		{
+BX_TRACE("zoffset %d, depth %d", _zoffset, _depth);
+
+			GL_CHECK(glTexSubImage3D(
+				  _target
+				, _level
+				, _xoffset
+				, _yoffset
+				, _zoffset
+				, _width
+				, _height
+				, _depth
+				, _format
+				, _type
+				, _data
+				) );
+		}
+		else if (_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
 		{
-			GL_CHECK(glTexSubImage3D(_target, _level, _xoffset, _yoffset, _zoffset, _width, _height, _depth, _format, _type, _data) );
 		}
 		else
 		{
 			BX_UNUSED(_zoffset, _depth);
-			GL_CHECK(glTexSubImage2D(_target, _level, _xoffset, _yoffset, _width, _height, _format, _type, _data) );
+			GL_CHECK(glTexSubImage2D(
+				  _target
+				, _level
+				, _xoffset
+				, _yoffset
+				, _width
+				, _height
+				, _format
+				, _type
+				, _data
+				) );
 		}
 	}
 
-	static void compressedTexImage(GLenum _target, GLint _level, GLenum _internalformat, GLsizei _width, GLsizei _height, GLsizei _depth, GLint _border, GLsizei _imageSize, const GLvoid* _data)
+	static void compressedTexImage(
+		  GLenum _target
+		, GLint _level
+		, GLenum _internalformat
+		, GLsizei _width
+		, GLsizei _height
+		, GLsizei _depth
+		, GLint _border
+		, GLsizei _imageSize
+		, const GLvoid* _data
+	)
 	{
-		if (_target == GL_TEXTURE_3D)
+		if (_target == GL_TEXTURE_3D
+		||  _target == GL_TEXTURE_2D_ARRAY
+		||  _target == GL_TEXTURE_CUBE_MAP_ARRAY)
+		{
+			GL_CHECK(glCompressedTexImage3D(
+				  _target
+				, _level
+				, _internalformat
+				, _width
+				, _height
+				, _depth
+				, _border
+				, _imageSize
+				, _data
+				) );
+		}
+		else if (_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
 		{
-			GL_CHECK(glCompressedTexImage3D(_target, _level, _internalformat, _width, _height, _depth, _border, _imageSize, _data) );
 		}
 		else
 		{
 			BX_UNUSED(_depth);
-			GL_CHECK(glCompressedTexImage2D(_target, _level, _internalformat, _width, _height, _border, _imageSize, _data) );
+			GL_CHECK(glCompressedTexImage2D(
+				  _target
+				, _level
+				, _internalformat
+				, _width
+				, _height
+				, _border
+				, _imageSize
+				, _data
+				) );
 		}
 	}
 
-	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)
+	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 (_target == GL_TEXTURE_3D)
 		{
-			GL_CHECK(glCompressedTexSubImage3D(_target, _level, _xoffset, _yoffset, _zoffset, _width, _height, _depth, _format, _imageSize, _data) );
+			GL_CHECK(glCompressedTexSubImage3D(
+				  _target
+				, _level
+				, _xoffset
+				, _yoffset
+				, _zoffset
+				, _width
+				, _height
+				, _depth
+				, _format
+				, _imageSize
+				, _data
+				) );
 		}
 		else
 		{
 			BX_UNUSED(_zoffset, _depth);
-			GL_CHECK(glCompressedTexSubImage2D(_target, _level, _xoffset, _yoffset, _width, _height, _format, _imageSize, _data) );
+			GL_CHECK(glCompressedTexSubImage2D(
+				  _target
+				, _level
+				, _xoffset
+				, _yoffset
+				, _width
+				, _height
+				, _format
+				, _imageSize
+				, _data
+				) );
 		}
 	}
 
@@ -4408,7 +4611,10 @@ namespace bgfx { namespace gl
 				const ImageBlockInfo& ibi = getBlockInfo(TextureFormat::Enum(imageContainer.m_format) );
 				textureWidth  = bx::uint32_max(ibi.blockWidth,  imageContainer.m_width >>startLod);
 				textureHeight = bx::uint32_max(ibi.blockHeight, imageContainer.m_height>>startLod);
-				textureDepth  = imageContainer.m_depth;
+				textureDepth  = 1 < imageContainer.m_depth
+					? imageContainer.m_depth
+					: imageContainer.m_numLayers
+					;
 			}
 
 			m_requestedFormat  = uint8_t(imageContainer.m_format);
@@ -4431,6 +4637,16 @@ namespace bgfx { namespace gl
 				target = GL_TEXTURE_3D;
 			}
 
+			if (1 < imageContainer.m_numLayers)
+			{
+				switch (target)
+				{
+				case GL_TEXTURE_CUBE_MAP:       target = GL_TEXTURE_CUBE_MAP_ARRAY;
+				case GL_TEXTURE_2D_MULTISAMPLE: target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
+				default:                        target = GL_TEXTURE_2D_ARRAY;
+				}
+			}
+
 			if (!init(target
 					, textureWidth
 					, textureHeight
@@ -4442,7 +4658,10 @@ namespace bgfx { namespace gl
 				return;
 			}
 
-			target = GL_TEXTURE_CUBE_MAP == m_target ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : m_target;
+			target = isCubeMap()
+				? GL_TEXTURE_CUBE_MAP_POSITIVE_X
+				: m_target
+				;
 
 			const GLenum internalFmt = srgb
 				? s_textureFormat[m_textureFormat].m_internalFmtSrgb
@@ -4460,11 +4679,12 @@ namespace bgfx { namespace gl
 				|| swizzle
 				;
 
-			BX_TRACE("Texture%-4s %3d: %s (requested: %s), %dx%dx%d%s."
+			BX_TRACE("Texture%-4s %3d: %s (requested: %s), layers %d, %dx%dx%d%s."
 				, imageContainer.m_cubeMap ? "Cube" : (1 < imageContainer.m_depth ? "3D" : "2D")
 				, this - s_renderGL->m_textures
 				, getName( (TextureFormat::Enum)m_textureFormat)
 				, getName( (TextureFormat::Enum)m_requestedFormat)
+				, imageContainer.m_numLayers
 				, textureWidth
 				, textureHeight
 				, imageContainer.m_cubeMap ? 6 : (1 < imageContainer.m_depth ? imageContainer.m_depth : 0)
@@ -4495,7 +4715,10 @@ namespace bgfx { namespace gl
 				{
 					width  = bx::uint32_max(1, width);
 					height = bx::uint32_max(1, height);
-					depth  = bx::uint32_max(1, depth);
+					depth  = 1 < imageContainer.m_depth
+						? bx::uint32_max(1, depth)
+						: imageContainer.m_numLayers
+						;
 
 					ImageMip mip;
 					if (imageGetRawData(imageContainer, side, lod+startLod, _mem->data, _mem->size, mip) )
@@ -4622,8 +4845,6 @@ namespace bgfx { namespace gl
 
 	void TextureGL::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem)
 	{
-		BX_UNUSED(_z, _depth);
-
 		const uint32_t bpp = getBitsPerPixel(TextureFormat::Enum(m_textureFormat) );
 		const uint32_t rectpitch = _rect.m_width*bpp/8;
 		uint32_t srcpitch  = UINT16_MAX == _pitch ? rectpitch : _pitch;
@@ -4631,7 +4852,10 @@ namespace bgfx { namespace gl
 		GL_CHECK(glBindTexture(m_target, m_id) );
 		GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1) );
 
-		GLenum target = GL_TEXTURE_CUBE_MAP == m_target ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : m_target;
+		GLenum target = isCubeMap()
+			? GL_TEXTURE_CUBE_MAP_POSITIVE_X
+			: m_target
+			;
 
 		const bool swizzle = true
 			&& TextureFormat::BGRA8 == m_requestedFormat
@@ -5132,11 +5356,12 @@ namespace bgfx { namespace gl
 						&& s_extension[Extension::ARB_shader_texture_lod].m_supported
 						&& bx::findIdentifierMatch(code, s_ARB_shader_texture_lod)
 						;
-					const bool usesGpuShader5 = !!bx::findIdentifierMatch(code, s_ARB_gpu_shader5);
-					const bool usesIUsamplers = !!bx::findIdentifierMatch(code, s_uisamplers);
-					const bool usesTexelFetch = !!bx::findIdentifierMatch(code, s_texelFetch);
-					const bool usesTextureMS  = !!bx::findIdentifierMatch(code, s_ARB_texture_multisample);
-					const bool usesPacking    = !!bx::findIdentifierMatch(code, s_ARB_shading_language_packing);
+					const bool usesGpuShader5   = !!bx::findIdentifierMatch(code, s_ARB_gpu_shader5);
+					const bool usesIUsamplers   = !!bx::findIdentifierMatch(code, s_uisamplers);
+					const bool usesTexelFetch   = !!bx::findIdentifierMatch(code, s_texelFetch);
+					const bool usesTextureArray = !!bx::findIdentifierMatch(code, s_textureArray);
+					const bool usesTextureMS    = !!bx::findIdentifierMatch(code, s_ARB_texture_multisample);
+					const bool usesPacking      = !!bx::findIdentifierMatch(code, s_ARB_shading_language_packing);
 
 					uint32_t version =
 						  usesIUsamplers || usesTexelFetch ? 130
@@ -5172,6 +5397,11 @@ namespace bgfx { namespace gl
 						writeString(&writer, "#extension GL_ARB_texture_multisample : enable\n");
 					}
 
+					if (usesTextureArray)
+					{
+						writeString(&writer, "#extension GL_EXT_texture_array : enable\n");
+					}
+
 					if (130 <= version)
 					{
 						if (m_type == GL_FRAGMENT_SHADER)
@@ -5460,7 +5690,7 @@ namespace bgfx { namespace gl
 					}
 					else
 					{
-						GLenum target = GL_TEXTURE_CUBE_MAP == texture.m_target
+						GLenum target = texture.isCubeMap()
 							? GL_TEXTURE_CUBE_MAP_POSITIVE_X + m_attachment[ii].layer
 							: texture.m_target
 							;
@@ -5521,7 +5751,7 @@ namespace bgfx { namespace gl
 							{
 								++colorIdx;
 
-								GLenum target = GL_TEXTURE_CUBE_MAP == texture.m_target
+								GLenum target = texture.isCubeMap()
 									? GL_TEXTURE_CUBE_MAP_POSITIVE_X + m_attachment[ii].layer
 									: texture.m_target
 									;

+ 36 - 0
src/renderer_gl.h

@@ -624,6 +624,14 @@ typedef uint64_t GLuint64;
 #	define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
 #endif // GL_UNSIGNED_INT_SAMPLER_2D
 
+#ifndef GL_INT_SAMPLER_2D_ARRAY
+#	define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#endif // GL_INT_SAMPLER_2D_ARRAY
+
+#ifndef GL_UNSIGNED_INT_SAMPLER_2D_ARRAY
+#	define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#endif // GL_UNSIGNED_INT_SAMPLER_2D_ARRAY
+
 #ifndef GL_INT_SAMPLER_3D
 #	define GL_INT_SAMPLER_3D 0x8DCB
 #endif // GL_INT_SAMPLER_3D
@@ -656,6 +664,14 @@ typedef uint64_t GLuint64;
 #	define GL_SAMPLER_2D_SHADOW 0x8B62
 #endif // GL_SAMPLER_2D_SHADOW
 
+#ifndef GL_SAMPLER_2D_ARRAY
+#	define GL_SAMPLER_2D_ARRAY 0x8DC1
+#endif // GL_SAMPLER_2D_ARRAY
+
+#ifndef GL_SAMPLER_2D_ARRAY_SHADOW
+#	define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#endif // GL_SAMPLER_2D_ARRAY_SHADOW
+
 #ifndef GL_TEXTURE_MAX_LEVEL
 #	define GL_TEXTURE_MAX_LEVEL 0x813D
 #endif // GL_TEXTURE_MAX_LEVEL
@@ -863,6 +879,18 @@ typedef uint64_t GLuint64;
 #	define GL_CLAMP_TO_BORDER 0x812D
 #endif // GL_CLAMP_TO_BORDER
 
+#ifndef GL_TEXTURE_2D_ARRAY
+#	define GL_TEXTURE_2D_ARRAY 0x8C1A
+#endif // GL_TEXTURE_2D_ARRAY
+
+#ifndef GL_TEXTURE_2D_MULTISAMPLE_ARRAY
+#	define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#endif // GL_TEXTURE_2D_MULTISAMPLE_ARRAY
+
+#ifndef GL_TEXTURE_CUBE_MAP_ARRAY
+#	define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#endif // GL_TEXTURE_CUBE_MAP_ARRAY
+
 #ifndef GL_TEXTURE_CUBE_MAP_SEAMLESS
 #	define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
 #endif // GL_TEXTURE_CUBE_MAP_SEAMLESS
@@ -1240,6 +1268,14 @@ namespace bgfx { namespace gl
 		void commit(uint32_t _stage, uint32_t _flags, const float _palette[][4]);
 		void resolve() const;
 
+		bool isCubeMap() const
+		{
+			return 0
+				|| GL_TEXTURE_CUBE_MAP       == m_target
+				|| GL_TEXTURE_CUBE_MAP_ARRAY == m_target
+				;
+		}
+
 		GLuint m_id;
 		GLuint m_rbo;
 		GLenum m_target;

+ 21 - 5
tools/shaderc/shaderc.cpp

@@ -89,6 +89,14 @@ namespace bgfx
 		NULL
 	};
 
+	static const char* s_textureArray[] =
+	{
+		"texture2DArray",
+		"texture2DArrayLod",
+		"shadow2DArray",
+		NULL
+	};
+
 	static const char* s_ARB_texture_multisample[] =
 	{
 		"sampler2DMS",
@@ -1760,11 +1768,12 @@ namespace bgfx
 							{
 								std::string code;
 
-								const bool usesTextureLod = !!bx::findIdentifierMatch(input, s_ARB_shader_texture_lod /*EXT_shader_texture_lod*/);
-								const bool usesGpuShader5 = !!bx::findIdentifierMatch(input, s_ARB_gpu_shader5);
-								const bool usesPacking    = !!bx::findIdentifierMatch(input, s_ARB_shading_language_packing);
-								const bool usesTextureMS  = !!bx::findIdentifierMatch(input, s_ARB_texture_multisample);
-								const bool usesTexelFetch = !!bx::findIdentifierMatch(input, s_texelFetch);
+								const bool usesGpuShader5   = !!bx::findIdentifierMatch(input, s_ARB_gpu_shader5);
+								const bool usesTexelFetch   = !!bx::findIdentifierMatch(input, s_texelFetch);
+								const bool usesTextureLod   = !!bx::findIdentifierMatch(input, s_ARB_shader_texture_lod /*EXT_shader_texture_lod*/);
+								const bool usesTextureMS    = !!bx::findIdentifierMatch(input, s_ARB_texture_multisample);
+								const bool usesTextureArray = !!bx::findIdentifierMatch(input, s_textureArray);
+								const bool usesPacking      = !!bx::findIdentifierMatch(input, s_ARB_shading_language_packing);
 
 								if (0 == essl)
 								{
@@ -1824,6 +1833,13 @@ namespace bgfx
 											, "#extension GL_ARB_texture_multisample : enable\n"
 											);
 									}
+
+									if (usesTextureArray)
+									{
+										bx::stringPrintf(code
+											, "#extension GL_EXT_texture_array : enable\n"
+											);
+									}
 								}
 								else
 								{