{"record":{"id":"fdcb91c0d9fc7676","repo":"unoplatform/uno","slug":"getactiveuniform-did-not-report-uwave-barcount","errorCode":null,"errorMessage":"GetActiveUniform did not report uWave[{BarCount}] (saw {activeUniforms} active uniforms)","messagePattern":"GetActiveUniform did not report uWave\\[(.+?)\\] \\(saw (.+?) active uniforms\\)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/SamplesApp/SamplesApp.Samples/Windows_UI_Composition/QuerySyncGlCanvasElement.cs","lineNumber":151,"sourceCode":"\t\t\tgl.Uniform3(_uPaletteLoc, 4, new ReadOnlySpan<float>(_palette));\n\t\t\tgl.GetUniform(_barsProgram, _uPaletteLoc, out float firstComponent);\n\t\t\tif (Math.Abs(firstComponent - _palette[0]) > 0.001f)\n\t\t\t{\n\t\t\t\tthrow new Exception($\"GetUniform readback mismatch: got {firstComponent}, expected {_palette[0]}\");\n\t\t\t}\n\n\t\t\t// Program introspection: enumerate active uniforms and validate the program.\n\t\t\tgl.GetProgram(_barsProgram, ProgramPropertyARB.ActiveUniforms, out int activeUniforms);\n\t\t\tvar foundWave = false;\n\t\t\tfor (uint i = 0; i < activeUniforms; i++)\n\t\t\t{\n\t\t\t\tvar name = gl.GetActiveUniform(_barsProgram, i, out int size, out UniformType type);\n\t\t\t\t// Array uniforms report as \"uWave[0]\" with size = element count.\n\t\t\t\tfoundWave |= name.StartsWith(\"uWave\", StringComparison.Ordinal) && size == BarCount && type == UniformType.Float;\n\t\t\t}\n\t\t\tif (!foundWave)\n\t\t\t{\n\t\t\t\tthrow new Exception($\"GetActiveUniform did not report uWave[{BarCount}] (saw {activeUniforms} active uniforms)\");\n\t\t\t}\n\t\t\tgl.ValidateProgram(_barsProgram);\n\t\t\tgl.GetProgram(_barsProgram, ProgramPropertyARB.ValidateStatus, out int validateStatus);\n\t\t\tif (validateStatus != (int)GLEnum.True)\n\t\t\t{\n\t\t\t\tthrow new Exception(\"ValidateProgram failed: \" + gl.GetProgramInfoLog(_barsProgram));\n\t\t\t}\n\n\t\t\t_query = gl.GenQuery();\n\n\t\t\t// Init must finish error-clean; surface anything the calls above raised.\n\t\t\tvar err = gl.GetError();\n\t\t\tif (err != GLEnum.NoError)\n\t\t\t{\n\t\t\t\tthrow new Exception($\"GL error at end of Init: 0x{(int)err:x}\");\n\t\t\t}\n\t\t}\n","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/unoplatform/uno/blob/04183404888ea21b4e5bfa3493e8d5f15e972c3a/src/SamplesApp/SamplesApp.Samples/Windows_UI_Composition/QuerySyncGlCanvasElement.cs#L133-L169","documentation":"QuerySyncGlCanvasElement enumerates the active uniforms of _barsProgram via gl.GetProgram(ACTIVE_UNIFORMS) + gl.GetActiveUniform, expecting to find uWave reported as an array of size 8 (BarCount) with type Float. If no uniform matching `uWave`, size 8, type Float is found, this throws — meaning the program introspection did not surface the uWave array as expected.","triggerScenarios":"The loop at lines 143-148 iterates all active uniforms; foundWave stays false if no entry has name starting 'uWave', size == BarCount (8), and UniformType.Float. The throw at line 151 reports how many active uniforms were seen.","commonSituations":"uWave was optimized out by the GLSL compiler because the driver determined the array was not effectively used (it is used via uWave[gl_InstanceID], which some drivers fail to track as a dynamic index and prune); the driver reports the array name as 'uWave[0]' (correct) but with size 1 instead of 8 due to a driver bug; the type is reported as FloatVec3 or similar because of an introspection quirk; the uniform was inactive and thus not enumerated at all (ACTIVE_UNIFORMS only lists active uniforms).","solutions":["Print every (name, size, type) triple in the loop to see exactly how the driver reports uWave — most drivers report 'uWave[0]' with size 8 and type FLOAT, but a quirk needs to be seen to be handled.","Confirm the uWave array is genuinely used with a dynamically-indexed read in the shader (it is: `uWave[gl_InstanceID]`) — if a driver prunes it anyway, force it active by adding a dummy use or move the index to a non-instance-driven source.","Loosen the match: check `name.StartsWith(\"uWave\")` and `size == BarCount || size == 1` (some drivers report size 1 for arrays) before throwing.","Request the uniform's location with GetUniformLocation(program, \"uWave[0]\") and GetUniformLocation(program, \"uWave\") to confirm both forms resolve; -1 for both means the compiler pruned it.","If the driver reports UniformType.FloatVec4 instead of Float for the array element, that indicates the array was coalesced — inspect the shader source for an unintended redeclaration."],"exampleFix":"// before\nfoundWave |= name.StartsWith(\"uWave\", StringComparison.Ordinal) && size == BarCount && type == UniformType.Float;\nif (!foundWave)\n    throw new Exception($\"GetActiveUniform did not report uWave[{BarCount}] (saw {activeUniforms} active uniforms)\");\n\n// after — collect all uniforms for diagnosis and tolerate driver quirks\nvar report = new List<string>();\nfor (uint i = 0; i < activeUniforms; i++)\n{\n    var name = gl.GetActiveUniform(_barsProgram, i, out int size, out UniformType type);\n    report.Add($\"{name} size={size} type={type}\");\n    foundWave |= name.StartsWith(\"uWave\", StringComparison.Ordinal)\n        && (size == BarCount || size == 1)\n        && type == UniformType.Float;\n}\nif (!foundWave)\n    throw new Exception($\"uWave not reported. Active uniforms:\\n{string.Join('\\n', report)}\");","handlingStrategy":"validation","validationCode":"// Enumerate active uniforms with full diagnostics and tolerate driver-specific reporting quirks\nvar report = new List<string>();\nvar found = false;\nfor (uint i = 0; i < activeUniforms; i++)\n{\n    var (name, size, type) = (gl.GetActiveUniform(_barsProgram, i, out int s, out UniformType t), s, t);\n    report.Add($\"{name} size={size} type={type}\");\n    found |= name.StartsWith(\"uWave\") && (size == BarCount || size == 1) && type == UniformType.Float;\n}\nif (!found) App.MainWindow?.LogError($\"uWave not found. Uniforms:\\n{string.Join('\\n', report)}\");","typeGuard":null,"tryCatchPattern":"try { /* introspection loop + assertion */ }\ncatch (Exception ex) when (ex.Message.Contains(\"GetActiveUniform\"))\n{\n    // Driver may have pruned or coalesced uWave; rendering may still work\n    App.MainWindow?.LogError(ex.Message);\n}","preventionTips":["Print every active uniform's (name, size, type) to see how the driver reports arrays.","Tolerate size == 1 for arrays (some drivers report the [0] element only).","Confirm the uniform is genuinely used in the shader with a dynamic index.","Use GetUniformLocation(program, \"uWave[0]\") as a fallback to confirm existence."],"tags":["opengl","silk-net","uniform","uniform-array","introspection","driver-quirk","glsl"],"backgroundTag":null,"analyzedSha":"04183404888ea21b4e5bfa3493e8d5f15e972c3a","analyzedAt":"2026-08-13T21:08:11.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}