mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-02-22 09:55:33 +01:00
More hooks more problems
- Remove Engine#setupRender - Combine DrawManager#flush and DrawManager#render to simplify engines - Document the hooks in RenderDispatcher
This commit is contained in:
parent
39a9c45b25
commit
a2fc111499
7 changed files with 50 additions and 79 deletions
|
@ -58,22 +58,11 @@ public interface Engine {
|
||||||
void onLightUpdate(SectionPos sectionPos, LightLayer layer);
|
void onLightUpdate(SectionPos sectionPos, LightLayer layer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up rendering for the current level render.
|
* Render all instances necessary for the given visual type.
|
||||||
*
|
*
|
||||||
* <p>This method is guaranteed to be called after
|
* <p>This method is guaranteed to be called after
|
||||||
* {@linkplain #createFramePlan() the frame plan} has finished execution and before
|
* {@linkplain #createFramePlan() the frame plan} has finished execution and before
|
||||||
* {@link #render} and {@link #renderCrumbling} are called. This method is guaranteed to
|
* {@link #renderCrumbling} are called. This method is guaranteed to be called on the render thread.
|
||||||
* be called on the render thread.
|
|
||||||
*
|
|
||||||
* @param context The context for the current level render.
|
|
||||||
*/
|
|
||||||
void setupRender(RenderContext context);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render all instances necessary for the given visual type.
|
|
||||||
*
|
|
||||||
* <p>This method is guaranteed to be called after {@link #setupRender} for the current
|
|
||||||
* level render. This method is guaranteed to be called on the render thread.
|
|
||||||
*
|
*
|
||||||
* @param context The context for the current level render.
|
* @param context The context for the current level render.
|
||||||
*/
|
*/
|
||||||
|
@ -82,7 +71,7 @@ public interface Engine {
|
||||||
/**
|
/**
|
||||||
* Render the given instances as a crumbling overlay.
|
* Render the given instances as a crumbling overlay.
|
||||||
*
|
*
|
||||||
* <p>This method is guaranteed to be called after {@link #setupRender} for the current
|
* <p>This method is guaranteed to be called after {@link #render} for the current
|
||||||
* level render. This method is guaranteed to be called on the render thread.
|
* level render. This method is guaranteed to be called on the render thread.
|
||||||
*
|
*
|
||||||
* @param context The context for the current level render.
|
* @param context The context for the current level render.
|
||||||
|
|
|
@ -47,10 +47,31 @@ public interface VisualizationManager {
|
||||||
|
|
||||||
@ApiStatus.NonExtendable
|
@ApiStatus.NonExtendable
|
||||||
interface RenderDispatcher {
|
interface RenderDispatcher {
|
||||||
|
/**
|
||||||
|
* Prepare visuals for render.
|
||||||
|
*
|
||||||
|
* <p>Guaranteed to be called before {@link #afterEntities} and {@link #beforeCrumbling}.
|
||||||
|
* <br>Guaranteed to be called after the render thread has processed all light updates.
|
||||||
|
* <br>The caller is otherwise free to choose an invocation site, but it is recommended to call
|
||||||
|
* this as early as possible to give the VisualizationManager time to process things off-thread.
|
||||||
|
*/
|
||||||
void onStartLevelRender(RenderContext ctx);
|
void onStartLevelRender(RenderContext ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render instances.
|
||||||
|
*
|
||||||
|
* <p>Guaranteed to be called after {@link #onStartLevelRender} and before {@link #beforeCrumbling}.
|
||||||
|
* <br>The caller is otherwise free to choose an invocation site, but it is recommended to call
|
||||||
|
* this between rendering entities and block entities.
|
||||||
|
*/
|
||||||
void afterEntities(RenderContext ctx);
|
void afterEntities(RenderContext ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render crumbling block entities.
|
||||||
|
*
|
||||||
|
* <p>Guaranteed to be called after {@link #onStartLevelRender} and {@link #afterEntities}
|
||||||
|
* @param destructionProgress The destruction progress map from {@link net.minecraft.client.renderer.LevelRenderer LevelRenderer}.
|
||||||
|
*/
|
||||||
void beforeCrumbling(RenderContext ctx, Long2ObjectMap<SortedSet<BlockDestructionProgress>> destructionProgress);
|
void beforeCrumbling(RenderContext ctx, Long2ObjectMap<SortedSet<BlockDestructionProgress>> destructionProgress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ public abstract class DrawManager<N extends AbstractInstancer<?>> {
|
||||||
/**
|
/**
|
||||||
* A list of instancers that have not yet been initialized.
|
* A list of instancers that have not yet been initialized.
|
||||||
* <br>
|
* <br>
|
||||||
* All new instancers land here before having resources allocated in {@link #flush}.
|
* All new instancers land here before having resources allocated in {@link #render}.
|
||||||
*/
|
*/
|
||||||
protected final Queue<UninitializedInstancer<N, ?>> initializationQueue = new ConcurrentLinkedQueue<>();
|
protected final Queue<UninitializedInstancer<N, ?>> initializationQueue = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ public abstract class DrawManager<N extends AbstractInstancer<?>> {
|
||||||
return ForEachPlan.of(() -> new ArrayList<>(instancers.values()), AbstractInstancer::parallelUpdate);
|
return ForEachPlan.of(() -> new ArrayList<>(instancers.values()), AbstractInstancer::parallelUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush(LightStorage lightStorage, EnvironmentStorage environmentStorage) {
|
public void render(LightStorage lightStorage, EnvironmentStorage environmentStorage) {
|
||||||
// Thread safety: flush is called from the render thread after all visual updates have been made,
|
// Thread safety: flush is called from the render thread after all visual updates have been made,
|
||||||
// so there are no:tm: threads we could be racing with.
|
// so there are no:tm: threads we could be racing with.
|
||||||
for (var init : initializationQueue) {
|
for (var init : initializationQueue) {
|
||||||
|
@ -75,8 +75,6 @@ public abstract class DrawManager<N extends AbstractInstancer<?>> {
|
||||||
.forEach(AbstractInstancer::clear);
|
.forEach(AbstractInstancer::clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void render();
|
|
||||||
|
|
||||||
public abstract void renderCrumbling(List<Engine.CrumblingBlock> crumblingBlocks);
|
public abstract void renderCrumbling(List<Engine.CrumblingBlock> crumblingBlocks);
|
||||||
|
|
||||||
protected abstract <I extends Instance> N create(InstancerKey<I> type);
|
protected abstract <I extends Instance> N create(InstancerKey<I> type);
|
||||||
|
|
|
@ -89,23 +89,13 @@ public class EngineImpl implements Engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setupRender(RenderContext context) {
|
public void render(RenderContext context) {
|
||||||
try (var state = GlStateTracker.getRestoreState()) {
|
try (var state = GlStateTracker.getRestoreState()) {
|
||||||
// Process the render queue for font updates
|
// Process the render queue for font updates
|
||||||
RenderSystem.replayQueue();
|
RenderSystem.replayQueue();
|
||||||
Uniforms.update(context);
|
Uniforms.update(context);
|
||||||
environmentStorage.flush();
|
environmentStorage.flush();
|
||||||
drawManager.flush(lightStorage, environmentStorage);
|
drawManager.render(lightStorage, environmentStorage);
|
||||||
} catch (ShaderException e) {
|
|
||||||
FlwBackend.LOGGER.error("Falling back", e);
|
|
||||||
triggerFallback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(RenderContext context) {
|
|
||||||
try (var state = GlStateTracker.getRestoreState()) {
|
|
||||||
drawManager.render();
|
|
||||||
} catch (ShaderException e) {
|
} catch (ShaderException e) {
|
||||||
FlwBackend.LOGGER.error("Falling back", e);
|
FlwBackend.LOGGER.error("Falling back", e);
|
||||||
triggerFallback();
|
triggerFallback();
|
||||||
|
|
|
@ -48,8 +48,6 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
|
||||||
|
|
||||||
private final DepthPyramid depthPyramid;
|
private final DepthPyramid depthPyramid;
|
||||||
|
|
||||||
private boolean needsBarrier = false;
|
|
||||||
|
|
||||||
public IndirectDrawManager(IndirectPrograms programs) {
|
public IndirectDrawManager(IndirectPrograms programs) {
|
||||||
this.programs = programs;
|
this.programs = programs;
|
||||||
programs.acquire();
|
programs.acquire();
|
||||||
|
@ -78,30 +76,9 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
|
||||||
group.add((IndirectInstancer<I>) instancer, key, meshPool);
|
group.add((IndirectInstancer<I>) instancer, key, meshPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render() {
|
|
||||||
TextureBinder.bindLightAndOverlay();
|
|
||||||
|
|
||||||
vertexArray.bindForDraw();
|
|
||||||
lightBuffers.bind();
|
|
||||||
matrixBuffer.bind();
|
|
||||||
Uniforms.bindAll();
|
|
||||||
|
|
||||||
if (needsBarrier) {
|
|
||||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
|
||||||
needsBarrier = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var group : cullingGroups.values()) {
|
|
||||||
group.submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialRenderState.reset();
|
|
||||||
TextureBinder.resetLightAndOverlay();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void flush(LightStorage lightStorage, EnvironmentStorage environmentStorage) {
|
public void render(LightStorage lightStorage, EnvironmentStorage environmentStorage) {
|
||||||
super.flush(lightStorage, environmentStorage);
|
super.render(lightStorage, environmentStorage);
|
||||||
|
|
||||||
for (var group : cullingGroups.values()) {
|
for (var group : cullingGroups.values()) {
|
||||||
group.flushInstancers();
|
group.flushInstancers();
|
||||||
|
@ -151,7 +128,21 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
|
||||||
group.dispatchApply();
|
group.dispatchApply();
|
||||||
}
|
}
|
||||||
|
|
||||||
needsBarrier = true;
|
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||||
|
|
||||||
|
TextureBinder.bindLightAndOverlay();
|
||||||
|
|
||||||
|
vertexArray.bindForDraw();
|
||||||
|
lightBuffers.bind();
|
||||||
|
matrixBuffer.bind();
|
||||||
|
Uniforms.bindAll();
|
||||||
|
|
||||||
|
for (var group : cullingGroups.values()) {
|
||||||
|
group.submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialRenderState.reset();
|
||||||
|
TextureBinder.resetLightAndOverlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -51,8 +51,8 @@ public class InstancedDrawManager extends DrawManager<InstancedInstancer<?>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void flush(LightStorage lightStorage, EnvironmentStorage environmentStorage) {
|
public void render(LightStorage lightStorage, EnvironmentStorage environmentStorage) {
|
||||||
super.flush(lightStorage, environmentStorage);
|
super.render(lightStorage, environmentStorage);
|
||||||
|
|
||||||
this.instancers.values()
|
this.instancers.values()
|
||||||
.removeIf(instancer -> {
|
.removeIf(instancer -> {
|
||||||
|
@ -71,13 +71,8 @@ public class InstancedDrawManager extends DrawManager<InstancedInstancer<?>> {
|
||||||
meshPool.flush();
|
meshPool.flush();
|
||||||
|
|
||||||
light.flush(lightStorage);
|
light.flush(lightStorage);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (draws.isEmpty()) {
|
||||||
public void render() {
|
|
||||||
var stage = draws;
|
|
||||||
|
|
||||||
if (stage.isEmpty()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +81,7 @@ public class InstancedDrawManager extends DrawManager<InstancedInstancer<?>> {
|
||||||
TextureBinder.bindLightAndOverlay();
|
TextureBinder.bindLightAndOverlay();
|
||||||
light.bind();
|
light.bind();
|
||||||
|
|
||||||
stage.draw(instanceTexture, programs);
|
draws.draw(instanceTexture, programs);
|
||||||
|
|
||||||
MaterialRenderState.reset();
|
MaterialRenderState.reset();
|
||||||
TextureBinder.resetLightAndOverlay();
|
TextureBinder.resetLightAndOverlay();
|
||||||
|
|
|
@ -73,8 +73,6 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
||||||
private final Plan<RenderContext> framePlan;
|
private final Plan<RenderContext> framePlan;
|
||||||
private final Plan<TickableVisual.Context> tickPlan;
|
private final Plan<TickableVisual.Context> tickPlan;
|
||||||
|
|
||||||
private boolean canEngineRender;
|
|
||||||
|
|
||||||
private VisualizationManagerImpl(LevelAccessor level) {
|
private VisualizationManagerImpl(LevelAccessor level) {
|
||||||
taskExecutor = FlwTaskExecutor.get();
|
taskExecutor = FlwTaskExecutor.get();
|
||||||
engine = BackendManager.currentBackend()
|
engine = BackendManager.currentBackend()
|
||||||
|
@ -241,24 +239,15 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
||||||
frameFlag.lower();
|
frameFlag.lower();
|
||||||
|
|
||||||
frameLimiter.tick();
|
frameLimiter.tick();
|
||||||
canEngineRender = false;
|
|
||||||
|
|
||||||
framePlan.execute(taskExecutor, context);
|
framePlan.execute(taskExecutor, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureCanRender(RenderContext context) {
|
|
||||||
taskExecutor.syncUntil(frameFlag::isRaised);
|
|
||||||
if (!canEngineRender) {
|
|
||||||
engine.setupRender(context);
|
|
||||||
canEngineRender = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw all visuals of the given type.
|
* Draw all visuals of the given type.
|
||||||
*/
|
*/
|
||||||
private void render(RenderContext context) {
|
private void render(RenderContext context) {
|
||||||
ensureCanRender(context);
|
taskExecutor.syncUntil(frameFlag::isRaised);
|
||||||
engine.render(context);
|
engine.render(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,8 +256,6 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ensureCanRender(context);
|
|
||||||
|
|
||||||
List<Engine.CrumblingBlock> crumblingBlocks = new ArrayList<>();
|
List<Engine.CrumblingBlock> crumblingBlocks = new ArrayList<>();
|
||||||
|
|
||||||
for (var entry : destructionProgress.long2ObjectEntrySet()) {
|
for (var entry : destructionProgress.long2ObjectEntrySet()) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue