From 300f2a611e0108bf6ed2c73e39ff594ce84d5c02 Mon Sep 17 00:00:00 2001 From: Luke Benstead <kazade@gmail.com> Date: Fri, 17 Mar 2023 20:40:45 +0000 Subject: [PATCH] Optimise state management --- GL/private.h | 1 + GL/state.c | 210 ++++++++++++++++++++++++++++++++++++--------------- GL/texture.c | 8 ++ 3 files changed, 160 insertions(+), 59 deletions(-) diff --git a/GL/private.h b/GL/private.h index 200ffde..7db1b13 100644 --- a/GL/private.h +++ b/GL/private.h @@ -525,6 +525,7 @@ GLboolean _glNearZClippingEnabled(); GLboolean _glGPUStateIsDirty(); void _glGPUStateMarkClean(); +void _glGPUStateMarkDirty(); #define MAX_GLDC_TEXTURE_UNITS 2 #define MAX_GLDC_LIGHTS 8 diff --git a/GL/state.c b/GL/state.c index 38c60ee..ced1cdc 100644 --- a/GL/state.c +++ b/GL/state.c @@ -90,6 +90,10 @@ void _glGPUStateMarkClean() { GPUState.is_dirty = GL_FALSE; } +void _glGPUStateMarkDirty() { + GPUState.is_dirty = GL_TRUE; +} + GLboolean _glGPUStateIsDirty() { return GPUState.is_dirty; } @@ -160,10 +164,8 @@ GLboolean _glIsScissorTestEnabled() { } void _glRecalcEnabledLights() { - GLubyte i; - GPUState.enabled_light_count = 0; - for(int i = 0; i < MAX_GLDC_LIGHTS; ++i) { + for(GLubyte i = 0; i < MAX_GLDC_LIGHTS; ++i) { if(_glLightAt(i)->isEnabled) { GPUState.enabled_light_count++; } @@ -389,41 +391,68 @@ void _glInitContext() { } GLAPI void APIENTRY glEnable(GLenum cap) { - GLboolean was_dirty = GPUState.is_dirty; - - GPUState.is_dirty = GL_TRUE; - switch(cap) { case GL_TEXTURE_2D: - TEXTURES_ENABLED[_glGetActiveTexture()] = GL_TRUE; + if(TEXTURES_ENABLED[_glGetActiveTexture()] != GL_TRUE) { + TEXTURES_ENABLED[_glGetActiveTexture()] = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } break; case GL_CULL_FACE: { - GPUState.cull_face = GL_TRUE; + if(GPUState.cull_face != GL_TRUE) { + GPUState.cull_face = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } + } break; case GL_DEPTH_TEST: { - GPUState.depth_test_enabled = GL_TRUE; + if(GPUState.depth_test_enabled != GL_TRUE) { + GPUState.depth_test_enabled = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } } break; case GL_BLEND: { - GPUState.blend_enabled = GL_TRUE; + if(GPUState.blend_enabled != GL_TRUE) { + GPUState.blend_enabled = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } } break; case GL_SCISSOR_TEST: { - GPUState.scissor_test_enabled = GL_TRUE; + if(GPUState.scissor_test_enabled != GL_TRUE) { + GPUState.scissor_test_enabled = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } } break; case GL_LIGHTING: { - GPUState.lighting_enabled = GL_TRUE; + if(GPUState.lighting_enabled != GL_TRUE) { + GPUState.lighting_enabled = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } } break; case GL_FOG: - GPUState.fog_enabled = GL_TRUE; + if(GPUState.fog_enabled != GL_TRUE) { + GPUState.fog_enabled = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } break; case GL_COLOR_MATERIAL: - GPUState.color_material_enabled = GL_TRUE; + if(GPUState.color_material_enabled != GL_TRUE) { + GPUState.color_material_enabled = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } break; case GL_SHARED_TEXTURE_PALETTE_EXT: { - GPUState.shared_palette_enabled = GL_TRUE; + if(GPUState.shared_palette_enabled != GL_TRUE) { + GPUState.shared_palette_enabled = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } } break; case GL_ALPHA_TEST: { - GPUState.alpha_test_enabled = GL_TRUE; + if(GPUState.alpha_test_enabled != GL_TRUE) { + GPUState.alpha_test_enabled = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } } break; case GL_LIGHT0: case GL_LIGHT1: @@ -432,62 +461,102 @@ GLAPI void APIENTRY glEnable(GLenum cap) { case GL_LIGHT4: case GL_LIGHT5: case GL_LIGHT6: - case GL_LIGHT7: - _glLightAt(cap & 0xF)->isEnabled = GL_TRUE; - _glRecalcEnabledLights(); + case GL_LIGHT7: { + LightSource* ptr = _glLightAt(cap & 0xF); + if(ptr->isEnabled != GL_TRUE) { + ptr->isEnabled = GL_TRUE; + _glRecalcEnabledLights(); + } + } break; case GL_NEARZ_CLIPPING_KOS: - GPUState.znear_clipping_enabled = GL_TRUE; + if(GPUState.znear_clipping_enabled != GL_TRUE) { + GPUState.znear_clipping_enabled = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } break; case GL_POLYGON_OFFSET_POINT: case GL_POLYGON_OFFSET_LINE: case GL_POLYGON_OFFSET_FILL: - GPUState.polygon_offset_enabled = GL_TRUE; + if(GPUState.polygon_offset_enabled != GL_TRUE) { + GPUState.polygon_offset_enabled = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } break; case GL_NORMALIZE: - GPUState.normalize_enabled = GL_TRUE; + if(GPUState.normalize_enabled != GL_TRUE) { + GPUState.normalize_enabled = GL_TRUE; + GPUState.is_dirty = GL_TRUE; + } break; default: - GPUState.is_dirty = was_dirty; break; } } GLAPI void APIENTRY glDisable(GLenum cap) { - GLboolean was_dirty = GPUState.is_dirty; - GPUState.is_dirty = GL_TRUE; - switch(cap) { - case GL_TEXTURE_2D: { - TEXTURES_ENABLED[_glGetActiveTexture()] = GL_FALSE; - } break; + case GL_TEXTURE_2D: + if(TEXTURES_ENABLED[_glGetActiveTexture()] != GL_FALSE) { + TEXTURES_ENABLED[_glGetActiveTexture()] = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } + break; case GL_CULL_FACE: { - GPUState.culling_enabled = GL_FALSE; + if(GPUState.cull_face != GL_FALSE) { + GPUState.cull_face = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } + } break; case GL_DEPTH_TEST: { - GPUState.depth_test_enabled = GL_FALSE; + if(GPUState.depth_test_enabled != GL_FALSE) { + GPUState.depth_test_enabled = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } + } break; + case GL_BLEND: { + if(GPUState.blend_enabled != GL_FALSE) { + GPUState.blend_enabled = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } } break; - case GL_BLEND: - GPUState.blend_enabled = GL_FALSE; - break; case GL_SCISSOR_TEST: { - GPUState.scissor_test_enabled = GL_FALSE; + if(GPUState.scissor_test_enabled != GL_FALSE) { + GPUState.scissor_test_enabled = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } } break; case GL_LIGHTING: { - GPUState.lighting_enabled = GL_FALSE; + if(GPUState.lighting_enabled != GL_FALSE) { + GPUState.lighting_enabled = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } } break; case GL_FOG: - GPUState.fog_enabled = GL_FALSE; + if(GPUState.fog_enabled != GL_FALSE) { + GPUState.fog_enabled = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } break; case GL_COLOR_MATERIAL: - GPUState.color_material_enabled = GL_FALSE; + if(GPUState.color_material_enabled != GL_FALSE) { + GPUState.color_material_enabled = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } break; case GL_SHARED_TEXTURE_PALETTE_EXT: { - GPUState.shared_palette_enabled = GL_FALSE; + if(GPUState.shared_palette_enabled != GL_FALSE) { + GPUState.shared_palette_enabled = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } } break; case GL_ALPHA_TEST: { - GPUState.alpha_test_enabled = GL_FALSE; + if(GPUState.alpha_test_enabled != GL_FALSE) { + GPUState.alpha_test_enabled = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } } break; case GL_LIGHT0: case GL_LIGHT1: @@ -497,21 +566,32 @@ GLAPI void APIENTRY glDisable(GLenum cap) { case GL_LIGHT5: case GL_LIGHT6: case GL_LIGHT7: - _glEnableLight(cap & 0xF, GL_FALSE); + if(GPUState.lights[cap & 0xF].isEnabled) { + _glEnableLight(cap & 0xF, GL_FALSE); + GPUState.is_dirty = GL_TRUE; + } break; case GL_NEARZ_CLIPPING_KOS: - GPUState.znear_clipping_enabled = GL_FALSE; + if(GPUState.znear_clipping_enabled != GL_FALSE) { + GPUState.znear_clipping_enabled = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } break; case GL_POLYGON_OFFSET_POINT: case GL_POLYGON_OFFSET_LINE: case GL_POLYGON_OFFSET_FILL: - GPUState.polygon_offset_enabled = GL_FALSE; + if(GPUState.polygon_offset_enabled != GL_FALSE) { + GPUState.polygon_offset_enabled = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } break; case GL_NORMALIZE: - GPUState.normalize_enabled = GL_FALSE; + if(GPUState.normalize_enabled != GL_FALSE) { + GPUState.normalize_enabled = GL_FALSE; + GPUState.is_dirty = GL_TRUE; + } break; default: - GPUState.is_dirty = was_dirty; break; } } @@ -558,13 +638,17 @@ GLAPI void APIENTRY glReadBuffer(GLenum mode) { } GLAPI void APIENTRY glDepthMask(GLboolean flag) { - GPUState.depth_mask_enabled = flag; - GPUState.is_dirty = GL_TRUE; + if(GPUState.depth_mask_enabled != flag) { + GPUState.depth_mask_enabled = flag; + GPUState.is_dirty = GL_TRUE; + } } GLAPI void APIENTRY glDepthFunc(GLenum func) { - GPUState.depth_func = func; - GPUState.is_dirty = GL_TRUE; + if(GPUState.depth_func != func) { + GPUState.depth_func = func; + GPUState.is_dirty = GL_TRUE; + } } /* Hints */ @@ -584,26 +668,34 @@ GLAPI void APIENTRY glPolygonMode(GLenum face, GLenum mode) { /* Culling */ GLAPI void APIENTRY glFrontFace(GLenum mode) { - GPUState.front_face = mode; - GPUState.is_dirty = GL_TRUE; + if(GPUState.front_face != mode) { + GPUState.front_face = mode; + GPUState.is_dirty = GL_TRUE; + } } GLAPI void APIENTRY glCullFace(GLenum mode) { - GPUState.cull_face = mode; - GPUState.is_dirty = GL_TRUE; + if(GPUState.cull_face != mode) { + GPUState.cull_face = mode; + GPUState.is_dirty = GL_TRUE; + } } /* Shading - Flat or Goraud */ GLAPI void APIENTRY glShadeModel(GLenum mode) { - GPUState.shade_model = mode; - GPUState.is_dirty = GL_TRUE; + if(GPUState.shade_model != mode) { + GPUState.shade_model = mode; + GPUState.is_dirty = GL_TRUE; + } } /* Blending */ GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) { - GPUState.blend_sfactor = sfactor; - GPUState.blend_dfactor = dfactor; - GPUState.is_dirty = GL_TRUE; + if(GPUState.blend_dfactor != dfactor || GPUState.blend_sfactor != sfactor) { + GPUState.blend_sfactor = sfactor; + GPUState.blend_dfactor = dfactor; + GPUState.is_dirty = GL_TRUE; + } } diff --git a/GL/texture.c b/GL/texture.c index ce2414e..016be45 100644 --- a/GL/texture.c +++ b/GL/texture.c @@ -607,6 +607,8 @@ void APIENTRY glBindTexture(GLenum target, GLuint texture) { } else { TEXTURE_UNITS[ACTIVE_TEXTURE] = NULL; } + + _glGPUStateMarkDirty(); } void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) { @@ -668,6 +670,8 @@ void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) { default: break; } + + _glGPUStateMarkDirty(); } void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param) { @@ -1626,6 +1630,8 @@ void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) { break; } } + + _glGPUStateMarkDirty(); } void APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param) { @@ -1783,6 +1789,8 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize } _glApplyColorTable(palette); + + _glGPUStateMarkDirty(); } GLAPI void APIENTRY glColorSubTableEXT(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data) {