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

Implemented Procedural Texture (Texture Unit 3) #2697

Merged
merged 2 commits into from May 25, 2017

Conversation

Projects
None yet
4 participants
@wwylele
Copy link
Member

wwylele commented May 11, 2017

Credits to @fincs and @MerryMage

Implementation based on fincs' notes.

Hardware test
Here is a test written by fincs (binary). Note that this program need to be compiled using citro3d's "next" branch. You can change the parameters in the source code to test different modes and LUT. I will probably make a fully configurable testing program if requested.

Problems

  • There exists a mode involving 1D mipmaps for the final color LUT, however it hasn't been tested yet. Considering the low significance of it, I left it as TODO in citra.
  • PICA has a broken sqrt, which produces very inaccurate result for small numbers, and causes a little different output between 3ds and citra, for SqrtAdd2 and RMax combiner mode (can be seen at the most inner ring of the "wood" example above). I am not going to "fix" this because the difference is not easy to notice and it is giant PITA to emulate "a bug".

Fixed games:
Mario & Luigi: Paper Jam (issue #2213)
screenshot from 2017-05-05 15-55-04

The sea is rendered by procedural texture, which previously causes shader compilation failure because the bump map uses proctex.

Other test results are welcome. This PR is going to fix games that log Unknown op source 6, or have shader compilation failure due to using texture3 in bump map.


This change is Reviewable

@wwylele wwylele force-pushed the wwylele:proctex branch from d36bc1c to 4ab2c72 May 11, 2017

@Subv

This comment has been minimized.

Copy link
Member

Subv commented May 14, 2017

Reviewed 8 of 8 files at r1.
Review status: 8 of 14 files reviewed at latest revision, 2 unresolved discussions.


src/video_core/command_processor.cpp, line 473 at r1 (raw file):

        switch (regs.texturing.proctex_lut_config.ref_table.Value()) {
        case TexturingRegs::ProcTexLutTable::Noise:
            pt.noise_table[index % pt.noise_table.size()].raw = value;

Is it verified that this index wraps around?


src/video_core/swrasterizer/proctex.cpp, line 106 at r1 (raw file):

    }
    case ProcTexClamp::Pulse:
        if (coord < 0.5f)

Is 0.5 also treated as 1?


Comments from Reviewable

@Subv

This comment has been minimized.

Copy link
Member

Subv commented May 14, 2017

Reviewed 6 of 6 files at r2.
Review status: all files reviewed at latest revision, 3 unresolved discussions.


src/video_core/renderer_opengl/gl_rasterizer.cpp, line 1200 at r2 (raw file):

            glGetUniformLocation(shader->shader.handle, "proctex_noise_lut");
        if (uniform_proctex_noise_lut != -1) {
            glUniform1i(uniform_proctex_noise_lut, 10);

Mabye we should start using an enum for these texture ids, that'd be a different PR, though


Comments from Reviewable

@yuriks

This comment has been minimized.

Copy link
Member

yuriks commented May 15, 2017

Partial review, I haven't looked at the OpenGL bits yet.


Reviewed 8 of 8 files at r1.
Review status: all files reviewed at latest revision, 22 unresolved discussions.


src/video_core/command_processor.cpp, line 471 at r1 (raw file):

        auto& index = regs.texturing.proctex_lut_config.index;
        auto& pt = g_state.proctex;
        switch (regs.texturing.proctex_lut_config.ref_table.Value()) {

Add a blank line before this to make it more visible.


src/video_core/pica_state.h, line 31 at r1 (raw file):

    struct ProcTex {
        union Lut128Entry {
            // Used for raw access

This comment seem unnecessary. A u32 raw; entry in unions is a common idiom in the codebase, and the comment doesn't really explain anything over the variable name.


src/video_core/pica_state.h, line 37 at r1 (raw file):

            BitField<0, 12, u32> value; // 0.0.12 fixed point

            // Difference between two entry value. Used for efficient interpolation.

"entry values."


src/video_core/pica_state.h, line 40 at r1 (raw file):

difference
Opinion: I think "delta" is a better/less awkward word than "difference". But "difference" is simpler vocabulary so you might want to keep using it regardless.


src/video_core/pica_state.h, line 51 at r1 (raw file):

        };

        using Lut128 = std::array<Lut128Entry, 128>;

The name "Lut128" is kinda arbitrary... I think I'd get rid of this typedef and use arrays directly (like for the color LUTs) and rename the union to "ValueEntry", to mirror "ColorEntry".


src/video_core/regs_texturing.h, line 205 at r1 (raw file):

float1.5.10
Is this the only format used for 16-bit floats? We can probably just say it's a "float16" and then have a class to manipulate those similar to our float24 one.


src/video_core/swrasterizer/proctex.cpp, line 19 at r1 (raw file):

index
I think (someone correct me if I'm wrong) "index" is always used to refer to integers. A value from 0.0 to 1.0 would be a coordinate


src/video_core/swrasterizer/proctex.cpp, line 31 at r1 (raw file):

UnknownPRNG
Is it really unknown now, if it has been fully reversed already?


src/video_core/swrasterizer/proctex.cpp, line 31 at r1 (raw file):

// These function are used to generate random noise for procedural texture. Their results are
// verified against real hardware.
static int UnknownPRNG(int v) {

Change the parameter, return and table type to unsigned int. (This actually makes the divisions somewhat faster since they can be simplified to less bitwise operations.)


src/video_core/swrasterizer/proctex.cpp, line 32 at r1 (raw file):

// verified against real hardware.
static int UnknownPRNG(int v) {
    const std::array<int, 16> table{{0, 4, 10, 8, 4, 9, 7, 12, 5, 15, 13, 14, 11, 15, 2, 11}};

Make this static and constexpr (if you can)


src/video_core/swrasterizer/proctex.cpp, line 33 at r1 (raw file):

static int UnknownPRNG(int v) {
    const std::array<int, 16> table{{0, 4, 10, 8, 4, 9, 7, 12, 5, 15, 13, 14, 11, 15, 2, 11}};
    return ((v % 9 + 2) * 3 & 0xF) ^ table[(v / 9) & 0xF];

You could replace the first half with a table of length 9 ({6, 9, 12, 15, 2, 5, 8, 11, 14}), unless to preserve the somewhat arbitrary looking formula.


src/video_core/swrasterizer/proctex.cpp, line 36 at r1 (raw file):

}

static float NoiseRand(int x, int y) {

Also change the types to unsigned


src/video_core/swrasterizer/proctex.cpp, line 37 at r1 (raw file):

static float NoiseRand(int x, int y) {
    const std::array<int, 16> table{{10, 2, 15, 8, 0, 7, 4, 5, 5, 13, 2, 6, 13, 9, 3, 14}};

Make this static and constexpr (if you can)


src/video_core/swrasterizer/proctex.cpp, line 40 at r1 (raw file):

    int u2 = UnknownPRNG(x);
    int v2 = UnknownPRNG(y);
    v2 += ((u2 & 3) == 1) ? 4 : 0;

You could express this without the ternary as just ((u2 & 3) == 1) * 4. Up to you.


src/video_core/swrasterizer/proctex.cpp, line 69 at r1 (raw file):

    const float x0 = g0 * (1 - x_noise) + g1 * x_noise;
    const float x1 = g2 * (1 - x_noise) + g3 * x_noise;
    return x0 * (1 - y_noise) + x1 * y_noise;

Last 3 lines are bilinear interpolation. Factor this out into a function. There's also the Math::Lerp function you can use, which results in:

static float BilinearInterp(float s00, float s01, float s10, float s11, float s, float t) {
    float s0 = Lerp(s00, s01, s);
    float s1 = Lerp(s10, s11, s);
    return Lerp(s0, s1, t);
}

src/video_core/swrasterizer/proctex.cpp, line 177 at r1 (raw file):

    // Shift
    const float u_shift = ShiftCoord(u, v, regs.proctex.u_shift, regs.proctex.u_clamp);
    const float v_shift = ShiftCoord(v, u, regs.proctex.v_shift, regs.proctex.v_clamp);

This seems to be incorrect somehow. This modification of the test gives slightly different results between Citra and hardware.


src/video_core/swrasterizer/proctex.cpp, line 193 at r1 (raw file):

    const u32 offset = regs.proctex_lut_offset;
    const u32 width = regs.proctex_lut.width;
    const float index = offset + (lut_index * (width - 1));

I feel like "index" is especially confusing here. color_coord?


src/video_core/swrasterizer/proctex.h, line 12 at r1 (raw file):

/// Generates procedural texture color for the given coordinates
Math::Vec4<u8> ProcTex(float u, float v);

Pass in g_state.regs.texturing (or a more specific sub-struct if one exists) and g_state.proctex as parameters.


src/video_core/swrasterizer/rasterizer.cpp, line 339 at r1 (raw file):

            // sample procedural texture
            if (regs.texturing.main_config.texture3_enable) {

Did you check what's in the buffer if you try to use Source::Texture3 while this is disabled?


Comments from Reviewable

@yuriks

This comment has been minimized.

Copy link
Member

yuriks commented May 16, 2017

Took a look at the OpenGL commit too.


Reviewed 6 of 6 files at r2.
Review status: all files reviewed at latest revision, 23 unresolved discussions.


src/video_core/renderer_opengl/gl_rasterizer.cpp, line 1200 at r2 (raw file):

Previously, Subv (Sebastian Valle) wrote…

Mabye we should start using an enum for these texture ids, that'd be a different PR, though

+1, though the LUT textures might be replaced by something else (uniforms, etc.) soon™ (as soon as someone gets around to it).


src/video_core/renderer_opengl/gl_shader_gen.cpp, line 833 at r2 (raw file):

                                     // extracted as index_i = 127.0 and index_f = 1.0
    uint entry = texelFetch(lut, int(index_i), 0).r;
    float entry_difference = float(int(entry << 8U) >> 20U); // extract the signed difference

You should do this on the CPU and upload the LUT with 2 components instead. That way you're also free to use another data type for this instead of integer and skip some of the conversion in the return below.


Comments from Reviewable

@wwylele

This comment has been minimized.

Copy link
Member

wwylele commented May 18, 2017

Review status: all files reviewed at latest revision, 23 unresolved discussions.


src/video_core/command_processor.cpp, line 471 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

Add a blank line before this to make it more visible.

Done.


src/video_core/command_processor.cpp, line 473 at r1 (raw file):

Previously, Subv (Sebastian Valle) wrote…

Is it verified that this index wraps around?

Not verified. This was following the fog lut register implementation. I will change it to an assert instead (like the lighting lut one)


src/video_core/pica_state.h, line 31 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

This comment seem unnecessary. A u32 raw; entry in unions is a common idiom in the codebase, and the comment doesn't really explain anything over the variable name.

Removed. Was a copy pasta from lighting lut


src/video_core/pica_state.h, line 37 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

"entry values."

Done.


src/video_core/pica_state.h, line 40 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

difference
Opinion: I think "delta" is a better/less awkward word than "difference". But "difference" is simpler vocabulary so you might want to keep using it regardless.

"Delta" was actually the first word coming to my mind, but "difference" is already used for fog and lighting lut, so I don't want to break the convention.


src/video_core/pica_state.h, line 51 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

The name "Lut128" is kinda arbitrary... I think I'd get rid of this typedef and use arrays directly (like for the color LUTs) and rename the union to "ValueEntry", to mirror "ColorEntry".

Done.


src/video_core/regs_texturing.h, line 205 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

float1.5.10
Is this the only format used for 16-bit floats? We can probably just say it's a "float16" and then have a class to manipulate those similar to our float24 one.

Should be the only format and we already had the class for it. Fixed the comment


src/video_core/renderer_opengl/gl_shader_gen.cpp, line 833 at r2 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

You should do this on the CPU and upload the LUT with 2 components instead. That way you're also free to use another data type for this instead of integer and skip some of the conversion in the return below.

This was following the fog lut style. I agree to decode on CPU, but since we are going to do #2704, should I keep the same style so that we won't get confused when we change them all together? (Or this PR should wait for a final solution to the issue and I change it directly?)


src/video_core/swrasterizer/proctex.cpp, line 19 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

index
I think (someone correct me if I'm wrong) "index" is always used to refer to integers. A value from 0.0 to 1.0 would be a coordinate

Done.


src/video_core/swrasterizer/proctex.cpp, line 31 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

UnknownPRNG
Is it really unknown now, if it has been fully reversed already?

The result is proved fully correct, but the algorithm is not necessary the one used in 3ds, so I marked it as "unknown if this is the 3ds way". Do you have any suggestions on naming this?


src/video_core/swrasterizer/proctex.cpp, line 31 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

Change the parameter, return and table type to unsigned int. (This actually makes the divisions somewhat faster since they can be simplified to less bitwise operations.)

Done.


src/video_core/swrasterizer/proctex.cpp, line 32 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

Make this static and constexpr (if you can)

Done.


src/video_core/swrasterizer/proctex.cpp, line 33 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

You could replace the first half with a table of length 9 ({6, 9, 12, 15, 2, 5, 8, 11, 14}), unless to preserve the somewhat arbitrary looking formula.

This is not arbitrary looking to me... it is a simple linear formula which looks good to me


src/video_core/swrasterizer/proctex.cpp, line 36 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

Also change the types to unsigned

Done.


src/video_core/swrasterizer/proctex.cpp, line 37 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

Make this static and constexpr (if you can)

Done.


src/video_core/swrasterizer/proctex.cpp, line 40 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

You could express this without the ternary as just ((u2 & 3) == 1) * 4. Up to you.

I find the true is 1 trick hard to read, so I prefer the current one.


src/video_core/swrasterizer/proctex.cpp, line 69 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

Last 3 lines are bilinear interpolation. Factor this out into a function. There's also the Math::Lerp function you can use, which results in:

static float BilinearInterp(float s00, float s01, float s10, float s11, float s, float t) {
    float s0 = Lerp(s00, s01, s);
    float s1 = Lerp(s10, s11, s);
    return Lerp(s0, s1, t);
}

Done. Add the function to vector_math.h, where the Lerp lives


src/video_core/swrasterizer/proctex.cpp, line 193 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

I feel like "index" is especially confusing here. color_coord?

The lut_index should be actually coord. The index is an actual index that has its integer part representing an index into an array.


src/video_core/swrasterizer/proctex.h, line 12 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

Pass in g_state.regs.texturing (or a more specific sub-struct if one exists) and g_state.proctex as parameters.

Done.


src/video_core/swrasterizer/rasterizer.cpp, line 339 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

Did you check what's in the buffer if you try to use Source::Texture3 while this is disabled?

Checked, the color is pretty random. I am not going to emulate that weird color


Comments from Reviewable

@wwylele

This comment has been minimized.

Copy link
Member

wwylele commented May 18, 2017

Addressed most trivial issues


Review status: 6 of 15 files reviewed at latest revision, 23 unresolved discussions.


Comments from Reviewable

@wwylele wwylele force-pushed the wwylele:proctex branch from 9210284 to eac2e7d May 18, 2017

@wwylele

This comment has been minimized.

Copy link
Member

wwylele commented May 18, 2017

Review status: 6 of 15 files reviewed at latest revision, 23 unresolved discussions.


src/video_core/swrasterizer/proctex.cpp, line 106 at r1 (raw file):

Previously, Subv (Sebastian Valle) wrote…

Is 0.5 also treated as 1?

Just did hardware test. 0.5 is treated as 0, so I fixed here. The gl renderer already has 0.5->0. Sorry for inconsistency.


Comments from Reviewable

@wwylele wwylele force-pushed the wwylele:proctex branch from eac2e7d to 02100fd May 18, 2017

@wwylele

This comment has been minimized.

Copy link
Member

wwylele commented May 18, 2017

Review status: 6 of 15 files reviewed at latest revision, 23 unresolved discussions.


src/video_core/command_processor.cpp, line 473 at r1 (raw file):

Previously, wwylele (Weiyi Wang) wrote…

Not verified. This was following the fog lut register implementation. I will change it to an assert instead (like the lighting lut one)

Update: wrap around verified. Changed back to what it was.


Comments from Reviewable

@wwylele wwylele force-pushed the wwylele:proctex branch from 02100fd to 33beab1 May 18, 2017

@yuriks

This comment has been minimized.

Copy link
Member

yuriks commented May 19, 2017

Reviewed 2 of 2 files at r3, 7 of 7 files at r4.
Review status: all files reviewed at latest revision, 7 unresolved discussions.


src/video_core/renderer_opengl/gl_shader_gen.cpp, line 833 at r2 (raw file):

Previously, wwylele (Weiyi Wang) wrote…

This was following the fog lut style. I agree to decode on CPU, but since we are going to do #2704, should I keep the same style so that we won't get confused when we change them all together? (Or this PR should wait for a final solution to the issue and I change it directly?)

IMO do it now. It's not that big of a change anyway.


src/video_core/swrasterizer/proctex.cpp, line 31 at r1 (raw file):

Previously, wwylele (Weiyi Wang) wrote…

The result is proved fully correct, but the algorithm is not necessary the one used in 3ds, so I marked it as "unknown if this is the 3ds way". Do you have any suggestions on naming this?

If that's the intent with the name then I'm spell that out in the comment above (saying that the results are equivalent, but it's not known if the algorithm is the same). For the function name, maybe name this one NoiseRand1D, and the other one NoiseRand2D?


src/video_core/swrasterizer/proctex.cpp, line 33 at r1 (raw file):

Previously, wwylele (Weiyi Wang) wrote…

This is not arbitrary looking to me... it is a simple linear formula which looks good to me

Ok.


Comments from Reviewable

@wwylele

This comment has been minimized.

Copy link
Member

wwylele commented May 19, 2017

Review status: 11 of 15 files reviewed at latest revision, 6 unresolved discussions.


src/video_core/renderer_opengl/gl_shader_gen.cpp, line 833 at r2 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

IMO do it now. It's not that big of a change anyway.

Done.


src/video_core/swrasterizer/proctex.cpp, line 31 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

If that's the intent with the name then I'm spell that out in the comment above (saying that the results are equivalent, but it's not known if the algorithm is the same). For the function name, maybe name this one NoiseRand1D, and the other one NoiseRand2D?

Done.


Comments from Reviewable

@yuriks

This comment has been minimized.

Copy link
Member

yuriks commented May 19, 2017

Reviewed 1 of 1 files at r5, 3 of 3 files at r6.
Review status: all files reviewed at latest revision, 5 unresolved discussions.


src/video_core/renderer_opengl/gl_shader_gen.cpp, line 832 at r6 (raw file):

    float index_f = coord - index_i; // fract() cannot be used here because 128.0 needs to be
                                     // extracted as index_i = 127.0 and index_f = 1.0
    vec4 entry = texelFetch(lut, int(index_i), 0);

You can use a ".rg" swizzle similar to before, I think it makes it clearer you're only using 2 values.


Comments from Reviewable

@wwylele

This comment has been minimized.

Copy link
Member

wwylele commented May 19, 2017

Review status: 14 of 15 files reviewed at latest revision, 5 unresolved discussions.


src/video_core/renderer_opengl/gl_shader_gen.cpp, line 832 at r6 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

You can use a ".rg" swizzle similar to before, I think it makes it clearer you're only using 2 values.

Done.


Comments from Reviewable

@yuriks

This comment has been minimized.

Copy link
Member

yuriks commented May 19, 2017

Reviewed 1 of 1 files at r7.
Review status: all files reviewed at latest revision, 4 unresolved discussions.


Comments from Reviewable

@wwylele

This comment has been minimized.

Copy link
Member

wwylele commented May 19, 2017

Review status: all files reviewed at latest revision, 4 unresolved discussions.


src/video_core/swrasterizer/proctex.cpp, line 177 at r1 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

This seems to be incorrect somehow. This modification of the test gives slightly different results between Citra and hardware.

Fixed. The auxiliary coordinate should be without noise applied.


Comments from Reviewable

@wwylele wwylele force-pushed the wwylele:proctex branch from bced161 to 9bd00cb May 19, 2017

@yuriks

This comment has been minimized.

Copy link
Member

yuriks commented May 20, 2017

Reviewed 1 of 7 files at r8, 5 of 6 files at r9.
Review status: 14 of 15 files reviewed at latest revision, 4 unresolved discussions.


src/video_core/swrasterizer/proctex.cpp, line 81 at r9 (raw file):

    default:
        LOG_CRITICAL(HW_GPU, "Unknown shift mode %u", static_cast<u32>(mode));
        return u;

Instead of always summing u here and returning that, you can instead return the amount of shift to apply (or 0). Then below you can calculate the u_shift/v_shift before the noise, and just apply it afterwards. Makes the code look somewhat nicer imo.


Comments from Reviewable

@yuriks

This comment has been minimized.

Copy link
Member

yuriks commented May 20, 2017

Yup, output seems to match now!


Reviewed 1 of 6 files at r9.
Review status: all files reviewed at latest revision, 3 unresolved discussions.


src/video_core/swrasterizer/proctex.cpp, line 81 at r9 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

Instead of always summing u here and returning that, you can instead return the amount of shift to apply (or 0). Then below you can calculate the u_shift/v_shift before the noise, and just apply it afterwards. Makes the code look somewhat nicer imo.

But well, the code also looks good enough as-is, so up to you really.


Comments from Reviewable

@wwylele wwylele force-pushed the wwylele:proctex branch from 9bd00cb to 4d62e75 May 20, 2017

@wwylele

This comment has been minimized.

Copy link
Member

wwylele commented May 20, 2017

Review status: 8 of 15 files reviewed at latest revision, 4 unresolved discussions.


src/video_core/swrasterizer/proctex.cpp, line 81 at r9 (raw file):

Previously, yuriks (Yuri Kunde Schlesner) wrote…

But well, the code also looks good enough as-is, so up to you really.

Done.


Comments from Reviewable

@yuriks

This comment has been minimized.

Copy link
Member

yuriks commented May 20, 2017

Reviewed 1 of 7 files at r10, 6 of 6 files at r11.
Review status: all files reviewed at latest revision, 3 unresolved discussions.


Comments from Reviewable

@Subv

This comment has been minimized.

Copy link
Member

Subv commented May 21, 2017

Reviewed 4 of 7 files at r4.
Review status: all files reviewed at latest revision, 2 unresolved discussions.


Comments from Reviewable

@yuriks

This comment has been minimized.

Copy link
Member

yuriks commented May 25, 2017

Is this waiting on anything? Can we merge it?

@wwylele

This comment has been minimized.

Copy link
Member

wwylele commented May 25, 2017

I am just waiting for merge

@yuriks yuriks merged commit bae3799 into citra-emu:master May 25, 2017

2 of 3 checks passed

code-review/reviewable 2 discussions left (Subv)
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@yuriks

This comment has been minimized.

Copy link
Member

yuriks commented May 25, 2017

Guess you're not waiting anymore then.

@wwylele wwylele deleted the wwylele:proctex branch May 25, 2017

@turbedi

This comment has been minimized.

Copy link

turbedi commented May 25, 2017

Does this fix #1858 and #1521 ?

@jroweboy jroweboy referenced this pull request Jun 27, 2017

Merged

Progress Report 2017 June #29

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment