mirror of
https://github.com/MobileGL-Dev/MobileGlues.git
synced 2025-09-22 02:32:29 -04:00
[Feat] (multidraw): switch different multidraw emulation routine
This commit is contained in:
parent
f11ba3f11b
commit
eab666e44b
@ -26,6 +26,8 @@ void init_settings() {
|
||||
int enableExtGL43 = success ? config_get_int("enableExtGL43") : 0;
|
||||
int enableExtComputeShader = success ? config_get_int("enableExtComputeShader") : 0;
|
||||
int enableCompatibleMode = success ? config_get_int("enableCompatibleMode") : 0;
|
||||
multidraw_mode_t multidrawMode = success ? (multidraw_mode_t)config_get_int("multidrawMode") : multidraw_mode_t::Auto;
|
||||
// multidraw_mode_t multidrawMode = multidraw_mode_t::PreferUnroll;
|
||||
size_t maxGlslCacheSize = 0;
|
||||
if (config_get_int("maxGlslCacheSize") > 0)
|
||||
maxGlslCacheSize = success ? config_get_int("maxGlslCacheSize") * 1024 * 1024 : 0;
|
||||
@ -40,6 +42,8 @@ void init_settings() {
|
||||
enableExtComputeShader = 0;
|
||||
if (enableCompatibleMode < 0 || enableCompatibleMode > 1)
|
||||
enableCompatibleMode = 0;
|
||||
if ((int)multidrawMode < 0 || (int)multidrawMode > 3)
|
||||
multidrawMode = multidraw_mode_t::Auto;
|
||||
|
||||
// 1205
|
||||
int fclVersion = 0;
|
||||
@ -63,6 +67,7 @@ void init_settings() {
|
||||
enableCompatibleMode = 0;
|
||||
}
|
||||
|
||||
// Determining actual ANGLE mode
|
||||
const char* gpuString = getGPUInfo();
|
||||
LOG_D("GPU: %s", gpuString)
|
||||
|
||||
@ -120,10 +125,73 @@ void init_settings() {
|
||||
|
||||
global_settings.enable_compatible_mode = enableCompatibleMode;
|
||||
|
||||
global_settings.multidraw_mode = multidrawMode;
|
||||
|
||||
std::string draw_mode_str;
|
||||
switch (global_settings.multidraw_mode) {
|
||||
case multidraw_mode_t::PreferIndirect:
|
||||
draw_mode_str = "Indirect";
|
||||
break;
|
||||
case multidraw_mode_t::PreferUnroll:
|
||||
draw_mode_str = "Unroll";
|
||||
break;
|
||||
case multidraw_mode_t::PreferMultidrawIndirect:
|
||||
draw_mode_str = "Multidraw indirect";
|
||||
break;
|
||||
case multidraw_mode_t::Auto:
|
||||
draw_mode_str = "Auto";
|
||||
break;
|
||||
default:
|
||||
draw_mode_str = "(Unknown)";
|
||||
global_settings.multidraw_mode = multidraw_mode_t::Auto;
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_V("[MobileGlues] Setting: enableAngle = %s", global_settings.angle ? "true" : "false")
|
||||
LOG_V("[MobileGlues] Setting: ignoreError = %i", global_settings.ignore_error)
|
||||
LOG_V("[MobileGlues] Setting: enableExtComputeShader = %s", global_settings.ext_compute_shader ? "true" : "false")
|
||||
LOG_V("[MobileGlues] Setting: enableExtGL43 = %s", global_settings.ext_gl43 ? "true" : "false")
|
||||
LOG_V("[MobileGlues] Setting: maxGlslCacheSize = %i", global_settings.max_glsl_cache_size / 1024 / 1024)
|
||||
LOG_V("[MobileGlues] Setting: enableCompatibleMode = %s", global_settings.enable_compatible_mode ? "true" : "false")
|
||||
LOG_V("[MobileGlues] Setting: multidrawMode = %s", draw_mode_str.c_str())
|
||||
}
|
||||
|
||||
void init_settings_post() {
|
||||
bool multidraw = g_gles_caps.GL_EXT_multi_draw_indirect;
|
||||
bool basevertex =
|
||||
g_gles_caps.GL_OES_draw_elements_base_vertex ||
|
||||
(g_gles_caps.major == 3 && g_gles_caps.minor >= 2) || (g_gles_caps.major > 3);
|
||||
bool indirect = (g_gles_caps.major == 3 && g_gles_caps.minor >= 1) || (g_gles_caps.major > 3);
|
||||
|
||||
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)")
|
||||
break;
|
||||
case multidraw_mode_t::PreferUnroll:
|
||||
LOG_V("multidrawMode = PreferUnroll")
|
||||
if (basevertex) {
|
||||
global_settings.multidraw_mode = multidraw_mode_t::PreferUnroll;
|
||||
LOG_V(" -> Unroll (OK)")
|
||||
} else if (multidraw) {
|
||||
global_settings.multidraw_mode = multidraw_mode_t::PreferMultidrawIndirect;
|
||||
LOG_V(" -> MultidrawIndirect (Preferred not supported, falling back)")
|
||||
} else {
|
||||
global_settings.multidraw_mode = multidraw_mode_t::PreferIndirect;
|
||||
LOG_V(" -> Indirect (Preferred not supported, falling back)")
|
||||
}
|
||||
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 {
|
||||
global_settings.multidraw_mode = multidraw_mode_t::PreferIndirect;
|
||||
LOG_V(" -> Indirect")
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
@ -11,6 +11,13 @@ extern "C" {
|
||||
|
||||
#include <__stddef_size_t.h>
|
||||
|
||||
enum class multidraw_mode_t: int {
|
||||
Auto = 0,
|
||||
PreferIndirect,
|
||||
PreferUnroll,
|
||||
PreferMultidrawIndirect
|
||||
};
|
||||
|
||||
struct global_settings_t {
|
||||
int angle; // 0, 1
|
||||
int ignore_error; // 0, 1, 2
|
||||
@ -18,12 +25,14 @@ 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
|
||||
};
|
||||
|
||||
extern struct global_settings_t global_settings;
|
||||
|
||||
void init_settings();
|
||||
|
||||
void init_settings_post();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -14,6 +14,141 @@ 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) {
|
||||
GLES.glGenBuffers(1, &g_indirectbuffer);
|
||||
GLES.glBindBuffer(GL_DRAW_INDIRECT_BUFFER, g_indirectbuffer);
|
||||
g_cmdbufsize = 1;
|
||||
GLES.glBufferData(GL_DRAW_INDIRECT_BUFFER,
|
||||
g_cmdbufsize * sizeof(draw_elements_indirect_command_t), NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
g_indirect_cmds_inited = true;
|
||||
}
|
||||
|
||||
if (g_cmdbufsize < primcount) {
|
||||
size_t sz = g_cmdbufsize;
|
||||
|
||||
LOG_D("Before resize: %d", sz)
|
||||
|
||||
// 2-exponential to reduce reallocation
|
||||
while (sz < primcount)
|
||||
sz *= 2;
|
||||
|
||||
GLES.glBufferData(GL_DRAW_INDIRECT_BUFFER,
|
||||
sz * sizeof(draw_elements_indirect_command_t), NULL, GL_DYNAMIC_DRAW);
|
||||
g_cmdbufsize = sz;
|
||||
}
|
||||
|
||||
LOG_D("After resize: %d", g_cmdbufsize)
|
||||
|
||||
auto* pcmds = (draw_elements_indirect_command_t*)
|
||||
GLES.glMapBufferRange(GL_DRAW_INDIRECT_BUFFER,
|
||||
0, primcount * sizeof(draw_elements_indirect_command_t),
|
||||
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
||||
|
||||
GLsizei elementSize;
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
elementSize = 1;
|
||||
break;
|
||||
case GL_UNSIGNED_SHORT:
|
||||
elementSize = 2;
|
||||
break;
|
||||
case GL_UNSIGNED_INT:
|
||||
elementSize = 4;
|
||||
break;
|
||||
default:
|
||||
elementSize = 4;
|
||||
}
|
||||
|
||||
for (GLsizei i = 0; i < primcount; ++i) {
|
||||
auto byteOffset = reinterpret_cast<uintptr_t>(indices[i]);
|
||||
pcmds[i].firstIndex = static_cast<GLuint>(byteOffset / elementSize);
|
||||
pcmds[i].count = counts[i];
|
||||
pcmds[i].instanceCount = 1;
|
||||
pcmds[i].baseVertex = basevertex[i];
|
||||
pcmds[i].reservedMustBeZero = 0;
|
||||
}
|
||||
|
||||
GLES.glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER);
|
||||
}
|
||||
|
||||
void mg_glMultiDrawElementsBaseVertex_indirect(GLenum mode, GLsizei* counts, GLenum type, const void* const* indices, GLsizei primcount, const GLint* basevertex) {
|
||||
LOG()
|
||||
|
||||
prepare_indirect_buffer(counts, type, indices, primcount, basevertex);
|
||||
|
||||
// Draw indirect!
|
||||
for (GLsizei i = 0; i < primcount; ++i) {
|
||||
const GLvoid* offset = reinterpret_cast<GLvoid*>(i * sizeof(draw_elements_indirect_command_t));
|
||||
GLES.glDrawElementsIndirect(mode, type, offset);
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR
|
||||
}
|
||||
|
||||
void mg_glMultiDrawElementsBaseVertex_multiindirect(GLenum mode, GLsizei* counts, GLenum type, const void* const* indices, GLsizei primcount, const GLint* basevertex) {
|
||||
LOG()
|
||||
|
||||
prepare_indirect_buffer(counts, type, indices, primcount, basevertex);
|
||||
|
||||
// Multi-draw indirect!
|
||||
GLES.glMultiDrawElementsIndirectEXT(mode, type, 0, primcount, 0);
|
||||
|
||||
CHECK_GL_ERROR
|
||||
}
|
||||
|
||||
void mg_glMultiDrawElementsBaseVertex_unroll(GLenum mode, GLsizei* counts, GLenum type, const void* const* indices, GLsizei primcount, const GLint* basevertex) {
|
||||
LOG()
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
CHECK_GL_ERROR
|
||||
}
|
||||
|
||||
void mg_glMultiDrawElements_indirect(GLenum mode, const GLsizei *count, GLenum type, const void *const *indices, GLsizei primcount) {
|
||||
LOG()
|
||||
|
||||
prepare_indirect_buffer(count, type, indices, primcount, 0);
|
||||
// Draw indirect!
|
||||
for (GLsizei i = 0; i < primcount; ++i) {
|
||||
const GLvoid* offset = reinterpret_cast<GLvoid*>(i * sizeof(draw_elements_indirect_command_t));
|
||||
GLES.glDrawElementsIndirect(mode, type, offset);
|
||||
}
|
||||
CHECK_GL_ERROR
|
||||
}
|
||||
|
||||
void mg_glMultiDrawElements_multiindirect(GLenum mode, const GLsizei *count, GLenum type, const void *const *indices, GLsizei primcount) {
|
||||
LOG()
|
||||
|
||||
prepare_indirect_buffer(count, type, indices, primcount, 0);
|
||||
|
||||
// Multi-draw indirect!
|
||||
GLES.glMultiDrawElementsIndirectEXT(mode, type, 0, primcount, 0);
|
||||
|
||||
CHECK_GL_ERROR
|
||||
}
|
||||
|
||||
void mg_glMultiDrawElements_unroll(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 glMultiDrawElementsBaseVertex(GLenum mode, GLsizei* counts, GLenum type, const void* const* indices, GLsizei primcount, const GLint* basevertex) {
|
||||
LOG()
|
||||
|
||||
|
@ -31,6 +31,18 @@ struct draw_elements_indirect_command_t {
|
||||
|
||||
GLAPI GLAPIENTRY void glMultiDrawElementsBaseVertex(GLenum mode, GLsizei *counts, GLenum type, const void *const *indices, GLsizei primcount, const GLint *basevertex);
|
||||
|
||||
GLAPI GLAPIENTRY void mg_glMultiDrawElementsBaseVertex_indirect(GLenum mode, GLsizei *counts, GLenum type, const void *const *indices, GLsizei primcount, const GLint *basevertex);
|
||||
|
||||
GLAPI GLAPIENTRY void mg_glMultiDrawElementsBaseVertex_multiindirect(GLenum mode, GLsizei *counts, GLenum type, const void *const *indices, GLsizei primcount, const GLint *basevertex);
|
||||
|
||||
GLAPI GLAPIENTRY void mg_glMultiDrawElementsBaseVertex_unroll(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_unroll(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);
|
||||
|
@ -138,6 +138,9 @@ void InitGLESCapabilities() {
|
||||
|
||||
InitGLESBaseExtensions();
|
||||
|
||||
GLES.glGetIntegerv(GL_MAJOR_VERSION, &g_gles_caps.major);
|
||||
GLES.glGetIntegerv(GL_MINOR_VERSION, &g_gles_caps.minor);
|
||||
|
||||
// int has_GL_EXT_buffer_storage = 0;
|
||||
// int has_GL_ARB_timer_query = 0;
|
||||
// int has_GL_QCOM_texture_lod_bias = 0;
|
||||
@ -577,13 +580,13 @@ void init_target_gles() {
|
||||
INIT_GLES_FUNC(glMultiDrawArraysIndirectEXT)
|
||||
INIT_GLES_FUNC(glMultiDrawElementsIndirectEXT)
|
||||
INIT_GLES_FUNC(glMultiDrawElementsBaseVertexEXT)
|
||||
INIT_GLES_FUNC(glBruh)
|
||||
// INIT_GLES_FUNC(glBruh)
|
||||
|
||||
LOG_D("glMultiDrawArraysIndirectEXT() @ 0x%x", GLES.glMultiDrawArraysIndirectEXT)
|
||||
LOG_D("glMultiDrawElementsIndirectEXT() @ 0x%x", GLES.glMultiDrawElementsIndirectEXT)
|
||||
LOG_D("glMultiDrawElementsBaseVertexEXT() @ 0x%x", GLES.glMultiDrawElementsBaseVertexEXT)
|
||||
|
||||
LOG_D("glBruh() @ 0x%x", GLES.glBruh)
|
||||
// LOG_D("glBruh() @ 0x%x", GLES.glBruh)
|
||||
|
||||
LOG_D("Initializing %s @ hardware", RENDERERNAME)
|
||||
set_hardware();
|
||||
|
@ -137,6 +137,8 @@ extern "C" GLAPI GLAPIENTRY type name(__VA_ARGS__) { \
|
||||
}
|
||||
|
||||
struct gles_caps_t {
|
||||
int major;
|
||||
int minor;
|
||||
int GL_EXT_buffer_storage;
|
||||
int GL_EXT_disjoint_timer_query;
|
||||
int GL_QCOM_texture_lod_bias;
|
||||
|
@ -11,12 +11,44 @@
|
||||
#include "../includes.h"
|
||||
#include "../gl/log.h"
|
||||
#include "../gl/envvars.h"
|
||||
#include "../config/settings.h"
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
void* get_multidraw_func(const char* name) {
|
||||
std::string namestr = name;
|
||||
if (namestr != "glMultiDrawElementsBaseVertex" && namestr != "glMultiDrawElements") {
|
||||
return nullptr;
|
||||
} else {
|
||||
namestr = "mg_" + namestr;
|
||||
}
|
||||
|
||||
switch (global_settings.multidraw_mode) {
|
||||
case multidraw_mode_t::PreferIndirect:
|
||||
namestr += "_indirect";
|
||||
break;
|
||||
case multidraw_mode_t::PreferUnroll:
|
||||
namestr += "_unroll";
|
||||
break;
|
||||
case multidraw_mode_t::PreferMultidrawIndirect:
|
||||
namestr += "_multiindirect";
|
||||
break;
|
||||
default:
|
||||
LOG_W("get_multidraw_func() cannot determine multidraw emulation mode!")
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dlsym(RTLD_DEFAULT, namestr.c_str());
|
||||
}
|
||||
|
||||
void *glXGetProcAddress(const char *name) {
|
||||
LOG()
|
||||
void* proc = dlsym(RTLD_DEFAULT, (const char*)name);
|
||||
void* proc = nullptr;
|
||||
|
||||
proc = get_multidraw_func(name);
|
||||
|
||||
if (!proc)
|
||||
proc = dlsym(RTLD_DEFAULT, (const char*)name);
|
||||
|
||||
if (!proc) {
|
||||
fprintf(stderr, "Failed to get OpenGL function %s: %s\n", name, dlerror());
|
||||
@ -29,7 +61,12 @@ void *glXGetProcAddress(const char *name) {
|
||||
|
||||
void *glXGetProcAddressARB(const char *name) {
|
||||
LOG()
|
||||
void* proc = dlsym(RTLD_DEFAULT, (const char*)name);
|
||||
void* proc = nullptr;
|
||||
|
||||
proc = get_multidraw_func(name);
|
||||
|
||||
if (!proc)
|
||||
proc = dlsym(RTLD_DEFAULT, (const char*)name);
|
||||
|
||||
if (!proc) {
|
||||
fprintf(stderr, "Failed to get OpenGL function %s: %s\n", name, dlerror());
|
||||
|
@ -76,6 +76,8 @@ void proc_init() {
|
||||
init_target_egl();
|
||||
init_target_gles();
|
||||
|
||||
init_settings_post();
|
||||
|
||||
init_libshaderconv();
|
||||
|
||||
#if PROFILING
|
||||
|
@ -13,7 +13,7 @@
|
||||
#define REVISION 2
|
||||
#define PATCH 0
|
||||
|
||||
#define VERSION_TYPE VERSION_RELEASE
|
||||
#define VERSION_TYPE VERSION_DEVELOPMENT
|
||||
|
||||
#define VERSION_SUFFIX ""
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user