Skip to content

Return int from the NaN-safe multiplication of two ints - #1067

Open
Coastrnaut wants to merge 1 commit into
projectM-visualizer:masterfrom
Coastrnaut:fix/gles-int-multiply
Open

Coastrnaut wants to merge 1 commit into
projectM-visualizer:masterfrom
Coastrnaut:fix/gles-int-multiply

Conversation

@Coastrnaut

@Coastrnaut Coastrnaut commented Nov 9, 2026 •

Copy link
Copy Markdown

Related to #998

With Flag_AlternateNanPropagation, which projectM uses for all preset shaders, the GLSL generator replaces every multiplication with a mult0() helper. The int * int overload returned a float, but in HLSL the product of two ints is an int, and the generated code uses it as one, e.g. mult0(a, b) + 1, mult0(a, b) / 2 or int mask = mult0(a, b). Desktop GLSL converts int to float implicitly, so this mostly went unnoticed there, but GLSL ES has no implicit conversions, and these shaders fail to compile on OpenGL ES:

error C7011: implicit cast from "int" to "float"
error C7011: implicit cast from "float" to "int"

This makes the int overload return an int and adds the missing ivec2/ivec3/ivec4 overloads. Integers have no NaN, so a plain multiplication gives the same result. The float, vector and matrix overloads are unchanged.

How I found it

Master accepts GLES 3.0 contexts since e98fca8, so I compiled all 14,536 presets from cream-of-the-crop, en-d, milkdrop-original and projectm-classic with a GLES build in an OpenGL ES context (NVIDIA, via WGL_EXT_create_context_es2_profile) and compared with desktop GL 3.3. All of projectM's shaders use #version 300 es, so the driver applies GLSL ES 3.00 rules. 10 presets failed only on GLES:

martin - funky illusions failed on both desktop and GLES because of the int ← float assignment.

Testing

  • GLES: the 8 presets compile now. The only GLES-only failures left are the 3 sample ones that Fix HLSL constructs in Milkdrop presets that failed to transpile #1062 fixes; everything else that fails on GLES fails on desktop as well.
  • Desktop: I rendered all 14,536 presets with fixed audio, frame times and random seeds (local patch only, identical on both sides) and the preset folders as texture search path. Compile/link results and load failures are identical to master except that martin - funky illusions now compiles. Rendered one by one, the frames are identical to master except for two presets (martin - gate to moria, martin - mucus cervix) whose generated shaders only differ in the unused helper definitions and which also render differently between runs of master itself.
  • New HLSLAlternateMultiplyTest with 3 tests; 2 of them fail on master. All unit tests pass.

The NVIDIA driver always creates a GLES 3.2 context, so this covers the GLSL ES 3.00 language rules, not the 3.0 API limits mentioned in #998 (e.g. rendering to the GL_RG16F motion vector texture).

Retested on current master (2026-11-12)

With Flag_AlternateNanPropagation, which projectM uses for all preset
shaders, the GLSL generator replaces every multiplication with a helper
function. The int * int overload returned a float, but in HLSL the
product of two ints is an int, and the generated code uses it as one,
e.g. "mult0(a, b) + 1" or "int c = mult0(a, b)". Desktop GLSL converts
implicitly, but GLSL ES has no implicit int/float conversions, so these
shaders failed to compile on OpenGL ES.

Make the int overload return an int, and add the missing ivec overloads.
Integers have no NaN, so a plain multiplication gives the same result.

Related to projectM-visualizer#998

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant