Implement unpacking for compressed vertex formats on GLES2 when not supported, fixes #22957
This commit is contained in:
parent
42ce497e79
commit
4f4e46edd5
5 changed files with 263 additions and 7 deletions
|
@ -1715,8 +1715,205 @@ RID RasterizerStorageGLES2::mesh_create() {
|
|||
return mesh_owner.make_rid(mesh);
|
||||
}
|
||||
|
||||
static float Float16ToFloat(short fltInt16) {
|
||||
int fltInt32 = ((fltInt16 & 0x8000) << 16);
|
||||
fltInt32 |= ((fltInt16 & 0x7fff) << 13) + 0x38000000;
|
||||
|
||||
float fRet;
|
||||
memcpy(&fRet, &fltInt32, sizeof(float));
|
||||
return fRet;
|
||||
}
|
||||
|
||||
static PoolVector<uint8_t> _unpack_half_floats(const PoolVector<uint8_t> &array, uint32_t &format, int p_vertices) {
|
||||
|
||||
uint32_t p_format = format;
|
||||
|
||||
static int src_size[VS::ARRAY_MAX];
|
||||
static int dst_size[VS::ARRAY_MAX];
|
||||
static int to_convert[VS::ARRAY_MAX];
|
||||
|
||||
int src_stride = 0;
|
||||
int dst_stride = 0;
|
||||
|
||||
for (int i = 0; i < VS::ARRAY_MAX; i++) {
|
||||
|
||||
to_convert[i] = 0;
|
||||
if (!(p_format & (1 << i))) {
|
||||
src_size[i] = 0;
|
||||
dst_size[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (i) {
|
||||
|
||||
case VS::ARRAY_VERTEX: {
|
||||
|
||||
if (p_format & VS::ARRAY_COMPRESS_VERTEX) {
|
||||
|
||||
if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) {
|
||||
src_size[i] = 4;
|
||||
dst_size[i] = 8;
|
||||
to_convert[i] = 2;
|
||||
} else {
|
||||
src_size[i] = 8;
|
||||
dst_size[i] = 12;
|
||||
to_convert[i] = 3;
|
||||
}
|
||||
|
||||
format &= ~VS::ARRAY_COMPRESS_VERTEX;
|
||||
} else {
|
||||
|
||||
if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) {
|
||||
src_size[i] = 8;
|
||||
dst_size[i] = 8;
|
||||
} else {
|
||||
src_size[i] = 12;
|
||||
dst_size[i] = 12;
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
case VS::ARRAY_NORMAL: {
|
||||
|
||||
if (p_format & VS::ARRAY_COMPRESS_NORMAL) {
|
||||
src_size[i] = 4;
|
||||
dst_size[i] = 4;
|
||||
} else {
|
||||
src_size[i] = 12;
|
||||
dst_size[i] = 12;
|
||||
}
|
||||
|
||||
} break;
|
||||
case VS::ARRAY_TANGENT: {
|
||||
|
||||
if (p_format & VS::ARRAY_COMPRESS_TANGENT) {
|
||||
src_size[i] = 4;
|
||||
dst_size[i] = 4;
|
||||
} else {
|
||||
src_size[i] = 16;
|
||||
dst_size[i] = 16;
|
||||
}
|
||||
|
||||
} break;
|
||||
case VS::ARRAY_COLOR: {
|
||||
|
||||
if (p_format & VS::ARRAY_COMPRESS_COLOR) {
|
||||
src_size[i] = 4;
|
||||
dst_size[i] = 4;
|
||||
} else {
|
||||
src_size[i] = 16;
|
||||
dst_size[i] = 16;
|
||||
}
|
||||
|
||||
} break;
|
||||
case VS::ARRAY_TEX_UV: {
|
||||
|
||||
if (p_format & VS::ARRAY_COMPRESS_TEX_UV) {
|
||||
src_size[i] = 4;
|
||||
to_convert[i] = 2;
|
||||
format &= ~VS::ARRAY_COMPRESS_TEX_UV;
|
||||
} else {
|
||||
src_size[i] = 8;
|
||||
}
|
||||
|
||||
dst_size[i] = 8;
|
||||
|
||||
} break;
|
||||
case VS::ARRAY_TEX_UV2: {
|
||||
|
||||
if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) {
|
||||
src_size[i] = 4;
|
||||
to_convert[i] = 2;
|
||||
format &= ~VS::ARRAY_COMPRESS_TEX_UV2;
|
||||
} else {
|
||||
src_size[i] = 8;
|
||||
}
|
||||
|
||||
dst_size[i] = 8;
|
||||
|
||||
} break;
|
||||
case VS::ARRAY_BONES: {
|
||||
|
||||
if (p_format & VS::ARRAY_FLAG_USE_16_BIT_BONES) {
|
||||
src_size[i] = 8;
|
||||
dst_size[i] = 8;
|
||||
} else {
|
||||
src_size[i] = 4;
|
||||
dst_size[i] = 4;
|
||||
}
|
||||
|
||||
} break;
|
||||
case VS::ARRAY_WEIGHTS: {
|
||||
|
||||
if (p_format & VS::ARRAY_COMPRESS_WEIGHTS) {
|
||||
src_size[i] = 8;
|
||||
dst_size[i] = 8;
|
||||
} else {
|
||||
src_size[i] = 16;
|
||||
dst_size[i] = 16;
|
||||
}
|
||||
|
||||
} break;
|
||||
case VS::ARRAY_INDEX: {
|
||||
|
||||
src_size[i] = 0;
|
||||
dst_size[i] = 0;
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
src_stride += src_size[i];
|
||||
dst_stride += dst_size[i];
|
||||
}
|
||||
|
||||
PoolVector<uint8_t> ret;
|
||||
ret.resize(p_vertices * dst_stride);
|
||||
|
||||
PoolVector<uint8_t>::Read r = array.read();
|
||||
PoolVector<uint8_t>::Write w = ret.write();
|
||||
|
||||
int src_offset = 0;
|
||||
int dst_offset = 0;
|
||||
|
||||
for (int i = 0; i < VS::ARRAY_MAX; i++) {
|
||||
|
||||
if (src_size[i] == 0) {
|
||||
continue; //no go
|
||||
}
|
||||
const uint8_t *rptr = r.ptr();
|
||||
uint8_t *wptr = w.ptr();
|
||||
if (to_convert[i]) { //converting
|
||||
|
||||
for (int j = 0; j < p_vertices; j++) {
|
||||
const uint16_t *src = (const uint16_t *)&rptr[src_stride * j + src_offset];
|
||||
float *dst = (float *)&wptr[dst_stride * j + dst_offset];
|
||||
|
||||
for (int k = 0; k < to_convert[i]; k++) {
|
||||
|
||||
dst[k] = Math::half_to_float(src[k]);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
//just copy
|
||||
for (int j = 0; j < p_vertices; j++) {
|
||||
for (int k = 0; k < src_size[i]; k++) {
|
||||
wptr[dst_stride * j + dst_offset + k] = rptr[src_stride * j + src_offset + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
src_offset += src_size[i];
|
||||
dst_offset += dst_size[i];
|
||||
}
|
||||
|
||||
r = PoolVector<uint8_t>::Read();
|
||||
w = PoolVector<uint8_t>::Write();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<AABB> &p_bone_aabbs) {
|
||||
PoolVector<uint8_t> array = p_array;
|
||||
|
||||
Mesh *mesh = mesh_owner.getornull(p_mesh);
|
||||
ERR_FAIL_COND(!mesh);
|
||||
|
@ -1735,6 +1932,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
|
|||
Surface::Attrib attribs[VS::ARRAY_MAX];
|
||||
|
||||
int stride = 0;
|
||||
bool uses_half_float = false;
|
||||
|
||||
for (int i = 0; i < VS::ARRAY_MAX; i++) {
|
||||
|
||||
|
@ -1763,6 +1961,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
|
|||
if (p_format & VS::ARRAY_COMPRESS_VERTEX) {
|
||||
attribs[i].type = _GL_HALF_FLOAT_OES;
|
||||
stride += attribs[i].size * 2;
|
||||
uses_half_float = true;
|
||||
} else {
|
||||
attribs[i].type = GL_FLOAT;
|
||||
stride += attribs[i].size * 4;
|
||||
|
@ -1823,6 +2022,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
|
|||
if (p_format & VS::ARRAY_COMPRESS_TEX_UV) {
|
||||
attribs[i].type = _GL_HALF_FLOAT_OES;
|
||||
stride += 4;
|
||||
uses_half_float = true;
|
||||
} else {
|
||||
attribs[i].type = GL_FLOAT;
|
||||
stride += 8;
|
||||
|
@ -1838,6 +2038,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
|
|||
if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) {
|
||||
attribs[i].type = _GL_HALF_FLOAT_OES;
|
||||
stride += 4;
|
||||
uses_half_float = true;
|
||||
} else {
|
||||
attribs[i].type = GL_FLOAT;
|
||||
stride += 8;
|
||||
|
@ -1900,6 +2101,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
|
|||
}
|
||||
|
||||
//validate sizes
|
||||
PoolVector<uint8_t> array = p_array;
|
||||
|
||||
int array_size = stride * p_vertex_count;
|
||||
int index_array_size = 0;
|
||||
|
@ -1931,6 +2133,15 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
|
|||
|
||||
ERR_FAIL_COND(array.size() != array_size);
|
||||
|
||||
if (!config.support_half_float_vertices && uses_half_float) {
|
||||
|
||||
uint32_t new_format = p_format;
|
||||
PoolVector<uint8_t> unpacked_array = _unpack_half_floats(array, new_format, p_vertex_count);
|
||||
|
||||
mesh_add_surface(p_mesh, new_format, p_primitive, unpacked_array, p_vertex_count, p_index_array, p_index_count, p_aabb, p_blend_shapes, p_bone_aabbs);
|
||||
return; //do not go any further, above function used unpacked stuff will be used instead.
|
||||
}
|
||||
|
||||
if (p_format & VS::ARRAY_FORMAT_INDEX) {
|
||||
|
||||
index_array_size = attribs[VS::ARRAY_INDEX].stride * p_index_count;
|
||||
|
@ -4679,6 +4890,12 @@ void RasterizerStorageGLES2::initialize() {
|
|||
config.support_write_depth = config.extensions.has("GL_EXT_frag_depth");
|
||||
#endif
|
||||
|
||||
#ifdef JAVASCRIPT_ENABLED
|
||||
config.support_half_float_vertices = false;
|
||||
#else
|
||||
//every other platform, be it mobile or desktop, supports this (even if not in the GLES2 spec).
|
||||
config.support_half_float_vertices = true;
|
||||
#endif
|
||||
|
||||
frame.count = 0;
|
||||
frame.delta = 0;
|
||||
|
|
|
@ -81,6 +81,7 @@ public:
|
|||
|
||||
bool support_32_bits_indices;
|
||||
bool support_write_depth;
|
||||
bool support_half_float_vertices;
|
||||
} config;
|
||||
|
||||
struct Resources {
|
||||
|
|
|
@ -215,6 +215,26 @@ VERTEX_SHADER_CODE
|
|||
/* clang-format off */
|
||||
[fragment]
|
||||
|
||||
#ifndef USE_GLES_OVER_GL
|
||||
|
||||
#ifdef GL_EXT_shader_texture_lod
|
||||
#extension GL_EXT_shader_texture_lod : enable
|
||||
#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod)
|
||||
#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod)
|
||||
#endif
|
||||
|
||||
#ifdef GL_ARB_shader_texture_lod
|
||||
#extension GL_ARB_shader_texture_lod : enable
|
||||
#endif
|
||||
|
||||
#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod)
|
||||
#define texture2DLod(img, coord, lod) texture2D(img, coord, lod)
|
||||
#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_GLES_OVER_GL
|
||||
#define lowp
|
||||
#define mediump
|
||||
|
|
|
@ -25,6 +25,8 @@ void main() {
|
|||
/* clang-format off */
|
||||
[fragment]
|
||||
|
||||
#ifndef USE_GLES_OVER_GL
|
||||
|
||||
#ifdef GL_EXT_shader_texture_lod
|
||||
#extension GL_EXT_shader_texture_lod : enable
|
||||
#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod)
|
||||
|
@ -36,8 +38,10 @@ void main() {
|
|||
#endif
|
||||
|
||||
#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod)
|
||||
#define texture2DLod(img, coord, lod) texture2D(img, coord)
|
||||
#define textureCubeLod(img, coord, lod) textureCube(img, coord)
|
||||
#define texture2DLod(img, coord, lod) texture2D(img, coord, lod)
|
||||
#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_GLES_OVER_GL
|
||||
|
|
|
@ -655,13 +655,27 @@ VERTEX_SHADER_CODE
|
|||
|
||||
/* clang-format off */
|
||||
[fragment]
|
||||
#extension GL_ARB_shader_texture_lod : enable
|
||||
|
||||
#ifndef GL_ARB_shader_texture_lod
|
||||
#define texture2DLod(img, coord, lod) texture2D(img, coord)
|
||||
#define textureCubeLod(img, coord, lod) textureCube(img, coord)
|
||||
#ifndef USE_GLES_OVER_GL
|
||||
|
||||
#ifdef GL_EXT_shader_texture_lod
|
||||
#extension GL_EXT_shader_texture_lod : enable
|
||||
#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod)
|
||||
#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod)
|
||||
#endif
|
||||
|
||||
#ifdef GL_ARB_shader_texture_lod
|
||||
#extension GL_ARB_shader_texture_lod : enable
|
||||
#endif
|
||||
|
||||
#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod)
|
||||
#define texture2DLod(img, coord, lod) texture2D(img, coord, lod)
|
||||
#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_GLES_OVER_GL
|
||||
#define lowp
|
||||
#define mediump
|
||||
|
|
Loading…
Reference in a new issue