mirror of
https://github.com/MobileGL-Dev/MobileGlues.git
synced 2025-09-23 03:04:03 -04:00
[Feat] (...): Add "DrawElements" multi-draw mode.
This commit is contained in:
parent
77450d6e4c
commit
d609b8ceab
@ -42,7 +42,7 @@ void init_settings() {
|
||||
enableExtComputeShader = 0;
|
||||
if (enableCompatibleMode < 0 || enableCompatibleMode > 1)
|
||||
enableCompatibleMode = 0;
|
||||
if ((int)multidrawMode < 0 || (int)multidrawMode > 3)
|
||||
if ((int)multidrawMode < 0 || (int)multidrawMode > 4)
|
||||
multidrawMode = multidraw_mode_t::Auto;
|
||||
|
||||
// 1205
|
||||
@ -138,6 +138,9 @@ void init_settings() {
|
||||
case multidraw_mode_t::PreferMultidrawIndirect:
|
||||
draw_mode_str = "Multidraw indirect";
|
||||
break;
|
||||
case multidraw_mode_t::DrawElements:
|
||||
draw_mode_str = "DrawElements";
|
||||
break;
|
||||
case multidraw_mode_t::Auto:
|
||||
draw_mode_str = "Auto";
|
||||
break;
|
||||
@ -166,8 +169,13 @@ void init_settings_post() {
|
||||
switch (global_settings.multidraw_mode) {
|
||||
case multidraw_mode_t::PreferIndirect:
|
||||
LOG_V("multidrawMode = PreferIndirect")
|
||||
global_settings.multidraw_mode = multidraw_mode_t::PreferIndirect;
|
||||
LOG_V(" -> Indirect (OK)")
|
||||
if (indirect) {
|
||||
global_settings.multidraw_mode = multidraw_mode_t::PreferIndirect;
|
||||
LOG_V(" -> Indirect (OK)")
|
||||
} else {
|
||||
global_settings.multidraw_mode = multidraw_mode_t::DrawElements;
|
||||
LOG_V(" -> DrawElements (Preferred not supported, falling back)")
|
||||
}
|
||||
break;
|
||||
case multidraw_mode_t::PreferBaseVertex:
|
||||
LOG_V("multidrawMode = PreferUnroll")
|
||||
@ -177,20 +185,30 @@ void init_settings_post() {
|
||||
} else if (multidraw) {
|
||||
global_settings.multidraw_mode = multidraw_mode_t::PreferMultidrawIndirect;
|
||||
LOG_V(" -> MultidrawIndirect (Preferred not supported, falling back)")
|
||||
} else {
|
||||
} else if (indirect) {
|
||||
global_settings.multidraw_mode = multidraw_mode_t::PreferIndirect;
|
||||
LOG_V(" -> Indirect (Preferred not supported, falling back)")
|
||||
} else {
|
||||
global_settings.multidraw_mode = multidraw_mode_t::DrawElements;
|
||||
LOG_V(" -> DrawElements (Preferred not supported, falling back)")
|
||||
}
|
||||
break;
|
||||
case multidraw_mode_t::DrawElements:
|
||||
LOG_V("multidrawMode = DrawElements")
|
||||
global_settings.multidraw_mode = multidraw_mode_t::DrawElements;
|
||||
break;
|
||||
case multidraw_mode_t::Auto:
|
||||
default:
|
||||
LOG_V("multidrawMode = Auto")
|
||||
if (multidraw) {
|
||||
global_settings.multidraw_mode = multidraw_mode_t::PreferMultidrawIndirect;
|
||||
LOG_V(" -> MultidrawIndirect")
|
||||
} else {
|
||||
} else if (indirect) {
|
||||
global_settings.multidraw_mode = multidraw_mode_t::PreferIndirect;
|
||||
LOG_V(" -> Indirect")
|
||||
LOG_V(" -> Indirect (Preferred not supported, falling back)")
|
||||
} else {
|
||||
global_settings.multidraw_mode = multidraw_mode_t::DrawElements;
|
||||
LOG_V(" -> DrawElements (Preferred not supported, falling back)")
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -15,7 +15,8 @@ enum class multidraw_mode_t: int {
|
||||
Auto = 0,
|
||||
PreferIndirect,
|
||||
PreferBaseVertex,
|
||||
PreferMultidrawIndirect
|
||||
PreferMultidrawIndirect,
|
||||
DrawElements
|
||||
};
|
||||
|
||||
struct global_settings_t {
|
||||
@ -25,7 +26,7 @@ struct global_settings_t {
|
||||
int ext_compute_shader; // 0, 1
|
||||
size_t max_glsl_cache_size; // 0~
|
||||
int enable_compatible_mode; // 0, 1
|
||||
multidraw_mode_t multidraw_mode; // 0, 1, 2, 3
|
||||
multidraw_mode_t multidraw_mode; // 0, 1, 2, 3, 4
|
||||
};
|
||||
|
||||
extern struct global_settings_t global_settings;
|
||||
|
@ -12,8 +12,6 @@ static bool g_indirect_cmds_inited = false;
|
||||
static GLsizei g_cmdbufsize = 0;
|
||||
GLuint g_indirectbuffer = 0;
|
||||
|
||||
#define DRAW_INDIRECT
|
||||
|
||||
void prepare_indirect_buffer(const GLsizei *counts, GLenum type, const void *const *indices,
|
||||
GLsizei primcount, const GLint *basevertex) {
|
||||
if (!g_indirect_cmds_inited) {
|
||||
@ -74,6 +72,91 @@ void prepare_indirect_buffer(const GLsizei *counts, GLenum type, const void *con
|
||||
GLES.glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER);
|
||||
}
|
||||
|
||||
void mg_glMultiDrawElementsBaseVertex_drawelements(GLenum mode, GLsizei* counts, GLenum type, const void* const* indices, GLsizei primcount, const GLint* basevertex) {
|
||||
LOG()
|
||||
|
||||
GLint prevElementBuffer;
|
||||
GLES.glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &prevElementBuffer);
|
||||
|
||||
for (GLsizei i = 0; i < primcount; ++i) {
|
||||
if (counts[i] <= 0) continue;
|
||||
|
||||
GLsizei currentCount = counts[i];
|
||||
const GLvoid *currentIndices = indices[i];
|
||||
GLint currentBaseVertex = basevertex[i];
|
||||
|
||||
size_t indexSize;
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_INT: indexSize = sizeof(GLuint); break;
|
||||
case GL_UNSIGNED_SHORT: indexSize = sizeof(GLushort); break;
|
||||
case GL_UNSIGNED_BYTE: indexSize = sizeof(GLubyte); break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
GLuint tempBuffer;
|
||||
GLES.glGenBuffers(1, &tempBuffer);
|
||||
GLES.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tempBuffer);
|
||||
|
||||
void *srcData = nullptr;
|
||||
void *tempIndices = malloc(currentCount * indexSize);
|
||||
if (!tempIndices) {
|
||||
GLES.glDeleteBuffers(1, &tempBuffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prevElementBuffer != 0) {
|
||||
GLES.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prevElementBuffer);
|
||||
srcData = GLES.glMapBufferRange(
|
||||
GL_ELEMENT_ARRAY_BUFFER,
|
||||
(GLintptr)currentIndices,
|
||||
currentCount * indexSize,
|
||||
GL_MAP_READ_BIT
|
||||
);
|
||||
|
||||
if (!srcData) {
|
||||
free(tempIndices);
|
||||
GLES.glDeleteBuffers(1, &tempBuffer);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
srcData = (void*)currentIndices;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_INT:
|
||||
for (int j = 0; j < currentCount; ++j) {
|
||||
((GLuint *)tempIndices)[j] = ((GLuint *)srcData)[j] + currentBaseVertex;
|
||||
}
|
||||
break;
|
||||
case GL_UNSIGNED_SHORT:
|
||||
for (int j = 0; j < currentCount; ++j) {
|
||||
((GLushort *)tempIndices)[j] = ((GLushort *)srcData)[j] + currentBaseVertex;
|
||||
}
|
||||
break;
|
||||
case GL_UNSIGNED_BYTE:
|
||||
for (int j = 0; j < currentCount; ++j) {
|
||||
((GLubyte *)tempIndices)[j] = ((GLubyte *)srcData)[j] + currentBaseVertex;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (prevElementBuffer != 0) {
|
||||
GLES.glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
GLES.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tempBuffer);
|
||||
GLES.glBufferData(GL_ELEMENT_ARRAY_BUFFER, currentCount * indexSize, tempIndices, GL_STREAM_DRAW);
|
||||
free(tempIndices);
|
||||
GLES.glDrawElements(mode, currentCount, type, 0);
|
||||
|
||||
GLES.glDeleteBuffers(1, &tempBuffer);
|
||||
}
|
||||
|
||||
GLES.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prevElementBuffer);
|
||||
|
||||
CHECK_GL_ERROR
|
||||
}
|
||||
|
||||
void mg_glMultiDrawElementsBaseVertex_indirect(GLenum mode, GLsizei* counts, GLenum type, const void* const* indices, GLsizei primcount, const GLint* basevertex) {
|
||||
LOG()
|
||||
|
||||
@ -125,6 +208,19 @@ void mg_glMultiDrawElements_indirect(GLenum mode, const GLsizei *count, GLenum t
|
||||
CHECK_GL_ERROR
|
||||
}
|
||||
|
||||
void mg_glMultiDrawElements_drawelements(GLenum mode, const GLsizei *count, GLenum type, const void *const *indices, GLsizei primcount) {
|
||||
LOG()
|
||||
|
||||
for (GLsizei i = 0; i < primcount; ++i) {
|
||||
const GLsizei c = count[i];
|
||||
if (c > 0) {
|
||||
GLES.glDrawElements(mode, c, type, indices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR
|
||||
}
|
||||
|
||||
void mg_glMultiDrawElements_multiindirect(GLenum mode, const GLsizei *count, GLenum type, const void *const *indices, GLsizei primcount) {
|
||||
LOG()
|
||||
|
||||
@ -152,8 +248,6 @@ void mg_glMultiDrawElements_basevertex(GLenum mode, const GLsizei *count, GLenum
|
||||
void glMultiDrawElementsBaseVertex(GLenum mode, GLsizei* counts, GLenum type, const void* const* indices, GLsizei primcount, const GLint* basevertex) {
|
||||
LOG()
|
||||
|
||||
#ifdef DRAW_INDIRECT
|
||||
|
||||
if (!g_indirect_cmds_inited) {
|
||||
GLES.glGenBuffers(1, &g_indirectbuffer);
|
||||
GLES.glBindBuffer(GL_DRAW_INDIRECT_BUFFER, g_indirectbuffer);
|
||||
@ -217,26 +311,12 @@ void glMultiDrawElementsBaseVertex(GLenum mode, GLsizei* counts, GLenum type, co
|
||||
GLES.glDrawElementsIndirect(mode, type, offset);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
for (GLsizei i = 0; i < primcount; ++i) {
|
||||
const GLsizei count = counts[i];
|
||||
if (count > 0) {
|
||||
LOG_D("GLES.glDrawElementsBaseVertex, mode = %s, count = %d, type = %s, indices[i] = 0x%x, basevertex[i] = %d",
|
||||
glEnumToString(mode), count, glEnumToString(type), indices[i], basevertex[i])
|
||||
GLES.glDrawElementsBaseVertex(mode, count, type, indices[i], basevertex[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CHECK_GL_ERROR
|
||||
}
|
||||
|
||||
void glMultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices, GLsizei primcount) {
|
||||
LOG()
|
||||
|
||||
#ifdef DRAW_INDIRECT
|
||||
if (!g_indirect_cmds_inited) {
|
||||
GLES.glGenBuffers(1, &g_indirectbuffer);
|
||||
GLES.glBindBuffer(GL_DRAW_INDIRECT_BUFFER, g_indirectbuffer);
|
||||
@ -300,16 +380,6 @@ void glMultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, const v
|
||||
GLES.glDrawElementsIndirect(mode, type, offset);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
for (GLsizei i = 0; i < primcount; ++i) {
|
||||
const GLsizei c = count[i];
|
||||
if (c > 0) {
|
||||
GLES.glDrawElements(mode, c, type, indices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// solve the crash error for ANGLE, but it will make Derivative Main with Optifine not work!
|
||||
|
@ -37,12 +37,16 @@ GLAPI GLAPIENTRY void mg_glMultiDrawElementsBaseVertex_multiindirect(GLenum mode
|
||||
|
||||
GLAPI GLAPIENTRY void mg_glMultiDrawElementsBaseVertex_basevertex(GLenum mode, GLsizei *counts, GLenum type, const void *const *indices, GLsizei primcount, const GLint *basevertex);
|
||||
|
||||
GLAPI GLAPIENTRY void mg_glMultiDrawElementsBaseVertex_drawelements(GLenum mode, GLsizei *counts, GLenum type, const void *const *indices, GLsizei primcount, const GLint *basevertex);
|
||||
|
||||
GLAPI GLAPIENTRY void mg_glMultiDrawElements_indirect(GLenum mode, const GLsizei *count, GLenum type, const void *const *indices, GLsizei primcount);
|
||||
|
||||
GLAPI GLAPIENTRY void mg_glMultiDrawElements_multiindirect(GLenum mode, const GLsizei *count, GLenum type, const void *const *indices, GLsizei primcount);
|
||||
|
||||
GLAPI GLAPIENTRY void mg_glMultiDrawElements_basevertex(GLenum mode, const GLsizei *count, GLenum type, const void *const *indices, GLsizei primcount);
|
||||
|
||||
GLAPI GLAPIENTRY void mg_glMultiDrawElements_drawelements(GLenum mode, const GLsizei *count, GLenum type, const void *const *indices, GLsizei primcount);
|
||||
|
||||
GLAPI GLAPIENTRY void glMultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const void *const *indices, GLsizei primcount);
|
||||
|
||||
GLAPI GLAPIENTRY void glDrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices);
|
||||
|
@ -33,6 +33,9 @@ void* get_multidraw_func(const char* name) {
|
||||
case multidraw_mode_t::PreferMultidrawIndirect:
|
||||
namestr += "_multiindirect";
|
||||
break;
|
||||
case multidraw_mode_t::DrawElements:
|
||||
namestr += "_drawelements";
|
||||
break;
|
||||
default:
|
||||
LOG_W("get_multidraw_func() cannot determine multidraw emulation mode!")
|
||||
return nullptr;
|
||||
@ -52,7 +55,7 @@ void *glXGetProcAddress(const char *name) {
|
||||
|
||||
if (!proc) {
|
||||
fprintf(stderr, "Failed to get OpenGL function %s: %s\n", name, dlerror());
|
||||
LOG_W("Failed to get OpenGL function: %s", (const char*)name);
|
||||
LOG_W("Failed to get OpenGL function: %s", (const char*)name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -70,7 +73,7 @@ void *glXGetProcAddressARB(const char *name) {
|
||||
|
||||
if (!proc) {
|
||||
fprintf(stderr, "Failed to get OpenGL function %s: %s\n", name, dlerror());
|
||||
LOG_W("Failed to get OpenGL function: %s", (const char*)name);
|
||||
LOG_W("Failed to get OpenGL function: %s", (const char*)name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user