66import com .gtnewhorizons .angelica .mixins .interfaces .ITexturesCache ;
77import com .gtnewhorizons .angelica .rendering .AngelicaBlockSafetyRegistry ;
88import com .gtnewhorizons .angelica .rendering .AngelicaRenderQueue ;
9+ import it .unimi .dsi .fastutil .longs .LongArrayFIFOQueue ;
910import me .jellysquid .mods .sodium .client .SodiumClientMod ;
1011import me .jellysquid .mods .sodium .client .render .chunk .ChunkGraphicsState ;
1112import me .jellysquid .mods .sodium .client .render .chunk .ChunkRenderContainer ;
@@ -89,7 +90,7 @@ private boolean rendersOutsideBoundingBox(TileEntity entity, int baseX, int base
8990
9091 private boolean rendersOffThread (Block block ) {
9192 final int type = block .getRenderType ();
92- return type < 42 && type != 22 && AngelicaBlockSafetyRegistry .canBlockRenderOffThread (block );
93+ return ( type < 42 && type != 22 && AngelicaBlockSafetyRegistry .canBlockRenderOffThread (block , false )) || AngelicaBlockSafetyRegistry . canBlockRenderOffThread ( block , true );
9394 }
9495
9596 private void handleRenderBlocksTextures (RenderBlocks rb , ChunkRenderData .Builder builder ) {
@@ -104,7 +105,6 @@ private void handleRenderBlocksTextures(RenderBlocks rb, ChunkRenderData.Builder
104105
105106 @ Override
106107 public ChunkBuildResult <T > performBuild (ChunkRenderCacheLocal cache , ChunkBuildBuffers buffers , CancellationSource cancellationSource ) {
107- // COMPATIBLITY NOTE: Oculus relies on the LVT of this method being unchanged, at least in 16.5
108108 final ChunkRenderData .Builder renderData = new ChunkRenderData .Builder ();
109109 final ChunkOcclusionDataBuilder occluder = new ChunkOcclusionDataBuilder ();
110110 final ChunkRenderBounds .Builder bounds = new ChunkRenderBounds .Builder ();
@@ -120,9 +120,10 @@ public ChunkBuildResult<T> performBuild(ChunkRenderCacheLocal cache, ChunkBuildB
120120 final int baseY = this .render .getOriginY ();
121121 final int baseZ = this .render .getOriginZ ();
122122
123- final BlockPos . Mutable pos = new BlockPos . Mutable ();
123+ final BlockPos pos = new BlockPos ();
124124 final BlockPos renderOffset = this .offset ;
125125
126+ final LongArrayFIFOQueue mainThreadBlocks = new LongArrayFIFOQueue ();
126127 boolean hasMainThreadBlocks = false ;
127128
128129 for (int relY = 0 ; relY < 16 ; relY ++) {
@@ -160,6 +161,7 @@ public ChunkBuildResult<T> performBuild(ChunkRenderCacheLocal cache, ChunkBuildB
160161 }
161162 }
162163 } else {
164+ mainThreadBlocks .enqueue (pos .asLong ());
163165 hasMainThreadBlocks = true ;
164166 }
165167
@@ -200,7 +202,7 @@ public ChunkBuildResult<T> performBuild(ChunkRenderCacheLocal cache, ChunkBuildB
200202 if (hasMainThreadBlocks ) {
201203 // Render the other blocks on the main thread
202204 try {
203- CompletableFuture .runAsync (() -> this .performMainBuild (cache , buffers , cancellationSource , bounds , renderData ), AngelicaRenderQueue .executor ()).get ();
205+ CompletableFuture .runAsync (() -> this .performMainBuild (cache , buffers , cancellationSource , bounds , renderData , mainThreadBlocks ), AngelicaRenderQueue .executor ()).get ();
204206 } catch (InterruptedException e ) {
205207 Thread .currentThread ().interrupt ();
206208 return null ;
@@ -230,54 +232,51 @@ public ChunkBuildResult<T> performBuild(ChunkRenderCacheLocal cache, ChunkBuildB
230232
231233 /**
232234 * Render the blocks that should be rendered on the main thread.
233- *
234- * TODO: Deduplicate this with the main method above.
235235 */
236- private void performMainBuild (ChunkRenderCacheLocal cache , ChunkBuildBuffers buffers , CancellationSource cancellationSource , ChunkRenderBounds .Builder bounds , ChunkRenderData .Builder renderData ) {
236+ private void performMainBuild (ChunkRenderCacheLocal cache , ChunkBuildBuffers buffers , CancellationSource cancellationSource , ChunkRenderBounds .Builder bounds , ChunkRenderData .Builder renderData , LongArrayFIFOQueue mainThreadBlocks ) {
237237 final WorldSlice slice = cache .getWorldSlice ();
238- final BlockPos . Mutable pos = new BlockPos . Mutable ();
238+ final BlockPos pos = new BlockPos ();
239239 final int baseX = this .render .getOriginX ();
240240 final int baseY = this .render .getOriginY ();
241241 final int baseZ = this .render .getOriginZ ();
242242 final BlockPos renderOffset = this .offset ;
243243 final RenderBlocks rb = new RenderBlocks (slice .getWorld ());
244- for (int relY = 0 ; relY < 16 ; relY ++) {
244+ while (!mainThreadBlocks .isEmpty ()) {
245+ final long longPos = mainThreadBlocks .dequeueLong ();
245246 if (cancellationSource .isCancelled ()) {
246247 return ;
247248 }
248- for (int relZ = 0 ; relZ < 16 ; relZ ++) {
249- for (int relX = 0 ; relX < 16 ; relX ++) {
250- final Block block = slice .getBlockRelative (relX + 16 , relY + 16 , relZ + 16 );
249+ pos .set (longPos );
250+ final int relX = pos .getX () - baseX ;
251+ final int relY = pos .getY () - baseY ;
252+ final int relZ = pos .getZ () - baseZ ;
253+ final Block block = slice .getBlockRelative (relX + 16 , relY + 16 , relZ + 16 );
254+
255+ // Only render blocks that need main thread assistance
256+ if (block .getMaterial () == Material .air || rendersOffThread (block )) {
257+ continue ;
258+ }
251259
252- // Only render blocks that need main thread assistance
253- if (block .getMaterial () == Material .air || rendersOffThread (block )) {
254- continue ;
255- }
260+ // TODO: Collect data on which render types are hitting this code path most often so mods can be updated slowly
256261
257- // TODO: Collect data on which render types are hitting this code path most often
258- // so mods can be updated slowly
262+ final int meta = slice .getBlockMetadataRelative (relX + 16 , relY + 16 , relZ + 16 );
259263
260- final int meta = slice .getBlockMetadataRelative (relX + 16 , relY + 16 , relZ + 16 );
264+ buffers .setRenderOffset (pos .x - renderOffset .getX (), pos .y - renderOffset .getY (), pos .z - renderOffset .getZ ());
265+ if (AngelicaConfig .enableIris ) buffers .iris$setLocalPos (relX , relY , relZ );
261266
262- pos .set (baseX + relX , baseY + relY , baseZ + relZ );
263- buffers .setRenderOffset (pos .x - renderOffset .getX (), pos .y - renderOffset .getY (), pos .z - renderOffset .getZ ());
264- if (AngelicaConfig .enableIris ) buffers .iris$setLocalPos (relX , relY , relZ );
267+ // Do regular block rendering
268+ for (BlockRenderPass pass : BlockRenderPass .VALUES ) {
269+ if (block .canRenderInPass (pass .ordinal ()) && (!AngelicaConfig .enableSodiumFluidRendering || !(block instanceof IFluidBlock ))) {
270+ final long seed = MathUtil .hashPos (pos .x , pos .y , pos .z );
271+ if (AngelicaConfig .enableIris ) buffers .iris$setMaterialId (block , ExtendedDataHelper .BLOCK_RENDER_TYPE );
265272
266- // Do regular block rendering
267- for (BlockRenderPass pass : BlockRenderPass .VALUES ) {
268- if (block .canRenderInPass (pass .ordinal ()) && (!AngelicaConfig .enableSodiumFluidRendering || !(block instanceof IFluidBlock ))) {
269- final long seed = MathUtil .hashPos (pos .x , pos .y , pos .z );
270- if (AngelicaConfig .enableIris ) buffers .iris$setMaterialId (block , ExtendedDataHelper .BLOCK_RENDER_TYPE );
271-
272- if (cache .getBlockRenderer ().renderModel (slice .getWorld (), rb , block , meta , pos , buffers .get (pass ), true , seed )) {
273- bounds .addBlock (relX , relY , relZ );
274- }
275- }
273+ if (cache .getBlockRenderer ().renderModel (slice .getWorld (), rb , block , meta , pos , buffers .get (pass ), true , seed )) {
274+ bounds .addBlock (relX , relY , relZ );
276275 }
277-
278- if (AngelicaConfig .enableIris ) buffers .iris$resetBlockContext ();
279276 }
280277 }
278+
279+ if (AngelicaConfig .enableIris ) buffers .iris$resetBlockContext ();
281280 }
282281
283282 handleRenderBlocksTextures (rb , renderData );
0 commit comments