Skip to content
This repository has been archived by the owner on Oct 22, 2020. It is now read-only.

Fully implement structured control flow #8

Open
MaikKlein opened this issue Feb 8, 2018 · 7 comments
Open

Fully implement structured control flow #8

MaikKlein opened this issue Feb 8, 2018 · 7 comments

Comments

@MaikKlein
Copy link
Owner

No description provided.

@MaikKlein
Copy link
Owner Author

MaikKlein commented Mar 3, 2018

#[spirv(fragment)]
fn color_frag(
    frag: Fragment,
    uv: Input<N0, Vec2<f32>>,
    time: Descriptor<N2, N0, f32>,
) -> Output<N0, Vec4<f32>> {
    let uv = uv.data;
    // let mut time = time.data;
    let offset = Vec3::new(0.0f32, 2.0, 4.0);
    let right = uv.x > 0.5;
    let top = uv.y > 0.5;

    let color: Vec3<f32> = match (right, top) {
        (true, true) => Vec3::new(0.0, 0.0, 1.0),
        (true, false) => Vec3::new(0.0, 1.0, 0.0),
        (false, true) => Vec3::new(1.0, 0.0, 0.0),
        (false, false) => Vec3::new(1.0, 1.0, 1.0),
    };

    Output::new(color.extend(1.0))
}

This results in the following CFG
cfg

Three branches which all converge into bb7. The dashed lines here are the merge blocks. While 30 is the "correct" merge block, in spir-v all merge blocks have to be unique.

To address this issue we need to generate new blocks for:

bb1, bb2 -> bb8 -> bb7  

bb3, bb4 -> bb9 -> bb7 

bb0 -> bb10 -> bb7

And the new control flow node should be

bb5 => bb8

bb6 => bb9

bb0 => bb10

@MaikKlein
Copy link
Owner Author

MaikKlein commented Mar 3, 2018

cfg
76c1d30

@MaikKlein
Copy link
Owner Author

A more complex example

@MaikKlein
Copy link
Owner Author

MaikKlein commented Mar 4, 2018

Interestingly a very simple branch doesn't work.


#[spirv(fragment)]
fn color_frag(
    frag: Fragment,
    uv: Input<N0, Vec2<f32>>,
    time: Descriptor<N2, N0, f32>,
) -> Output<N0, Vec4<f32>> {
    let uv = uv.data;
    let mut color = Vec3::new(1.0, 1.0, 0.0);
    if uv.x > 0.5 {
        color.x = 0.5;
    }

    Output::new(color.extend(1.0))
}

It crashes in Vulkan.
Adding the else branch fixes it.

#[spirv(fragment)]
fn color_frag(
    frag: Fragment,
    uv: Input<N0, Vec2<f32>>,
    time: Descriptor<N2, N0, f32>,
) -> Output<N0, Vec4<f32>> {
    let uv = uv.data;
    let mut color = Vec3::new(1.0, 1.0, 0.0);
    if uv.x > 0.5 {
        color.x = 0.5;
    }
    } else {
        color.x = 0.5;
    }
    Output::new(color.extend(1.0))
}


I am not yet sure which rule I am violating.

@MaikKlein
Copy link
Owner Author

After some testing it seems the problem is the OpSwitchinstruction. Switching to OpBranchConditional fixes the problem. This might be a driver problem.

@MaikKlein
Copy link
Owner Author

The current implementation seems to break for the ? operator on options. It produces where weird looking cfgs

@MaikKlein
Copy link
Owner Author

It seems rlsl doesn't correctly handle unwind and resume.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant