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> {
private final ModelAllocator modelAllocator;
private final BufferLayout instanceFormat;
private final Instanced<D> instancedType;
@ -32,9 +31,8 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
protected boolean anyToUpdate;
public GPUInstancer(Instanced<D> type, Model model, ModelAllocator modelAllocator) {
public GPUInstancer(Instanced<D> type, Model model) {
super(type::create, model);
this.modelAllocator = modelAllocator;
this.instanceFormat = type.getLayout();
instancedType = type;
}
@ -63,7 +61,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
return deleted || model == null;
}
public void init() {
public void init(ModelAllocator modelAllocator) {
if (isInitialized()) return;
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.Material;
import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.backend.model.ModelAllocator;
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> {
protected final ModelAllocator allocator;
protected final Map<Object, GPUInstancer<D>> models = new HashMap<>();
protected final Instanced<D> type;
protected final List<GPUInstancer<D>> uninitialized = new ArrayList<>();
public InstancedMaterial(Instanced<D> type, ModelAllocator allocator) {
public InstancedMaterial(Instanced<D> type) {
this.type = type;
this.allocator = allocator;
}
/**
@ -40,7 +37,7 @@ public class InstancedMaterial<D extends InstanceData> implements Material<D> {
@Override
public Instancer<D> model(Object key, Supplier<Model> modelSupplier) {
return models.computeIfAbsent(key, $ -> {
GPUInstancer<D> instancer = new GPUInstancer<>(type, modelSupplier.get(), allocator);
GPUInstancer<D> instancer = new GPUInstancer<>(type, modelSupplier.get());
uninitialized.add(instancer);
return instancer;
});

View file

@ -32,27 +32,21 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
protected final RenderType type;
private final Map<Instanced<? extends InstanceData>, InstancedMaterial<?>> materials = new HashMap<>();
private final ModelAllocator allocator;
private ModelAllocator allocator;
private int vertexCount;
private int instanceCount;
public InstancedMaterialGroup(InstancingEngine<P> owner, RenderType type) {
this.owner = owner;
this.type = type;
if (GlCompat.getInstance()
.onAMDWindows()) {
this.allocator = FallbackAllocator.INSTANCE;
} else {
this.allocator = new ModelPool(Formats.POS_TEX_NORMAL);
}
}
@SuppressWarnings("unchecked")
@Override
public <D extends InstanceData> InstancedMaterial<D> material(StructType<D> type) {
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 {
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) {
// initialize all uninitialized instancers...
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();
}
initializeInstancers();
vertexCount = 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();
}
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
public void setup(P p) {
protected void setup(P p) {
p.setAtlasSize(width, height);
}
}