Model allocators are passed on init instead of stored

This commit is contained in:
Jozufozu 2022-03-16 21:26:43 -07:00
parent ec8b831917
commit eb5d3c4b25
4 changed files with 42 additions and 31 deletions

View file

@ -19,7 +19,6 @@ import com.jozufozu.flywheel.core.model.Model;
public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> { public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
private final ModelAllocator modelAllocator;
private final BufferLayout instanceFormat; private final BufferLayout instanceFormat;
private final Instanced<D> instancedType; private final Instanced<D> instancedType;
@ -32,9 +31,8 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
protected boolean anyToUpdate; protected boolean anyToUpdate;
public GPUInstancer(Instanced<D> type, Model model, ModelAllocator modelAllocator) { public GPUInstancer(Instanced<D> type, Model model) {
super(type::create, model); super(type::create, model);
this.modelAllocator = modelAllocator;
this.instanceFormat = type.getLayout(); this.instanceFormat = type.getLayout();
instancedType = type; instancedType = type;
} }
@ -63,7 +61,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
return deleted || model == null; return deleted || model == null;
} }
public void init() { public void init(ModelAllocator modelAllocator) {
if (isInitialized()) return; if (isInitialized()) return;
initialized = true; initialized = true;

View file

@ -11,7 +11,6 @@ import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.Instancer; import com.jozufozu.flywheel.api.Instancer;
import com.jozufozu.flywheel.api.Material; import com.jozufozu.flywheel.api.Material;
import com.jozufozu.flywheel.api.struct.Instanced; import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.backend.model.ModelAllocator;
import com.jozufozu.flywheel.core.model.Model; import com.jozufozu.flywheel.core.model.Model;
/** /**
@ -20,14 +19,12 @@ import com.jozufozu.flywheel.core.model.Model;
*/ */
public class InstancedMaterial<D extends InstanceData> implements Material<D> { public class InstancedMaterial<D extends InstanceData> implements Material<D> {
protected final ModelAllocator allocator;
protected final Map<Object, GPUInstancer<D>> models = new HashMap<>(); protected final Map<Object, GPUInstancer<D>> models = new HashMap<>();
protected final Instanced<D> type; protected final Instanced<D> type;
protected final List<GPUInstancer<D>> uninitialized = new ArrayList<>(); protected final List<GPUInstancer<D>> uninitialized = new ArrayList<>();
public InstancedMaterial(Instanced<D> type, ModelAllocator allocator) { public InstancedMaterial(Instanced<D> type) {
this.type = type; this.type = type;
this.allocator = allocator;
} }
/** /**
@ -40,7 +37,7 @@ public class InstancedMaterial<D extends InstanceData> implements Material<D> {
@Override @Override
public Instancer<D> model(Object key, Supplier<Model> modelSupplier) { public Instancer<D> model(Object key, Supplier<Model> modelSupplier) {
return models.computeIfAbsent(key, $ -> { return models.computeIfAbsent(key, $ -> {
GPUInstancer<D> instancer = new GPUInstancer<>(type, modelSupplier.get(), allocator); GPUInstancer<D> instancer = new GPUInstancer<>(type, modelSupplier.get());
uninitialized.add(instancer); uninitialized.add(instancer);
return instancer; return instancer;
}); });

View file

@ -32,27 +32,21 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
protected final RenderType type; protected final RenderType type;
private final Map<Instanced<? extends InstanceData>, InstancedMaterial<?>> materials = new HashMap<>(); private final Map<Instanced<? extends InstanceData>, InstancedMaterial<?>> materials = new HashMap<>();
private final ModelAllocator allocator;
private ModelAllocator allocator;
private int vertexCount; private int vertexCount;
private int instanceCount; private int instanceCount;
public InstancedMaterialGroup(InstancingEngine<P> owner, RenderType type) { public InstancedMaterialGroup(InstancingEngine<P> owner, RenderType type) {
this.owner = owner; this.owner = owner;
this.type = type; this.type = type;
if (GlCompat.getInstance()
.onAMDWindows()) {
this.allocator = FallbackAllocator.INSTANCE;
} else {
this.allocator = new ModelPool(Formats.POS_TEX_NORMAL);
}
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public <D extends InstanceData> InstancedMaterial<D> material(StructType<D> type) { public <D extends InstanceData> InstancedMaterial<D> material(StructType<D> type) {
if (type instanceof Instanced<D> instanced) { if (type instanceof Instanced<D> instanced) {
return (InstancedMaterial<D>) materials.computeIfAbsent(instanced, t -> new InstancedMaterial<>(t, allocator)); return (InstancedMaterial<D>) materials.computeIfAbsent(instanced, InstancedMaterial::new);
} else { } else {
throw new ClassCastException("Cannot use type '" + type + "' with GPU instancing."); throw new ClassCastException("Cannot use type '" + type + "' with GPU instancing.");
} }
@ -82,18 +76,7 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
} }
protected void renderAll(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) { protected void renderAll(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
// initialize all uninitialized instancers... initializeInstancers();
for (InstancedMaterial<?> material : materials.values()) {
for (GPUInstancer<?> instancer : material.uninitialized) {
instancer.init();
}
material.uninitialized.clear();
}
if (allocator instanceof ModelPool pool) {
// ...and then flush the model arena in case anything was marked for upload
pool.flush();
}
vertexCount = 0; vertexCount = 0;
instanceCount = 0; instanceCount = 0;
@ -119,7 +102,24 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
} }
} }
public void setup(P program) { private void initializeInstancers() {
ModelAllocator allocator = getModelAllocator();
// initialize all uninitialized instancers...
for (InstancedMaterial<?> material : materials.values()) {
for (GPUInstancer<?> instancer : material.uninitialized) {
instancer.init(allocator);
}
material.uninitialized.clear();
}
if (allocator instanceof ModelPool pool) {
// ...and then flush the model arena in case anything was marked for upload
pool.flush();
}
}
protected void setup(P program) {
} }
@ -133,4 +133,20 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
materials.clear(); materials.clear();
} }
private ModelAllocator getModelAllocator() {
if (allocator == null) {
allocator = createAllocator();
}
return this.allocator;
}
private static ModelAllocator createAllocator() {
if (GlCompat.getInstance()
.onAMDWindows()) {
return FallbackAllocator.INSTANCE;
} else {
return new ModelPool(Formats.POS_TEX_NORMAL);
}
}
} }

View file

@ -54,7 +54,7 @@ public class CrumblingGroup<P extends CrumblingProgram> extends InstancedMateria
} }
@Override @Override
public void setup(P p) { protected void setup(P p) {
p.setAtlasSize(width, height); p.setAtlasSize(width, height);
} }
} }