mojira.dev
MC-280125

Shader target buffers no longer saved between frames

post_effect shader target buffers are no longer saved between frames.

To prove this point, I've attached a resource pack. This pack renders green when the previous frame contained data in the shader target buffer, and red when the buffer is not initialized (all zeros). 

Steps to reproduce:

  • Launch the game in 1.21.4

  • Apply the provided resource pack with fabulous graphics settings on

  • Observe that the screen renders green (explanation for why below)

 

  • Close the game and relaunch in 25w06a

  • Apply the resource pack in the same way above

  • Observe that the screen renders red (explanation for why below)

 

Explanation:

In the post_effect 'transparency.json', the buffer named 'buffer' is copied to a secondary temporary buffer named 'buffer_copy'. This 'buffer_copy' is handed to the 'update_buffer' shader with the sampler name 'InSampler'.

here is a sample of the 'transparency.json' post_effect demonstrating what was outlined above

{
    "targets": {
        "buffer": {
            "width": 2,
            "height": 7
        },
        "buffer_copy": {
            "width": 2,
            "height": 7
        },
        ... // hidden since its irrelevant to this explanation.
    },
    "passes": [
        {
            "program": "minecraft:test/copy", // custom "blit" shader to copy buffers of different sizes
            "inputs": [
                {
                    "sampler_name": "In",
                    "target": "buffer"
                }
            ],
            "output": "buffer_copy"
        },
        {
            "program": "minecraft:test/updatebuffer",
            "inputs": [
                {
                    "sampler_name": "In",
                    "target": "buffer_copy"
                }
            ],
            "output": "buffer"
        },
        ... // vanilla implementation and rendering of the shader buffer
    ]
}

As you can see, the contents of the 'buffer' target are copied to 'buffer_copy' and then used as an input for the 'update_buffer' shader pass. This pass outputs back to the original 'buffer' target.

below is the code present in the 'update_buffer.fsh' which utilizes the 'buffer_copy' as 'InSampler'

#version 150

uniform sampler2D InSampler;

in vec2 texCoord;

out vec4 fragColor;

void main() {
    vec4 lastColor = texture(InSampler, texCoord);

    if(lastColor == vec4(0))
        fragColor = vec4(1, 0, 0, 1);
    else
        fragColor = vec4(0, 1, 0, 1);
}

The shader code samples the color of the previous value stored in 'buffer_copy', and then passes this value back to the original 'buffer'. if that value is the default initialized value of vec4(0) then the if statement present in the code will set the screen color to red. Assuming that the buffer was updated to the color red in the last frame and the buffers are saved between frames, then one can also assume that the if statement on any following frame will fail, and the screen will be colored green.

 

Expected Result: When loading this resource pack in 25w02a and above, the shader is expected to behave the same as it did in 1.21.4. There were no changes stated in the snapshot changelog relating to post_effect shader passes, so one can expect the shader target buffers to remain continuous between frames.
Actual Result (Bug): The resource pack does not behave the same as it did in the prior game release 1.21.4, and the shader target buffer resets at the start of the shader post_effect pass.

 

 

Linked issues

Attachments

Comments 6

Can confirm. This is also related to an existing issue, where the game would reset a target if it shared the same size as other targets, even if the post effect relies on the target being preserved for the next frame.

This kind of preservation seems to have been an intended feature rather than an accident, since the old phosphor.json post effect that used to be part of the vanilla resource pack also made use of it and got broken in recent versions, and with the current bug, has become impossible to implement.

It should be possible for the game to automatically recognize which targets rely on being preserved from the previous frame, simply by testing which targets have passes that read from them without there existing previous passes that write to the target.

Thank you for your report!
After consideration, the issue is being closed as Invalid.

This report does not describe a bug.

Quick Links:
📓 Bug Tracker Guidelines – 💬 Community Support – 📧 Mojang Support (Technical Issues) – 📧 Microsoft Support (Account Issues)
📓 Project Summary – ✍️ Feedback and Suggestions – 📖 Game Wiki

This wasn't mentioned in the 25w02a change log (technical section) as far as I can see and so it describes a feature that has unexpectedly (and perhaps mistakenly) broken/changed with no mention.

If it IS intentional, shouldn't this be WAI instead of outright invalid?

I would agree that this was mistakenly resolved as invalid. The resource pack provided perfectly outlines the problem when loaded in the 2 versions written in the description. There was no mention of this change in the snapshot where the problem began. 

At the time of my writing this, 8 users have voted for the issue and 6 have begun watching it.  To me, it seems that others also agree that this is a bug and would like it resolved just as I do. 

Please reconsider this report, and reopen the issue. 

Thanks

I've gone ahead and modified the description to better explain the bug and the steps on how to reproduce it. Hopefully, this matches the bug report guidelines that we are all used to seeing.

The change described in this report was intentional, and was made for performance reasons. So getting back this functionality is now a feature request. It is a reasonable feature request, and we might reintroduce the support for not clearing the targets in the future. No promises, though.

RitzKid76

(Unassigned)

Community Consensus

Rendering

rendering

25w06a

Retrieved