Class IrisRenderBatch
- All Implemented Interfaces:
AutoCloseable
-
Method Summary
Modifier and TypeMethodDescriptionstatic IrisRenderBatchactive()static IrisRenderBatchbegin(boolean shadowPass, org.joml.Matrix4f projectionMatrix) Opens a batch session for the given pass.voidclose()static voidCloses any persistent batch (shadow or main) still active at end-of-frame.voiddrawCompanion(IrisCompanionMesh companion, org.joml.Matrix4f modelView, int packedLight) Issues a single draw using the active batch shader.voiddrawCompanionWithPerVertexLight(IrisCompanionMesh companion, org.joml.Matrix4f modelView, float[] cornerUV16, int packedLightFallback) Variant ofdrawCompanion(IrisCompanionMesh, Matrix4f, int)that uses per-vertex lightmap UV2 derived by trilinear interpolation from the 8 world-space corner samples incornerUV16.voiddrawCompanionWithSlicedPerVertexLight(IrisCompanionMesh companion, org.joml.Matrix4f modelView, float[] probeUV32, int packedLightFallback) Per-vertex path for tall meshes that use a 2×4×2 world probe lattice (LightSampleCache.getOrSample16(net.minecraft.world.level.block.entity.BlockEntity, long, float[], net.minecraft.core.BlockPos, org.joml.Matrix4f, int, float[])→float[32]), matching the vanilla VBO / instanced-sliced path underUSE_SLICED_LIGHT.static voidDrops cached uniform handles.static booleanisActive()booleanWhether this batch is rendering into Iris's shadow pass.static voidrunVanillaOverlay(Runnable draw) Runs a short vanilla draw (recipe icon, item BER overlay) while a persistent Iris batch is open.
-
Method Details
-
active
- Returns:
- the currently-open batch, or
nullif no batch is active.
-
isActive
public static boolean isActive()- Returns:
trueif a batch session is currently open. Whentrueper-part renderers should calldrawCompanion(com.hbm_m.client.render.IrisCompanionMesh, org.joml.Matrix4f, int)onactive()instead of running their full standaloneapply/clearpath.
-
begin
Opens a batch session for the given pass. Returnsnullif no usable IrisExtendedShadercould be resolved (e.g. shader pack disabled, Iris not loaded, reflection failed) - in which case the caller MUST fall back to per-call rendering instead of relying ondrawCompanion(com.hbm_m.client.render.IrisCompanionMesh, org.joml.Matrix4f, int).Both passes batched. Shadow AND main pass each open one persistent batch per frame. The returned handle is always
NOOP_NESTEDon success — the caller's try-with-resources is decorative; the underlying batch outlives it. Subsequent BEs in the same pass piggyback on the sameshader.apply()viaactive(). The batch is torn down when:- a later
begin(...)call's pass differs from the active batch'sisShadowPass— typical case is the shadow→main transition inside one frame, but it also handles the rare (debug-paused / single-stepped) main→shadow inverse, or closePersistentIfActive()fires atAFTER_LEVEL— the safety net for the LAST batch of every frame (which has no follow-up begin() this frame to trigger pass-change close).
apply()/clear()pairs into exactly TWO per frame total (one shadow, one main) regardless of machine count. On a 400-machine farm under BSL the savings dominate the per-pass CPU budget — Iris'sapply()is the single most expensive call on this path because it binds the framebuffer, pushes every CustomUniform, and re-binds every sampler.Per-draw work is still issued eagerly inside
drawCompanion(com.hbm_m.client.render.IrisCompanionMesh, org.joml.Matrix4f, int)(see the field-level note onisPersistentfor why deferred sort-by-VAO flushes are unsafe).- Parameters:
shadowPass- whether we are inside Iris's shadow pass - selectsSHADOW_*variants of the entity shaderprojectionMatrix- projection matrix to upload once into the shader
- a later
-
closePersistentIfActive
public static void closePersistentIfActive()Closes any persistent batch (shadow or main) still active at end-of-frame. Called fromRenderLevelStageEvent.AFTER_LEVELas the safety net for the LAST batch of every frame — its pass-change close inbegin(boolean, org.joml.Matrix4f)never fires because no follow-up begin() happens this frame. Also covers leak-into-next-frame edge cases (e.g. player turned away so no main BE dispatch but shadow camera still captured them). -
isShadowPass
public boolean isShadowPass()Whether this batch is rendering into Iris's shadow pass. Lets callers skip the expensive 8-cornerLightSampleCachesampling and thewriteInstanceLightmap/uploadLightmapRangepair that produces no visible output in shadow (depth-only) but dominates the frame's CPU profile and poisons the light cache with shadow-camera state. Use together withcom.hbm_m.client.render.compat.ShaderCompatibilityDetector#isRenderingShadowPass()when no batch is active. -
runVanillaOverlay
Runs a short vanilla draw (recipe icon, item BER overlay) while a persistent Iris batch is open. Re-applies the batch shader afterward so the nextdrawCompanion(com.hbm_m.client.render.IrisCompanionMesh, org.joml.Matrix4f, int)still hits the correct program. -
drawCompanion
public void drawCompanion(IrisCompanionMesh companion, org.joml.Matrix4f modelView, int packedLight) Issues a single draw using the active batch shader. Updates only the per-instance uniforms (ModelViewMat,iris_ModelViewMatInverse,iris_NormalMat) and the per-draw lightmap UV2 attribute constant.Must be called from within a
begin(boolean, org.joml.Matrix4f)/close()pair on the OUTER batch returned byactive(). The work happens eagerly under the caller's still-bound shader program — deferring to teardown is unsafe because Iris swaps framebuffer + program between shadow and main passes before our lazyactuallyClose()runs. -
drawCompanionWithPerVertexLight
public void drawCompanionWithPerVertexLight(IrisCompanionMesh companion, org.joml.Matrix4f modelView, float[] cornerUV16, int packedLightFallback) Variant ofdrawCompanion(IrisCompanionMesh, Matrix4f, int)that uses per-vertex lightmap UV2 derived by trilinear interpolation from the 8 world-space corner samples incornerUV16.The companion mesh must support the per-vertex lightmap path (
IrisCompanionMesh.supportsPerVertexLightmap()) — it bakes trilinear weights per vertex at build time so this call only pays the per-instance combine + singleglBufferSubData. When the mesh doesn't support it (build failed, unusual vertex format) we fall back transparently to the legacy constant-UV2 path usingpackedLightFallback.Why this is the right default under Iris: pack shaders read
vaUV2per vertex anyway, so supplying per-vertex values gives a smooth in-mesh gradient at zero GPU cost over the constant-UV2 path — we only trade a few dozen kilobytes of per-frame CPU arithmetic for proper block-light response across multi-block machines. A torch on one side of an Advanced Assembler now visibly brightens just that side.- Parameters:
companion- the companion mesh to draw (must be built)modelView- per-instance ModelView (same as the constant path);iris_ModelViewMatInverse/iris_NormalMatare derived from itcornerUV16-[c0.blockU, c0.skyV, c1.blockU, ... c7.skyV]— 16 floats, typically produced byLightSampleCache.getOrSample8packedLightFallback- packed light to use when the per-vertex path can't run (companion mesh doesn't support it); ignored on the happy path
-
drawCompanionWithSlicedPerVertexLight
public void drawCompanionWithSlicedPerVertexLight(IrisCompanionMesh companion, org.joml.Matrix4f modelView, float[] probeUV32, int packedLightFallback) Per-vertex path for tall meshes that use a 2×4×2 world probe lattice (LightSampleCache.getOrSample16(net.minecraft.world.level.block.entity.BlockEntity, long, float[], net.minecraft.core.BlockPos, org.joml.Matrix4f, int, float[])→float[32]), matching the vanilla VBO / instanced-sliced path underUSE_SLICED_LIGHT.When the mesh has no
sliced weights, fall back todrawCompanionWithPerVertexLight(com.hbm_m.client.render.IrisCompanionMesh, org.joml.Matrix4f, float[], int)(8 corners) ordrawCompanion(com.hbm_m.client.render.IrisCompanionMesh, org.joml.Matrix4f, int). -
close
public void close()- Specified by:
closein interfaceAutoCloseable
-
invalidateCaches
public static void invalidateCaches()Drops cached uniform handles. Call after a shader pipeline rebuild (F3+T, shader pack swap) so the nextbegin(boolean, org.joml.Matrix4f)re-resolves them against the fresh program ID. Also force-closes any leftover persistent shadow batch so we never reuse a batch built against a now-deleted shader program.
-