Skip to content

Spurious differences in OpVariable instructions #6109

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jimblandy opened this issue Apr 28, 2025 · 3 comments
Open

Spurious differences in OpVariable instructions #6109

jimblandy opened this issue Apr 28, 2025 · 3 comments
Assignees

Comments

@jimblandy
Copy link
Contributor

When the attached files are compared, spirv-diff produces the following output:

...
          %50 = OpConstantComposite %6 %47 %48 %49
          %52 = OpTypePointer Private %6
-         %51 = OpVariable %52 Private %50
+        %404 = OpVariable %52 Private %50
          %54 = OpTypePointer StorageBuffer %20
          %53 = OpVariable %54 StorageBuffer
...

Those two instructions look the same to me.

spirv-diff-bug.zip

@ShabbyX
Copy link
Contributor

ShabbyX commented Apr 29, 2025

I went back and forth about this long ago, in the end I decided on the current behavior. The issue here is that debug information is missing, without which a lot of the variables look the same. Like a shader may have a lot of vec4 function-local variables, how would you distinguish them?

Right now, variables are matched independently from the shader code, so when ambiguous I don't attempt to match them. The differ could maybe try harder by doing all the possible mappings and see which one produces a minimal diff (but that's an exponential number of combinations).

@ShabbyX
Copy link
Contributor

ShabbyX commented Apr 29, 2025

Oh in this particular case I see the variables are not actually ambiguous, there is only one instance of a variable of type %52, so these could have been matched. I'll put up a fix when I get a chance.

@ShabbyX
Copy link
Contributor

ShabbyX commented Jun 6, 2025

I gave this a bunch of thought, and went in with some ideas about giving "match scores" between variables and running a "maximum bipartite matching" algorithm over it to find the best matches. However, I noticed something even better in the code already. Unfortunately, that makes it rather unjustified to try and match variables further.

What I found I had done before is this. First, the variables that are obviously a match are matched, but what's very useful in matching variables is that once the body of functions are matched, the matching OpLoad, OpStore, OpAccessChain etc instructions are inspected and if they are applied to unmatched variables, those variables are matched. So for example if you have these:

; Unmatched src variables
%srcv1 = OpVariable ...
%srcv2 = OpVariable ...
                                      ; Unmatched dst variables
                                      %dstv1 = OpVariable ...
                                      %dstv2 = OpVariable ...
                                      %dstv3 = OpVariable ...
...
; Bunch of matched instructions
; This OpLoad matched in the middle
%src = OpLoad %srcv1                  %dst = OpLoad %dstv3
; Bunch of matched instructions

Then while looking at the variables themselves it's highly ambiguous how to match them, looking at the matched OpLoads, it's very likely that %srcv1 and %dstv3 are a match. That's how spirv-diff currently matches Private variables (when debug info is missing).

If at the end some variables aren't matched, then matching them by some arbitrary matching doesn't really add much value; they were not used in matching instructions anyway. In your particular repro case, there's only one Private variable and it's completely unused in the shader.

I could add code to handle this very specific case, but I honestly don't see much value in it. If the shaders had more than 1 variable, the matching would be completely arbitrary. How would you match 3 unused private vec4s in one shader with 5 unused private vec4s in another? FWIW, the arbitrary matching is not hard, I guess I'm just trying to understand whether it's useful in any practical way (other than trying to reach empty diff for identical shaders)

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

No branches or pull requests

2 participants