Skip to content

Conversation

@tnibler
Copy link

@tnibler tnibler commented Nov 12, 2025

This issue has been raised in other places, but implementing it as a SPIR-V check instead of a glslang compiler/validator warning makes it a bit more generally applicable.

I realize I'm just dumping a huge feature here, but I find it useful and the linter hasn't seen too much recent interest it appears, so I thought why not.

Given the program:

#version 450

struct Foo {
    vec3 v;
    float f;
};

Foo GLOBAL;

void iSetGLOBAL() { GLOBAL.f = 5.0; }
float needGLOBAL() { return GLOBAL.f * 2.0; }
float needGLOBAL2() {  return GLOBAL.v[0]; }

int other() {
    int a = 2;
    for (int i; i < 5; ++i) {
        iSetGLOBAL();
    }
    if (GLOBAL.v[0] > 0) {
        a = 3;
    }
    return a;
}


float transitivelyNeedGLOBAL(float arg) {
    if (arg < 0.0) {
        return needGLOBAL();
    }
    return needGLOBAL2();
}

void main() {
    int a = 2;
    vec2 v;
    v[0] = 1.0;
    if (1 == 2) {
        v[1] = 2.0;
        needGLOBAL();
    }
    transitivelyNeedGLOBAL(4.0);
    float aaa = GLOBAL.f * v[1];
    int c = a + other();
    needGLOBAL();
}

It produces:

local_global.frag:33:11:	In function main:
local_global.frag:42:0:	Load from potentially uninitialized local variable v
	>    float aaa = GLOBAL.f * v[1];

local_global.frag:14:11:	In function other(:
local_global.frag:16:0:	Load from potentially uninitialized local variable i
	>    for (int i; i < 5; ++i) {
local_global.frag:16:0:	Load from potentially uninitialized local variable i
	>    for (int i; i < 5; ++i) {


In entrypoint main:
Load from potentially uninitialized module-private variable GLOBAL
local_global.frag:39:0:	In call to needGLOBAL(:
	>         needGLOBAL();
local_global.frag:11:0:
	> float needGLOBAL() { return GLOBAL.f * 2.0; }
Load from potentially uninitialized module-private variable GLOBAL
local_global.frag:28:0:	In call to needGLOBAL(:
	>         return needGLOBAL();
local_global.frag:41:0:	Called by transitivelyNeedGLOBAL(f1;:
	>     transitivelyNeedGLOBAL(4.0);
local_global.frag:11:0:
	> float needGLOBAL() { return GLOBAL.f * 2.0; }
Load from potentially uninitialized module-private variable GLOBAL
local_global.frag:30:0:	In call to needGLOBAL2(:
	>     return needGLOBAL2();
local_global.frag:41:0:	Called by transitivelyNeedGLOBAL(f1;:
	>     transitivelyNeedGLOBAL(4.0);
local_global.frag:12:0:
	> float needGLOBAL2() {  return GLOBAL.v[0]; }
Load from potentially uninitialized module-private variable GLOBAL
local_global.frag:42:0:
	>     float aaa = GLOBAL.f * v[1];
Load from potentially uninitialized module-private variable GLOBAL
local_global.frag:43:0:	In call to other(:
	>     int c = a + other();
local_global.frag:19:0:
	>     if (GLOBAL.v[0] > 0) {

Does do:

  • Tracks initialization state of every field in composite types
  • Merges init state after control flow constructs
  • Intra- and inter-function analysis, for module private/global variables

Does not (yet):

  • Look into loops, or any range analysis for non-constant array indexing. If an array is stored to in a loop we just treat it as a store to the whole array
  • Handle symbolic math for specconst-sized arrays. Arrays of this sort are treated like a single value for now.

The implementation covers the basics in its current state, though a number of things are still ugly and messy (and as mentioned some features are more like placeholders). But I think it's far enough along to see if there's any interest/remarks on it :)

@CLAassistant
Copy link

CLAassistant commented Nov 12, 2025

CLA assistant check
All committers have signed the CLA.

@alan-baker alan-baker requested a review from Keenuts November 14, 2025 19:45
@s-perron
Copy link
Collaborator

@tnibler When this is no longer a draft, ping me, and I'll get someone to look at it. We will probably not look at it as long as it is a draft.

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.

3 participants