Ensure task queue is not locked during rendering (fixes #157)
Similar to 3fedc22 in effect and cause. However tasks are executed, they just
cannot be submitted pre-1.14 because MC would continuously hold the lock on the
scheduledTasks queue for the entire renderVideo call.
This commit is contained in:
@@ -475,13 +475,30 @@ public class ReplayMod implements
|
|||||||
public final ReplayModExecutor executor = new ReplayModExecutor("Client/ReplayMod");
|
public final ReplayModExecutor executor = new ReplayModExecutor("Client/ReplayMod");
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
|
// Pre-1.14 MC would hold the lock on the scheduledTasks queue while executing its tasks
|
||||||
|
// such that no new tasks could be submitted while one of them was running.
|
||||||
|
// This would cause issues with long-running tasks (e.g. video rendering) as it would
|
||||||
|
// block all async tasks (e.g. skin loading).
|
||||||
|
public void runLaterWithoutLock(Runnable runnable) {
|
||||||
|
//#if MC>=11400
|
||||||
|
// MC 1.14+ no longer synchronizes on the queue while running its tasks
|
||||||
|
runLater(runnable);
|
||||||
|
//#else
|
||||||
|
//$$ runLater(() -> runLaterWithoutLock(runnable), runnable);
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
public void runLater(Runnable runnable) {
|
public void runLater(Runnable runnable) {
|
||||||
|
runLater(runnable, () -> runLater(runnable));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runLater(Runnable runnable, Runnable defer) {
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
if (mc.isOnThread() && inRunLater && !inRenderTaskQueue) {
|
if (mc.isOnThread() && inRunLater && !inRenderTaskQueue) {
|
||||||
((MinecraftAccessor) mc).getRenderTaskQueue().offer(() -> {
|
((MinecraftAccessor) mc).getRenderTaskQueue().offer(() -> {
|
||||||
inRenderTaskQueue = true;
|
inRenderTaskQueue = true;
|
||||||
try {
|
try {
|
||||||
runLater(runnable);
|
defer.run();
|
||||||
} finally {
|
} finally {
|
||||||
inRenderTaskQueue = false;
|
inRenderTaskQueue = false;
|
||||||
}
|
}
|
||||||
@@ -503,13 +520,13 @@ public class ReplayMod implements
|
|||||||
//$$ @SubscribeEvent
|
//$$ @SubscribeEvent
|
||||||
//$$ public void onRenderTick(TickEvent.RenderTickEvent event) {
|
//$$ public void onRenderTick(TickEvent.RenderTickEvent event) {
|
||||||
//$$ if (event.phase == TickEvent.Phase.START) {
|
//$$ if (event.phase == TickEvent.Phase.START) {
|
||||||
//$$ runLater(runnable);
|
|
||||||
//$$ FORGE_BUS.unregister(this);
|
//$$ FORGE_BUS.unregister(this);
|
||||||
|
//$$ defer.run();
|
||||||
//$$ }
|
//$$ }
|
||||||
//$$ }
|
//$$ }
|
||||||
//$$ });
|
//$$ });
|
||||||
//#else
|
//#else
|
||||||
//$$ FML_BUS.register(new RunLaterHelper(runnable));
|
//$$ FML_BUS.register(new RunLaterHelper(defer));
|
||||||
//#endif
|
//#endif
|
||||||
//$$ return;
|
//$$ return;
|
||||||
//$$ }
|
//$$ }
|
||||||
@@ -539,17 +556,17 @@ public class ReplayMod implements
|
|||||||
//$$
|
//$$
|
||||||
//$$ // in 1.7.10 apparently events can't be delivered to anonymous classes
|
//$$ // in 1.7.10 apparently events can't be delivered to anonymous classes
|
||||||
//$$ public class RunLaterHelper {
|
//$$ public class RunLaterHelper {
|
||||||
//$$ private final Runnable runnable;
|
//$$ private final Runnable defer;
|
||||||
//$$
|
//$$
|
||||||
//$$ private RunLaterHelper(Runnable runnable) {
|
//$$ private RunLaterHelper(Runnable defer) {
|
||||||
//$$ this.runnable = runnable;
|
//$$ this.defer = defer;
|
||||||
//$$ }
|
//$$ }
|
||||||
//$$
|
//$$
|
||||||
//$$ @SubscribeEvent
|
//$$ @SubscribeEvent
|
||||||
//$$ public void onRenderTick(TickEvent.RenderTickEvent event) {
|
//$$ public void onRenderTick(TickEvent.RenderTickEvent event) {
|
||||||
//$$ if (event.phase == TickEvent.Phase.START) {
|
//$$ if (event.phase == TickEvent.Phase.START) {
|
||||||
//$$ runLater(runnable);
|
|
||||||
//$$ FML_BUS.unregister(this);
|
//$$ FML_BUS.unregister(this);
|
||||||
|
//$$ defer.run();
|
||||||
//$$ }
|
//$$ }
|
||||||
//$$ }
|
//$$ }
|
||||||
//$$ }
|
//$$ }
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ public class GuiRenderQueue extends AbstractGuiPopup<GuiRenderQueue> {
|
|||||||
|
|
||||||
renderButton.onClick(() -> {
|
renderButton.onClick(() -> {
|
||||||
LOGGER.trace("Render button clicked");
|
LOGGER.trace("Render button clicked");
|
||||||
ReplayMod.instance.runLater(() -> processQueue(queue));
|
ReplayMod.instance.runLaterWithoutLock(() -> processQueue(queue));
|
||||||
});
|
});
|
||||||
|
|
||||||
updateButtons();
|
updateButtons();
|
||||||
@@ -233,7 +233,7 @@ public class GuiRenderQueue extends AbstractGuiPopup<GuiRenderQueue> {
|
|||||||
// Update current job with fixed ffmpeg arguments
|
// Update current job with fixed ffmpeg arguments
|
||||||
renderJob.setSettings(newSettings);
|
renderJob.setSettings(newSettings);
|
||||||
// Restart queue, skipping the already completed jobs
|
// Restart queue, skipping the already completed jobs
|
||||||
processQueue(Iterables.skip(queue, jobsToSkip));
|
ReplayMod.instance.runLaterWithoutLock(() -> processQueue(Iterables.skip(queue, jobsToSkip)));
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
|||||||
new GuiRenderQueue(GuiRenderSettings.this, GuiRenderSettings.this, replayHandler, timeline).open();
|
new GuiRenderQueue(GuiRenderSettings.this, GuiRenderSettings.this, replayHandler, timeline).open();
|
||||||
}
|
}
|
||||||
}).setSize(100, 20).setI18nLabel("replaymod.gui.renderqueue.open");
|
}).setSize(100, 20).setI18nLabel("replaymod.gui.renderqueue.open");
|
||||||
public final GuiButton renderButton = new GuiButton(buttonPanel).onClick(() -> ReplayMod.instance.runLater(new Runnable() {
|
public final GuiButton renderButton = new GuiButton(buttonPanel).onClick(() -> ReplayMod.instance.runLaterWithoutLock(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// Closing this GUI ensures that settings are saved
|
// Closing this GUI ensures that settings are saved
|
||||||
|
|||||||
Reference in New Issue
Block a user