Skip to content
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

[glsl-out] Handle vector bitcasts #1966

Merged
merged 10 commits into from
Jun 21, 2022

Conversation

expenses
Copy link
Contributor

@expenses expenses commented Jun 2, 2022

This fixes an issue where an OpBitcast on a vector didn't generate the correct glsl:

diff --git a/before.frag b/after.frag
index 8b2968b8..eb1074a2 100644
--- a/before.frag
+++ b/after.frag
@@ -126,8 +126,8 @@ void main_1() {
             }
             ivec3 _e2636 = phi_22745_;
             ivec3 _e2638 = phi_22742_;
-            ivec3 _e2643 = int(bitfieldExtract(uint(_e2638), int(uint(0)), int(uint(7))));
-            ivec3 _e2657 = int(bitfieldExtract(uint(_e2636), int(uint(0)), int(uint(7))));
+            ivec3 _e2643 = ivec3(bitfieldExtract(uvec3(_e2638), int(uint(0)), int(uint(7))));
+            ivec3 _e2657 = ivec3(bitfieldExtract(uvec3(_e2636), int(uint(0)), int(uint(7))));
             int _e2672 = max(((81 + (_e162 * 3)) - ((_e162 > _e180) ? 1 : 0)), 82);
             int _e2676 = (((_e162 == 0) || (_e162 == _e180)) ? 2 : 3);
             local = _e163;

@JCapucho
Copy link
Collaborator

JCapucho commented Jun 2, 2022

I don't think this is the right approach, I think the problem is the backend generating the bad casts not the frontend generating the bad IR because it sets the width, but I need either @kvark or @jimblandy to confirm

@jimblandy
Copy link
Member

SPIR-V OpBitcast instructions can change the number of components of composite types, but Naga IR has nothing like that. The other OpBitcast meanings all require the bit widths to match. So I would expect these to always become Expression::As expressions with convert: None.

So I think @JCapucho is right here: if the back end is looking at the absence of a bit width and generating an int cast instead of an ivec3 cast, that's the bug. It should be using the type of the operand and the kind in the As expression to decide what to output.

Here's the code in typifier.rs that says what the output of an As expression should be:

            crate::Expression::As {
                expr,
                kind,
                convert,
            } => match *past(expr)?.inner_with(types) {
                Ti::Scalar { kind: _, width } => TypeResolution::Value(Ti::Scalar {
                    kind,
                    width: convert.unwrap_or(width),
                }),
                Ti::Vector {
                    kind: _,
                    size,
                    width,
                } => TypeResolution::Value(Ti::Vector {
                    kind,
                    size,
                    width: convert.unwrap_or(width),
                }),
                Ti::Matrix {
                    columns,
                    rows,
                    width,
                } => TypeResolution::Value(Ti::Matrix {
                    columns,
                    rows,
                    width: convert.unwrap_or(width),
                }),
                ref other => {
                    return Err(ResolveError::IncompatibleOperands(format!(
                        "{:?} as {:?}",
                        other, kind
                    )))
                }
            },

Every path chooses the resulting kind from the As expression, not the operand.

@expenses expenses changed the title [spv-in] Fix bitcasts on non-scalars [glsl-out] Handle vector bitcasts Jun 13, 2022
src/back/glsl/mod.rs Outdated Show resolved Hide resolved
src/back/glsl/mod.rs Outdated Show resolved Hide resolved
Copy link
Member

@jimblandy jimblandy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs some test coverage. Snapshot tests that include a generated use of each of the GLSL functions in the output via this code should suffice, and that'll get the validator to check that it's valid.

@expenses expenses requested a review from jimblandy June 16, 2022 13:44
Copy link
Member

@jimblandy jimblandy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much for the tests - they look great.

I'm still concerned about code duplication. Could we go around one more time on this?

(Sk::Float, Sk::Uint) => "floatBitsToUint",
(Sk::Sint, Sk::Float) => "intBitsToFloat",
(Sk::Uint, Sk::Float) => "uintBitsToFloat",
let conv_op = match (source_kind, target_kind, vector_size) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like almost all of these match arms could be handled with a single default call to self.write_value_type(inner). I'd like to see if that works before we duplicate all those variations here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nice, that makes things super easy!

@expenses expenses requested a review from jimblandy June 17, 2022 13:45
Copy link
Member

@jimblandy jimblandy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good - thank you!

@jimblandy jimblandy merged commit ea832a9 into gfx-rs:master Jun 21, 2022
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