Skip to content

Conversation

Copy link

Copilot AI commented Feb 11, 2026

Several RenderState setters modify fields included in contentHashCode() but fail to invalidate the cached hash, causing stale hash values when objects are used in collections or equality checks.

Changes

  • Stencil setters: Added cachedHashCode = -1 to:

    • setFrontStencilMask()
    • setBackStencilMask()
    • setFrontStencilReference()
    • setBackStencilReference()
  • Face cull flip: Updated flipFaceCull() to call setFaceCullMode() instead of directly mutating cullMode, ensuring hash invalidation

  • Test coverage: Added testHashInvalidation() to verify hash invalidation for all modified setters

Pattern

All changes follow the existing pattern used by other setters:

public void setColorWrite(boolean colorWrite) {
    applyColorWrite = true;
    this.colorWrite = colorWrite;
    cachedHashCode = -1;  // Invalidate cached hash
}

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • dl.google.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED -XX:MaxMetaspaceSize=384m -XX:+HeapDumpOnOutOfMemoryError -Xms256m -Xmx512m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-8.8-bin/dl7vupf4psengwqhwktix4v1/gradle-8.8/lib/gradle-launcher-8.8.jar -javaagent:/home/REDACTED/.gradle/wrapper/dists/gradle-8.8-bin/dl7vupf4psengwqhwktix4v1/gradle-8.8/lib/agents/gradle-instrumentation-agent-8.8.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>RenderState: Setters Missing Hash Invalidation</issue_title>
<issue_description>The following fields are part of the contentHashCode() computation:

hash = 79 * hash + this.frontStencilMask;
hash = 79 * hash + this.frontStencilReference;
hash = 79 * hash + this.backStencilMask;
hash = 79 * hash + this.backStencilReference;

However, their corresponding setters do not set cachedHashCode = -1:

public void setFrontStencilMask(int frontStencilMask) {
    this.frontStencilMask = frontStencilMask;
}

public void setBackStencilMask(int backStencilMask) {
    this.backStencilMask = backStencilMask;
}

public void setFrontStencilReference(int frontStencilReference) {
    this.frontStencilReference = frontStencilReference;
}

public void setBackStencilReference(int backStencilReference) {
    this.backStencilReference = backStencilReference;
}

Since these fields directly contribute to the hash, modifying them without invalidating the cached hash results in an inconsistent RenderState.

Expected Fix
Each setter should follow the same pattern used in correctly implemented methods such as setColorWrite:

public void setColorWrite(boolean colorWrite) {
    applyColorWrite = true;
    this.colorWrite = colorWrite;
    cachedHashCode = -1;
}

This ensures that contentHashCode() always reflects the actual state of the object.

Edit:
Additionally, RenderState.flipFaceCull() should be updated to call RenderState.setFaceCullMode(FaceCullMode) so that cull changes also invalidate the cached hash.

    /**
     * Toggles the current face culling mode between {@code Front} and {@code Back}.
     * <p>
     * This method inverts the culling direction: {@code Back → Front} and
     * {@code Front → Back}. Other modes ({@code Off} and {@code FrontAndBack})
     * are left unchanged.
     * <p>
     * Useful when geometry is discovered to have reversed normals and the
     * culling orientation must be corrected at runtime.
     */
    public void flipFaceCull() {
        switch (cullMode) {
            case Back:
                cullMode = FaceCullMode.Front;
                break;
            case Front:
                cullMode = FaceCullMode.Back;
                break;
        }
    }

</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: riccardobl <4943530+riccardobl@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix missing hash invalidation in RenderState setters Fix RenderState hash invalidation in stencil setters and flipFaceCull Feb 11, 2026
Copilot AI requested a review from riccardobl February 11, 2026 19:35
@riccardobl riccardobl marked this pull request as ready for review February 11, 2026 19:36
@github-actions
Copy link

🖼️ Screenshot tests have failed.

The purpose of these tests is to ensure that changes introduced in this PR don't break visual features. They are visual unit tests.

📄 Where to find the report:

  • Go to the (failed run) > Summary > Artifacts > screenshot-test-report
  • Download the zip and open jme3-screenshot-tests/build/reports/ScreenshotDiffReport.html

⚠️ If you didn't expect to change anything visual:
Fix your changes so the screenshot tests pass.

If you did mean to change things:
Review the replacement images in jme3-screenshot-tests/build/changed-images to make sure they really are improvements and then replace and commit the replacement images at jme3-screenshot-tests/src/test/resources.

If you are creating entirely new tests:
Find the new images in jme3-screenshot-tests/build/changed-images and commit the new images at jme3-screenshot-tests/src/test/resources.

Note; it is very important that the committed reference images are created on the build pipeline, locally created images are not reliable. Similarly tests will fail locally but you can look at the report to check they are "visually similar".

See https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-screenshot-tests/README.md for more information

Contact @richardTingle (aka richtea) for guidance if required

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.

RenderState: Setters Missing Hash Invalidation

2 participants