Skip to content

Commit

Permalink
Add environment variable to select accuracy vs speed
Browse files Browse the repository at this point in the history
We might have more cases in the future, where we can choose between an
accurate software implemenation and a faster but non-standard GPU
implementation. Let's create a mechanism through which the client can
select the features which can be sped up at the cost of correct
rendering.

This is currently exposed as an environment variable, and not as an API,
because if it turns out to be a bad idea we can remove it without
breaking the public API.
  • Loading branch information
mardy authored and WinterMute committed Nov 25, 2024
1 parent 176dc82 commit f4b2329
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 3 deletions.
17 changes: 17 additions & 0 deletions src/gc_gl.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,28 @@ int ogx_prepare_swap_buffers()
return glparamstate.render_mode == GL_RENDER ? 0 : -1;
}

static int parse_hints()
{
OgxHints hints = OGX_HINT_NONE;

/* comma separated list of operations for which a faster (but inaccurate)
* implementation is to be preferred over a more standard-compliant one.
* By default, we always prefer standard-compliance over speed. */
const char *env = getenv("OPENGX_FAST_OPS");
if (env) {
if (strstr(env, "sphere_map") != NULL)
hints |= OGX_HINT_FAST_SPHERE_MAP;
}

glparamstate.hints = hints;
}

void ogx_initialize()
{
_ogx_log_init();

_ogx_gpu_resources_init();
parse_hints();

glparamstate.current_call_list.index = -1;
GX_SetDispCopyGamma(GX_GM_1_0);
Expand Down
8 changes: 8 additions & 0 deletions src/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ extern "C" {
* opengx when stencil is enabled. */
#define MAX_TEXTURE_UNITS 4

typedef enum {
OGX_HINT_NONE = 0,
/* Enables fast (but wrong) GPU-accelerated GL_SPHERE_MAP */
OGX_HINT_FAST_SPHERE_MAP = 1 << 0,
} OgxHints;

typedef struct {
Pos3f pos;
Norm3f norm;
Expand Down Expand Up @@ -131,6 +137,8 @@ typedef struct glparams_

int viewport[4];

OgxHints hints;

unsigned char srcblend, dstblend;
unsigned char blendenabled;
unsigned char zwrite, ztest, zfunc;
Expand Down
30 changes: 27 additions & 3 deletions src/texture_gen_sw.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,35 @@ POSSIBILITY OF SUCH DAMAGE.
bool _ogx_texture_gen_sw_enabled(uint8_t unit)
{
const OgxTextureUnit *tu = &glparamstate.texture_unit[unit];
OgxHints hint = OGX_HINT_NONE;
bool needs_normals = false;

if (tu->gen_mode != GL_SPHERE_MAP) return false;
switch (tu->gen_mode) {
case GL_SPHERE_MAP:
hint = OGX_HINT_FAST_SPHERE_MAP;
needs_normals = true;
break;
case GL_REFLECTION_MAP:
/* We don't support a standard-compiant generation of the reflection
* map yet, because its output should consist of three float
* components, whereas the TEV only supports two components for
* GX_VA_TEX*. One way to implement it would be to (ab)use the
* GX_VA_NBT format: storing the computed texture generated coordinates
* into the binormal part of the array, and then use them in the TEV as
* GX_TG_BINRM.
* But this requires yet one more refactoring of the array classes, to
* let the normals array switch between GX_VA_NRM and GX_VA_NBT
* depending on whether GL_REFLECTION_MAP is enabled. Let's leave this
* as a TODO.
*/
default:
return false;
}

/* We need normal coordinates to be there */
if (!glparamstate.cs.normal_enabled) return false;
/* If the client prefers the inaccurate GPU implementation, let it be */
if (hint != OGX_HINT_NONE && (glparamstate.hints & hint)) return false;

if (needs_normals && !glparamstate.cs.normal_enabled) return false;

return true;
}
Expand Down

0 comments on commit f4b2329

Please sign in to comment.