5 Commits
Author SHA1 Message Date
Speiger 56eae46176 Progress on UI Renderer 2026-08-16 21:22:28 +02:00
Speiger 3b074a2684 Font renderer ported 2026-08-06 13:56:16 +02:00
Speiger 9362707ccc More work on the rewrite 2026-08-05 17:15:58 +02:00
Speiger 060f5e534c Progress on the engine 2026-08-04 02:30:55 +02:00
Speiger df9c94ca37 gradle update 2026-07-31 18:57:05 +02:00
258 changed files with 7451 additions and 2718 deletions
+20 -8
View File
@@ -12,22 +12,34 @@
<attribute name="gradle_used_by_scope" value="main,test"/> <attribute name="gradle_used_by_scope" value="main,test"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" output="bin/assets" path="src/assets/java">
<attributes>
<attribute name="gradle_scope" value="assets"/>
<attribute name="gradle_used_by_scope" value="main,test,assets,graphics,gui"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/events" path="src/events/java">
<attributes>
<attribute name="gradle_scope" value="events"/>
<attribute name="gradle_used_by_scope" value="main,test,assets,events,graphics,gui"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/graphics" path="src/graphics/java"> <classpathentry kind="src" output="bin/graphics" path="src/graphics/java">
<attributes> <attributes>
<attribute name="gradle_scope" value="graphics"/> <attribute name="gradle_scope" value="graphics"/>
<attribute name="gradle_used_by_scope" value="graphics"/> <attribute name="gradle_used_by_scope" value="main,test,graphics,gui"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/gui" path="src/gui/java">
<attributes>
<attribute name="gradle_scope" value="gui"/>
<attribute name="gradle_used_by_scope" value="main,test,gui"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" output="bin/math" path="src/math/java"> <classpathentry kind="src" output="bin/math" path="src/math/java">
<attributes> <attributes>
<attribute name="gradle_scope" value="math"/> <attribute name="gradle_scope" value="math"/>
<attribute name="gradle_used_by_scope" value="main,graphics,math"/> <attribute name="gradle_used_by_scope" value="main,test,graphics,gui,math"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/assets" path="src/assets/java">
<attributes>
<attribute name="gradle_scope" value="assets"/>
<attribute name="gradle_used_by_scope" value="assets"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-25/"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-25/"/>
+13 -14
View File
@@ -2,22 +2,21 @@
<projectDescription> <projectDescription>
<name>SimpleJavaEngine</name> <name>SimpleJavaEngine</name>
<comment></comment> <comment></comment>
<projects> <projects/>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures> <natures>
<nature>org.eclipse.jdt.core.javanature</nature> <nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature> <nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures> </natures>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments/>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments/>
</buildCommand>
</buildSpec>
<linkedResources/>
<filteredResources/>
</projectDescription> </projectDescription>
+63 -60
View File
@@ -16,97 +16,100 @@ eclipse {
} }
sourceSets { sourceSets {
math { math
java {} events
} assets
assets { graphics
java {} gui
} main
graphics {
java {}
}
main {
compileClasspath += sourceSets.math.output
runtimeClasspath += sourceSets.math.output
}
graphics {
compileClasspath += sourceSets.math.output
runtimeClasspath += sourceSets.math.output
java {}
}
} }
configurations { configurations {
graphics.extendsFrom implementation commonImplementation
graphics.extendsFrom runtime assetsImplementation.extendsFrom(eventsImplementation)
graphics.extendsFrom mathRuntime graphicsImplementation.extendsFrom(mathImplementation, assetsImplementation)
implementation.extendsFrom mathRuntime guiImplementation.extendsFrom(graphicsImplementation)
implementation.extendsFrom(guiImplementation)
} }
sourceSets.all { sourceSet ->
String implementationConfigName = sourceSet.implementationConfigurationName
configurations.named(implementationConfigName).configure {
extendsFrom(configurations.named("commonImplementation").get())
}
}
repositories { repositories {
mavenCentral() mavenCentral()
maven { maven {
name = "Speiger Maven" name = "Speiger Maven"
url = "https://maven.speiger.com/repository/main" url = "https://maven.speiger.com/repository/main"
} }
maven { url "https://central.sonatype.com/repository/maven-snapshots" } maven { url = "https://central.sonatype.com/repository/maven-snapshots" }
} }
dependencies { dependencies {
//LWJGL 3 assetsImplementation sourceSets.events.output
implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion") graphicsImplementation sourceSets.math.output
graphicsImplementation sourceSets.assets.output
guiImplementation sourceSets.graphics.output
implementation sourceSets.gui.output
implementation "org.lwjgl:lwjgl" //LWJGL 3
implementation "org.lwjgl:lwjgl-glfw" commonImplementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion")
implementation "org.lwjgl:lwjgl-jemalloc"
implementation "org.lwjgl:lwjgl-openal" commonImplementation "org.lwjgl:lwjgl"
implementation "org.lwjgl:lwjgl-opengl" commonImplementation "org.lwjgl:lwjgl-glfw"
implementation "org.lwjgl:lwjgl-stb" commonImplementation "org.lwjgl:lwjgl-jemalloc"
implementation "org.lwjgl:lwjgl-nfd" commonImplementation "org.lwjgl:lwjgl-openal"
implementation "org.lwjgl:lwjgl-freetype" commonImplementation "org.lwjgl:lwjgl-opengl"
implementation "org.lwjgl:lwjgl-harfbuzz" commonImplementation "org.lwjgl:lwjgl-stb"
implementation "org.lwjgl:lwjgl-nanovg" commonImplementation "org.lwjgl:lwjgl-nfd"
implementation "org.lwjgl:lwjgl::$lwjglNatives" commonImplementation "org.lwjgl:lwjgl-freetype"
implementation "org.lwjgl:lwjgl-glfw::$lwjglNatives" commonImplementation "org.lwjgl:lwjgl-harfbuzz"
implementation "org.lwjgl:lwjgl-jemalloc::$lwjglNatives" commonImplementation "org.lwjgl:lwjgl-nanovg"
implementation "org.lwjgl:lwjgl-openal::$lwjglNatives" commonImplementation "org.lwjgl:lwjgl::$lwjglNatives"
implementation "org.lwjgl:lwjgl-opengl::$lwjglNatives" commonImplementation "org.lwjgl:lwjgl-glfw::$lwjglNatives"
implementation "org.lwjgl:lwjgl-stb::$lwjglNatives" commonImplementation "org.lwjgl:lwjgl-jemalloc::$lwjglNatives"
implementation "org.lwjgl:lwjgl-nfd::$lwjglNatives" commonImplementation "org.lwjgl:lwjgl-openal::$lwjglNatives"
implementation "org.lwjgl:lwjgl-freetype::$lwjglNatives" commonImplementation "org.lwjgl:lwjgl-opengl::$lwjglNatives"
implementation "org.lwjgl:lwjgl-harfbuzz::$lwjglNatives" commonImplementation "org.lwjgl:lwjgl-stb::$lwjglNatives"
implementation "org.lwjgl:lwjgl-nanovg::$lwjglNatives" commonImplementation "org.lwjgl:lwjgl-nfd::$lwjglNatives"
implementation "org.jspecify:jspecify:1.0.0" commonImplementation "org.lwjgl:lwjgl-freetype::$lwjglNatives"
commonImplementation "org.lwjgl:lwjgl-harfbuzz::$lwjglNatives"
commonImplementation "org.lwjgl:lwjgl-nanovg::$lwjglNatives"
commonImplementation "org.jspecify:jspecify:1.0.0"
//Gson //Gson
implementation 'com.google.code.gson:gson:2.8.6' commonImplementation 'com.google.code.gson:gson:2.8.6'
//Primitive Collections //Primitive Collections
implementation 'de.speiger:Primitive-Collections:1.0.0' commonImplementation 'de.speiger:Primitive-Collections:1.0.0'
mathImplementation 'de.speiger:Primitive-Collections:1.0.0'
} }
jar { jar {
manifest { sourceSets.each { ss ->
attributes "Main-Class": 'speiger.src.coreengine.NewInputTest' from ss.output
} }
from { from {
configurations.runtimeClasspath.collect { configurations.runtimeClasspath.collect {
it.isDirectory() ? it : zipTree(it) !it.exists() ? null : (it.isDirectory() ? it : zipTree(it))
} }
} }
duplicatesStrategy = DuplicatesStrategy.INCLUDE duplicatesStrategy = DuplicatesStrategy.INCLUDE
} }
task srcJar(type: Jar) { task srcJar(type: Jar) {
from sourceSets.main.allSource
archiveClassifier = 'sources' archiveClassifier = 'sources'
from {
configurations.runtimeClasspath.collect { sourceSets.each { ss ->
it.isDirectory() ? it : zipTree(it) from ss.allSource
} }
}
duplicatesStrategy = DuplicatesStrategy.INCLUDE duplicatesStrategy = DuplicatesStrategy.INCLUDE
} }
@@ -0,0 +1,35 @@
package speiger.src.coreengine.assets.api;
import java.util.Map;
public record AssetFilter(String prefix, String extension) {
public static AssetFilter json(String prefix) {
return new AssetFilter(prefix, ".json");
}
public ID id(ID file) {
String location = file.fileLocation();
return ID.of(file.domain(), location.substring(prefix().length()+1, location.length()-extension().length()));
}
public ID file(ID id) {
return ID.of(id.domain(), prefix()+"/"+id.fileLocation()+extension());
}
public Map<ID, IAsset> list(IAssetProvider provider) {
return provider.list(prefix, T -> T.endsWith(extension));
}
public Map<ID, IAsset> listRoot(IAssetProvider provider) {
return provider.list(prefix, T -> T.endsWith(extension) && T.isRootFolder(prefix));
}
public Map<ID, MultiAsset> multi(IAssetProvider provider) {
return provider.listAll(prefix, T -> T.endsWith(extension));
}
public Map<ID, MultiAsset> multiRoot(IAssetProvider provider) {
return provider.listAll(prefix, T -> T.endsWith(extension) && T.isRootFolder(prefix));
}
}
@@ -3,11 +3,17 @@ package speiger.src.coreengine.assets.api;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public interface IResourceListener { public interface IResourceListener {
void name();
CompletableFuture<Void> reload(ReloadContext context, ISyncer sync); CompletableFuture<Void> reload(ReloadContext context, ISyncer sync);
void release();
public static interface ISimpleResourceListener extends IResourceListener {
@Override
default CompletableFuture<Void> reload(ReloadContext context, ISyncer sync) { return CompletableFuture.runAsync(() -> reload(context), context.tasks()); }
void reload(ReloadContext context);
}
public static interface ISyncer { public static interface ISyncer {
<T> CompletableFuture<T> sync(T value); <T> CompletableFuture<T> sync(T value);
} }
} }
@@ -3,7 +3,7 @@ package speiger.src.coreengine.assets.api;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
public record ReloadContext(IAssetProvider provider, Set<ID> filter, Executor main, Executor background) { public record ReloadContext(IAssetProvider provider, Set<ID> filter, Executor mainThread, Executor tasks, Executor background) {
public boolean hasChanged(ID id) { public boolean hasChanged(ID id) {
return filter.isEmpty() || filter.contains(id); return filter.isEmpty() || filter.contains(id);
@@ -0,0 +1,13 @@
package speiger.src.coreengine.assets.api;
import java.util.concurrent.CompletableFuture;
public abstract class SteppedResourceListener<T> implements IResourceListener {
@Override
public CompletableFuture<Void> reload(ReloadContext context, ISyncer sync) {
return CompletableFuture.supplyAsync(() -> prepare(context), context.tasks()).thenCompose(sync::sync).thenAccept(T -> apply(T, context));
}
protected abstract T prepare(ReloadContext context);
protected abstract void apply(T value, ReloadContext context);
}
@@ -76,7 +76,7 @@ public class AssetManager {
if(builder.listeners.isEmpty()) builder.withListener(tracker.listeners()); if(builder.listeners.isEmpty()) builder.withListener(tracker.listeners());
return new ReloadTask(get(), builder); return new ReloadTask(get(), builder);
} }
public boolean isReloadable() { public boolean isReloadable() {
return manager != null; return manager != null;
} }
@@ -16,6 +16,7 @@ import speiger.src.coreengine.assets.providers.SingleProvider;
public class ReloadBuilder { public class ReloadBuilder {
Executor mainRunner = Runnable::run; Executor mainRunner = Runnable::run;
Executor taskRunner = Runnable::run;
Executor syncRunner = Runnable::run; Executor syncRunner = Runnable::run;
Set<ID> filter = ObjectSets.empty(); Set<ID> filter = ObjectSets.empty();
Optional<BaseProvider> packages = Optional.empty(); Optional<BaseProvider> packages = Optional.empty();
@@ -26,11 +27,16 @@ public class ReloadBuilder {
return this; return this;
} }
public ReloadBuilder withMain(Executor main) { public ReloadBuilder withMainThread(Executor main) {
mainRunner = Objects.requireNonNull(main); mainRunner = Objects.requireNonNull(main);
return this; return this;
} }
public ReloadBuilder withTasks(Executor tasks) {
taskRunner = Objects.requireNonNull(tasks);
return this;
}
public ReloadBuilder withSync(Executor sync) { public ReloadBuilder withSync(Executor sync) {
syncRunner = Objects.requireNonNull(sync); syncRunner = Objects.requireNonNull(sync);
return this; return this;
@@ -13,13 +13,13 @@ import speiger.src.coreengine.assets.api.IResourceListener;
import speiger.src.coreengine.assets.api.IResourceListener.ISyncer; import speiger.src.coreengine.assets.api.IResourceListener.ISyncer;
import speiger.src.coreengine.assets.api.ReloadContext; import speiger.src.coreengine.assets.api.ReloadContext;
public class ReloadTask { public class ReloadTask {
AtomicInteger started = new AtomicInteger(); AtomicInteger started = new AtomicInteger();
AtomicInteger finished = new AtomicInteger(); AtomicInteger finished = new AtomicInteger();
CompletableFuture<?> future; CompletableFuture<?> future;
public ReloadTask(IAssetProvider provider, ReloadBuilder builder) { public ReloadTask(IAssetProvider provider, ReloadBuilder builder) {
future = reload(new ReloadContext(provider, builder.filter, new CountingExecutor(builder.mainRunner, started, finished), new CountingExecutor(builder.syncRunner, started, finished)), new ObjectArrayList<>(builder.listeners.get())); future = reload(new ReloadContext(provider, builder.filter, new CountingExecutor(builder.mainRunner, started, finished), new CountingExecutor(builder.taskRunner, started, finished), new CountingExecutor(builder.syncRunner, started, finished)), new ObjectArrayList<>(builder.listeners.get()));
} }
public int started() { return started.get(); } public int started() { return started.get(); }
@@ -36,14 +36,14 @@ public class ReloadTask {
List<CompletableFuture<Void>> tasks = new ObjectArrayList<>(); List<CompletableFuture<Void>> tasks = new ObjectArrayList<>();
for(IResourceListener listener : listeners) { for(IResourceListener listener : listeners) {
CompletableFuture<Void> current = chainedTask; CompletableFuture<Void> current = chainedTask;
chainedTask = listener.reload(context, new Syncer(context.main(), current, syncFuture, listener, todo)); chainedTask = listener.reload(context, new Syncer(context.tasks(), current, syncFuture, listener, todo));
tasks.add(chainedTask); tasks.add(chainedTask);
} }
return CompletableFuture.allOf(tasks.toArray(CompletableFuture[]::new)).thenRunAsync(() -> { return CompletableFuture.allOf(tasks.toArray(CompletableFuture[]::new)).thenRunAsync(() -> {
finished.getAndIncrement(); finished.getAndIncrement();
try { context.provider().close(); } try { context.provider().close(); }
catch(Exception e) { e.printStackTrace(); } catch(Exception e) { e.printStackTrace(); }
}, context.main()); }, context.tasks());
} }
@@ -0,0 +1,6 @@
package speiger.src.coreengine.core.events.api;
public class Event {
boolean canceled = false;
public final Event self() { return this; }
}
@@ -0,0 +1,8 @@
package speiger.src.coreengine.core.events.api;
public enum EventPriority
{
HIGH,
MEDIUM,
LOW;
}
@@ -0,0 +1,8 @@
package speiger.src.coreengine.core.events.api;
public interface ICancelableEvent {
Event self();
default boolean isCancelable() { return true; }
default void setCanceled(boolean value) { self().canceled = value; }
default boolean isCanceled() { return self().canceled; }
}
@@ -0,0 +1,18 @@
package speiger.src.coreengine.core.events.api;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target({TYPE, FIELD, METHOD})
public @interface SubscribeEvent
{
public EventPriority priority() default EventPriority.MEDIUM;
public Class<? extends Event> value() default Event.class;
}
@@ -0,0 +1,41 @@
package speiger.src.coreengine.core.events.bus;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import speiger.src.coreengine.core.events.api.Event;
import speiger.src.coreengine.core.events.bus.EventBus.ClassFilter;
import speiger.src.coreengine.core.events.utility.IEventDispatcher;
import speiger.src.coreengine.core.events.utility.IEventExceptionHandler;
public class BusBuilder {
IEventDispatcher dispatcher = IEventDispatcher.DIRECT;
Optional<IEventExceptionHandler> exceptions = Optional.empty();
ClassFilter typeCheck = new ClassFilter(false, _ -> true, "");
boolean running = true;
public BusBuilder dispatcher(IEventDispatcher dispatcher) {
this.dispatcher = Objects.requireNonNull(dispatcher, "A Dispatcher is required");
return this;
}
public BusBuilder exceptions(IEventExceptionHandler exceptions) {
this.exceptions = Optional.ofNullable(exceptions);
return this;
}
public BusBuilder filter(Predicate<Class<? extends Event>> filter, String filterMessage) {
this.typeCheck = new ClassFilter(true, Objects.requireNonNull(filter, "A Filter is required"), Objects.requireNonNull(filterMessage, "A Filter Message is required"));
return this;
}
public BusBuilder beginShutdown() {
running = false;
return this;
}
public EventBus build() {
return new EventBus(this);
}
}
@@ -0,0 +1,202 @@
package speiger.src.coreengine.core.events.bus;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandleInfo;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.maps.impl.concurrent.Object2ObjectConcurrentOpenHashMap;
import speiger.src.coreengine.core.events.api.Event;
import speiger.src.coreengine.core.events.api.EventPriority;
import speiger.src.coreengine.core.events.api.SubscribeEvent;
import speiger.src.coreengine.core.events.utility.IEventDispatcher;
import speiger.src.coreengine.core.events.utility.IEventExceptionHandler;
import speiger.src.coreengine.core.events.utility.Listeners;
import speiger.src.coreengine.core.events.utility.Subscription;
public class EventBus implements IEventExceptionHandler {
private static final Lookup LOOKUP = MethodHandles.lookup();
IEventDispatcher dispatcher;
IEventExceptionHandler exceptions;
ClassFilter typeCheck;
boolean shutdown = false;
Map<Class<? extends Event>, Listeners> listeners = new Object2ObjectConcurrentOpenHashMap<>();
EventBus(BusBuilder builder) {
dispatcher = builder.dispatcher;
exceptions = builder.exceptions.orElse(this);
typeCheck = builder.typeCheck;
shutdown = !builder.running;
}
public static BusBuilder builder() {
return new BusBuilder();
}
public Subscriptions create() {
return new Subscriptions(this);
}
public void start() {
shutdown = false;
}
public void shutdown() {
shutdown = true;
}
public <T extends Event> T post(T event) {
if(shutdown) return event;
validateType(event.getClass());
Listeners listener = listeners.get(event.getClass());
if(listener == null) return event;
dispatcher.post(listener.getListeners(), event, exceptions);
return event;
}
public <T extends Event> CompletableFuture<T> postAsync(T event) {
if(shutdown) return CompletableFuture.completedFuture(event);
return CompletableFuture.supplyAsync(() -> post(event));
}
public <T extends Event> CompletableFuture<T> postAsync(T event, Executor executor) {
if(shutdown) return CompletableFuture.completedFuture(event);
return CompletableFuture.supplyAsync(() -> post(event), executor);
}
@Override
public void handleException(Event event, Consumer<Event>[] listeners, int index, Throwable crash) {
StringBuilder builder = new StringBuilder();
builder.append("Event ["+event.getClass()+"] caused an Exception: ").append(crash.getMessage()).append('\n');
builder.append('\t').append("At Index=").append(index).append('\n');
builder.append("Listeners: ");
for (int x = 0; x < listeners.length; x++) {
builder.append("\t\t").append(x).append(": ").append(listeners[x]).append('\n');
}
StringWriter exception = new StringWriter();
crash.printStackTrace(new PrintWriter(exception));
builder.append(exception.getBuffer());
//TODO implement logging
System.err.println(builder.toString());
}
<T extends Event> Subscription register(Class<T> clz, EventPriority prio, Consumer<T> listener) {
validateType(clz);
registerListener(clz).addListener(prio, cast(listener));
return new EventListener(castClass(clz), cast(listener));
}
<T extends Event> List<Subscription> register(Object obj, boolean superClasses) {
final List<Subscription> list = new ObjectArrayList<>();
try {
register(obj.getClass().getDeclaredAnnotation(SubscribeEvent.class), obj, list);
find(obj.getClass(), superClasses, Class::getDeclaredMethods, t -> {
try {
t.setAccessible(true);
SubscribeEvent data = t.getAnnotation(SubscribeEvent.class);
if(data == null) return;
Consumer<Event> listener = new MethodListener(LOOKUP.unreflect(t).bindTo(obj));
Class<Event> clz = castClass(t.getParameterTypes()[0]);
validateType(clz);
registerListener(clz).addListener(data.priority(), listener);
list.add(new EventListener(clz, listener));
}
catch(Exception e) { e.printStackTrace(); }
});
find(obj.getClass(), superClasses, Class::getDeclaredFields, t -> {
try {
t.setAccessible(true);
register(t.getAnnotation(SubscribeEvent.class), t.get(obj), list);
}
catch(Exception e) { e.printStackTrace(); }
});
}
catch(Exception e) { e.printStackTrace(); }
return list;
}
private synchronized Listeners registerListener(Class<? extends Event> event) {
Listeners result = listeners.get(event);
if(result == null) {
result = event == Event.class ? new Listeners() : new Listeners(registerListener(castClass(event.getSuperclass())));
listeners.put(event, result);
}
return result;
}
public class EventListener implements Subscription {
Class<Event> event;
Consumer<Event> listener;
public EventListener(Class<Event> event, Consumer<Event> listener) {
this.event = event;
this.listener = listener;
}
@Override
public void unsubscribe() { registerListener(event).removeListeners(listener); }
@Override
public Class<Event> type() { return event; }
}
public static record MethodListener(MethodHandle handle) implements Consumer<Event> {
@Override
public void accept(Event t) {
try { handle.invoke(t); }
catch(Throwable e) { e.printStackTrace(); }
}
@Override
public final String toString() {
MethodHandleInfo type = LOOKUP.revealDirect(handle);
return String.format("%s(%s)", type.getDeclaringClass().getCanonicalName(), String.join(", ", type.getMethodType().parameterList().stream().map(Class::getSimpleName).toList()));
}
}
public static record ClassFilter(boolean enabled, Predicate<Class<? extends Event>> event, String message) {
public boolean isInvalid(Class<? extends Event> filter) {
return enabled() && !event().test(filter);
}
}
private void register(SubscribeEvent data, Object obj, List<Subscription> listeners) {
if(data == null || !(obj instanceof Consumer)) return;
validateType(data.value());
registerListener(data.value()).addListener(data.priority(), cast(obj));
listeners.add(new EventListener(castClass(data.value()), cast(obj)));
}
private <T> void find(Class<?> clz, boolean superClasses, Function<Class<?>, T[]> mapper, Consumer<T> result) {
do {
for(T value : mapper.apply(clz)) result.accept(value);
clz = clz.getSuperclass();
}
while(clz != Object.class && superClasses);
}
private void validateType(Class<? extends Event> type) {
if(typeCheck.isInvalid(type)) throw new IllegalStateException(String.format(typeCheck.message(), type.getSimpleName()));
}
@SuppressWarnings("unchecked")
private <T> Consumer<T> cast(Object obj) {
return (Consumer<T>) obj;
}
@SuppressWarnings("unchecked")
private <T> Class<T> castClass(Class<?> clz) {
return (Class<T>) clz;
}
}
@@ -0,0 +1,53 @@
package speiger.src.coreengine.core.events.bus;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.core.events.api.Event;
import speiger.src.coreengine.core.events.api.EventPriority;
import speiger.src.coreengine.core.events.utility.Subscription;
public class Subscriptions {
List<Subscription> subscriptions = new ObjectArrayList<>();
EventBus owner;
Subscriptions(EventBus owner) {
this.owner = owner;
}
public <T extends Event> Subscriptions on(Class<T> clz, Consumer<T> event) {
return on(clz, EventPriority.MEDIUM, event);
}
public <T extends Event> Subscriptions on(Class<T> clz, EventPriority priority, Consumer<T> event) {
subscriptions.add(owner.register(clz, priority, event));
return this;
}
public Subscriptions register(Object obj) {
subscriptions.addAll(owner.register(obj, false));
return this;
}
public Subscriptions registerRecursive(Object obj) {
subscriptions.addAll(owner.register(obj, true));
return this;
}
public void unsubscripe(Class<? extends Event> subType) {
for(Iterator<Subscription> iter = subscriptions.iterator();iter.hasNext();) {
Subscription sub = iter.next();
if(!Objects.equals(sub.type(), subType)) continue;
sub.unsubscribe();
iter.remove();
}
}
public void unsubscibe() {
subscriptions.forEach(Subscription::unsubscribe);
subscriptions.clear();
}
}
@@ -0,0 +1,84 @@
package speiger.src.coreengine.core.events.utility;
import java.util.function.Consumer;
import speiger.src.collections.objects.maps.impl.hash.Object2LongLinkedOpenHashMap;
import speiger.src.collections.objects.maps.interfaces.Object2LongMap;
import speiger.src.coreengine.core.events.api.Event;
import speiger.src.coreengine.core.events.api.ICancelableEvent;
public interface IEventDispatcher {
public static final IEventDispatcher DIRECT = new Direct();
void post(Consumer<Event>[] listeners, Event toPost, IEventExceptionHandler exceptions);
public static class Direct implements IEventDispatcher {
@Override
public void post(Consumer<Event>[] listeners, Event toPost, IEventExceptionHandler exceptions) {
int index = 0;
try {
if(toPost instanceof ICancelableEvent cancelable) {
for(;index<listeners.length;index++) {
listeners[index].accept(toPost);
if(cancelable.isCanceled()) return;
}
return;
}
for(;index<listeners.length;index++) {
listeners[index].accept(toPost);
}
}
catch(Throwable e) {
exceptions.handleException(toPost, listeners, index, e);
}
}
}
public static class Profiled implements IEventDispatcher {
Consumer<ProfileOutput> output;
public Profiled(Consumer<ProfileOutput> output) {
this.output = output;
}
@Override
@SuppressWarnings("unchecked")
public void post(Consumer<Event>[] listeners, Event toPost, IEventExceptionHandler exceptions) {
long start = 0L;
long[] results = new long[listeners.length];
int index = 0;
try {
if(toPost instanceof ICancelableEvent cancelable) {
for(;index<listeners.length;index++) {
long time = handle(listeners[index], toPost);
start += time;
results[index] = time;
if(cancelable.isCanceled()) return;
}
return;
}
for(;index<listeners.length;index++) {
long time = handle(listeners[index], toPost);
start += time;
results[index] = time;
}
}
catch(Throwable e) {
exceptions.handleException(toPost, listeners, index, e);
}
finally {
output.accept(new ProfileOutput(start, (Class<Event>)toPost.getClass(), new Object2LongLinkedOpenHashMap<>(listeners, results)));
}
}
private long handle(Consumer<Event> listener, Event event) {
long time = System.nanoTime();
listener.accept(event);
return System.nanoTime() - time;
}
}
public record ProfileOutput(long total, Class<Event> clz, Object2LongMap<Consumer<Event>> perEvent) {}
}
@@ -0,0 +1,9 @@
package speiger.src.coreengine.core.events.utility;
import java.util.function.Consumer;
import speiger.src.coreengine.core.events.api.Event;
public interface IEventExceptionHandler {
void handleException(Event event, Consumer<Event>[] listeners, int index, Throwable crash);
}
@@ -0,0 +1,82 @@
package speiger.src.coreengine.core.events.utility;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Consumer;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.core.events.api.Event;
import speiger.src.coreengine.core.events.api.EventPriority;
public class Listeners
{
@SuppressWarnings("unchecked")
Queue<Consumer<Event>>[] unsortedListeners = new Queue[EventPriority.values().length];
@SuppressWarnings("unchecked")
Consumer<Event>[] listeners = new Consumer[0];
volatile boolean rebuild = true;
Listeners parent;
List<Listeners> childs = null;
public Listeners() {
for(int i = 0;i<unsortedListeners.length;i++) {
unsortedListeners[i] = new ConcurrentLinkedQueue<>();
}
}
public Listeners(Listeners parent) {
this();
this.parent = parent;
this.parent.addChild(this);
}
public void addChild(Listeners listener) {
if(childs == null) childs = new ObjectArrayList<>();
childs.add(listener);
}
public void addListener(EventPriority priority, Consumer<Event> listener) {
if(unsortedListeners[priority.ordinal()].add(listener)) markDirty();
}
public void removeListeners(Consumer<Event> listener) {
for(int i = 0,m=unsortedListeners.length;i<m;i++) {
if(unsortedListeners[i].remove(listener)) markDirty();
}
}
public void getListeners(EventPriority entry, List<Consumer<Event>> events) {
events.addAll(unsortedListeners[entry.ordinal()]);
if(parent != null) parent.getListeners(entry, events);
}
public Consumer<Event>[] getListeners() {
if(rebuild) {
synchronized(this) {
if(rebuild) rebuildListeners();
}
}
return listeners;
}
private void markDirty() {
if(rebuild) return;
rebuild = true;
if(childs != null) {
for(int i = 0,m=childs.size();i<m;i++) {
childs.get(i).markDirty();
}
}
}
@SuppressWarnings("unchecked")
public void rebuildListeners() {
List<Consumer<Event>> result = new ObjectArrayList<>();
for(EventPriority entry : EventPriority.values()) {
getListeners(entry, result);
}
listeners = result.toArray(new Consumer[result.size()]);
rebuild = false;
}
}
@@ -0,0 +1,8 @@
package speiger.src.coreengine.core.events.utility;
import speiger.src.coreengine.core.events.api.Event;
public interface Subscription {
void unsubscribe();
Class<Event> type();
}
@@ -1,7 +0,0 @@
package speiger.src.coreengine.graphics.api.buffer.states;
public enum IndeciesType {
BYTE,
SHORT,
INT;
}
@@ -1,5 +0,0 @@
package speiger.src.coreengine.graphics.api.core;
public interface CommandBuffer {
int commandCount();
}
@@ -1,30 +0,0 @@
package speiger.src.coreengine.graphics.api.core;
import java.util.List;
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.graphics.api.buffer.states.BufferState;
import speiger.src.coreengine.graphics.api.buffer.states.BufferType;
import speiger.src.coreengine.graphics.api.compute.ComputePipeline;
import speiger.src.coreengine.graphics.api.mesh.Mesh;
import speiger.src.coreengine.graphics.api.sampler.Sampler;
import speiger.src.coreengine.graphics.api.sampler.SamplerSettings;
import speiger.src.coreengine.graphics.api.shader.ShaderPipeline;
import speiger.src.coreengine.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.texture.TextureSettings;
import speiger.src.coreengine.graphics.api.utils.ExecutionType;
import speiger.src.coreengine.input.window.Window;
public interface GraphicsDevice {
Window window();
GraphicsSurface createSurface();
GraphicsCommandBuffer createCommandBuffer(ExecutionType type);
GraphicsCommandQueue queue();
VertexBuffer createBuffer(BufferType type, BufferState state);
VertexBuffer createBuffer(BufferType type, BufferState state, int allocatedBytes);
Texture createTexture(TextureSettings data, int width, int height);
Sampler createSampler(SamplerSettings settings);
Mesh createMesh(Mesh.Builder builder);
TimeQueryPool createQueryPool(int size);
void preloadPipelines(List<ShaderPipeline> graphics, List<ComputePipeline> compute);
}
@@ -1,7 +0,0 @@
package speiger.src.coreengine.graphics.api.core;
import speiger.src.coreengine.graphics.api.utils.GraphicsResource;
public interface GraphicsFence extends GraphicsResource {
boolean awaitCompletion(long timeout);
}
@@ -1,7 +0,0 @@
package speiger.src.coreengine.graphics.api.shader.states;
public enum PolygonMode {
POINT,
LINE,
FILL;
}
@@ -1,10 +0,0 @@
package speiger.src.coreengine.graphics.api.shader.states;
public enum PrimitiveType {
BYTE,
SHORT,
INT,
LONG,
FLOAT,
DOUBLE;
}
@@ -1,6 +0,0 @@
package speiger.src.coreengine.graphics.api.texture.states;
public enum StencilType {
GL_COMPARE_REF_TO_TEXTURE,
GL_NONE
}
@@ -1,10 +0,0 @@
package speiger.src.coreengine.graphics.api.texture.states;
public enum SwizzleMask {
ZERO,
ONE,
RED,
GREEN,
BLUE,
ALPHA;
}
@@ -1,7 +0,0 @@
package speiger.src.coreengine.graphics.api.utils;
public enum AccessType {
READ,
WRITE,
BOTH;
}
@@ -1,6 +0,0 @@
package speiger.src.coreengine.graphics.api.utils;
public enum BufferOwner {
KEPT,
GIVEN;
}
@@ -1,6 +0,0 @@
package speiger.src.coreengine.graphics.api.utils;
public enum ExecutionType {
IMMEDIATE,
RECORDED;
}
@@ -0,0 +1,39 @@
package speiger.src.coreengine.platform.graphics.api.buffer;
public class GrowableVertexBuffer
{
VertexBuffer buffer;
final int bytesPerIndex;
final int limit;
final int startSize;
int currentCapacity;
public GrowableVertexBuffer(VertexBuffer buffer, int bytesPerIndex, int limit, int startSize)
{
this.buffer = buffer;
this.bytesPerIndex = bytesPerIndex;
this.limit = limit;
this.startSize = startSize;
currentCapacity = startSize;
buffer.bind().allocate(startSize * bytesPerIndex).unbind();
}
public VertexBuffer ensureSize(int capacity)
{
if(capacity > currentCapacity)
{
if(currentCapacity == limit)
{
throw new RuntimeException("THIS SHOULD NEVER HAPPEN!: "+currentCapacity+":"+limit);
}
currentCapacity = Math.min(Math.max(currentCapacity + (currentCapacity / 2), capacity), limit);
buffer.bind().grow(currentCapacity * bytesPerIndex).unbind();
}
else if(capacity < currentCapacity / 2 && currentCapacity != 10)
{
currentCapacity = Math.max(10, capacity);
buffer.bind().shrink(currentCapacity * bytesPerIndex).unbind();
}
return buffer;
}
}
@@ -0,0 +1,75 @@
package speiger.src.coreengine.platform.graphics.api.buffer;
public class MultiVertexBuffer {
VertexBuffer buffer;
final int bytesPerIndex;
final int limit;
final int startSize;
final float growRate;
final int padding;
final int[][] offsets;
int currentCapacity;
public MultiVertexBuffer(VertexBuffer buffer, int bytesPerIndex, int limit, int startSize, int padding, float growRate, int[][] offsets) {
super();
this.buffer = buffer;
this.bytesPerIndex = bytesPerIndex;
this.limit = limit;
this.startSize = startSize;
this.padding = padding;
this.growRate = growRate;
this.offsets = offsets;
currentCapacity = startSize;
buffer.bind().allocate(startSize * bytesPerIndex).unbind();
}
public boolean ensureSize(int index, int capacity) {
int[] offset = offsets[index];
int room = offset[2] - offset[0];
if(capacity >= room) {
int newCap = Math.max((int)(room * growRate), capacity + 1);
offset[2] = offset[0] + newCap;
grow(index + 1, newCap - room);
return true;
}
return false;
}
protected void grow(int index, int extra) {
if(index == offsets.length) {
int newCap = offsets[offsets.length - 1][2] + extra;
if(newCap > currentCapacity) {
if(currentCapacity == limit) { throw new RuntimeException("THIS SHOULD NEVER HAPPEN!: "+currentCapacity+":"+limit); }
currentCapacity = Math.min(Math.max(currentCapacity + (currentCapacity / 2), newCap), limit);
buffer.bind().grow(currentCapacity * bytesPerIndex).unbind();
}
return;
}
int startBytes = offsets[index][0] * bytesPerIndex;
int endBytes = offsets[offsets.length - 1][2] * bytesPerIndex;
for(int i = index;i < offsets.length;i++) {
offsets[i][0] += extra;
offsets[i][2] += extra;
}
grow(offsets.length, extra);
buffer.bind().shift(startBytes, endBytes - startBytes, extra * bytesPerIndex).unbind();
}
protected void shrink(int index, int extra) {
if(index == offsets.length) {
int newCap = offsets[offsets.length - 1][2] - extra;
if(newCap < currentCapacity / 2 && currentCapacity != 10) {
currentCapacity = Math.max(10, newCap);
buffer.bind().shrink(currentCapacity * bytesPerIndex).unbind();
}
return;
}
int startBytes = offsets[index][0] * bytesPerIndex;
buffer.bind().shift(startBytes, (offsets[offsets.length - 1][2] * bytesPerIndex) - startBytes, -(extra * bytesPerIndex)).unbind();
for(int i = index;i < offsets.length;i++) {
offsets[i][0] -= extra;
offsets[i][2] -= extra;
}
shrink(offsets.length, extra);
}
}
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.buffer; package speiger.src.coreengine.platform.graphics.api.buffer;
import java.nio.Buffer; import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@@ -8,10 +8,10 @@ import org.jspecify.annotations.NonNull;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import speiger.src.collections.ints.misc.pairs.IntObjectPair; import speiger.src.collections.ints.misc.pairs.IntObjectPair;
import speiger.src.coreengine.graphics.api.buffer.states.BufferState; import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferState;
import speiger.src.coreengine.graphics.api.buffer.states.BufferType; import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
import speiger.src.coreengine.graphics.api.utils.BufferOwner; import speiger.src.coreengine.platform.graphics.api.utils.BufferOwner;
import speiger.src.coreengine.graphics.api.utils.GraphicsResource; import speiger.src.coreengine.platform.graphics.api.utils.GraphicsResource;
public abstract class VertexBuffer implements GraphicsResource { public abstract class VertexBuffer implements GraphicsResource {
protected final BufferType type; protected final BufferType type;
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.buffer.states; package speiger.src.coreengine.platform.graphics.api.buffer.states;
public enum BufferState { public enum BufferState {
STATIC_DRAW, STATIC_DRAW,
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.buffer.states; package speiger.src.coreengine.platform.graphics.api.buffer.states;
public enum BufferType { public enum BufferType {
ARRAY_BUFFER, ARRAY_BUFFER,
@@ -0,0 +1,7 @@
package speiger.src.coreengine.platform.graphics.api.buffer.states;
public enum IndeciesType {
BYTE,
SHORT,
INT;
}
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.compute; package speiger.src.coreengine.platform.graphics.api.compute;
public enum BarrierType { public enum BarrierType {
MESH_BUFFER, MESH_BUFFER,
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.compute; package speiger.src.coreengine.platform.graphics.api.compute;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -6,11 +6,11 @@ import java.util.Objects;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.lists.ObjectList; import speiger.src.collections.objects.lists.ObjectList;
import speiger.src.coreengine.assets.api.ID; import speiger.src.coreengine.assets.api.ID;
import speiger.src.coreengine.graphics.api.shader.states.Bindings.BufferBinding; import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.BufferBinding;
import speiger.src.coreengine.graphics.api.shader.states.Bindings.BufferMode; import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.BufferMode;
import speiger.src.coreengine.graphics.api.shader.states.Bindings.TextureBinding; import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.TextureBinding;
import speiger.src.coreengine.graphics.api.shader.states.Bindings.TextureMode; import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.TextureMode;
import speiger.src.coreengine.graphics.api.texture.states.TextureType; import speiger.src.coreengine.platform.graphics.api.texture.states.TextureType;
public record ComputePipeline(ID id, ID shader, List<BufferBinding> uniforms, List<TextureBinding> textures) { public record ComputePipeline(ID id, ID shader, List<BufferBinding> uniforms, List<TextureBinding> textures) {
@@ -0,0 +1,5 @@
package speiger.src.coreengine.platform.graphics.api.core;
public interface CommandBuffer {
int commandCount();
}
@@ -1,12 +1,12 @@
package speiger.src.coreengine.graphics.api.core; package speiger.src.coreengine.platform.graphics.api.core;
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer; import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.graphics.api.compute.BarrierType; import speiger.src.coreengine.platform.graphics.api.compute.BarrierType;
import speiger.src.coreengine.graphics.api.compute.ComputePipeline; import speiger.src.coreengine.platform.graphics.api.compute.ComputePipeline;
import speiger.src.coreengine.graphics.api.sampler.Sampler; import speiger.src.coreengine.platform.graphics.api.sampler.Sampler;
import speiger.src.coreengine.graphics.api.texture.Texture; import speiger.src.coreengine.platform.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.utils.AccessType; import speiger.src.coreengine.platform.graphics.api.utils.AccessType;
import speiger.src.coreengine.graphics.api.utils.GraphicsResource; import speiger.src.coreengine.platform.graphics.api.utils.GraphicsResource;
public interface ComputeCommandBuffer extends GraphicsResource, CommandBuffer { public interface ComputeCommandBuffer extends GraphicsResource, CommandBuffer {
ComputeCommandBuffer begin(); ComputeCommandBuffer begin();
@@ -1,6 +1,6 @@
package speiger.src.coreengine.graphics.api.core; package speiger.src.coreengine.platform.graphics.api.core;
import speiger.src.coreengine.input.window.Window; import speiger.src.coreengine.platform.input.window.Window;
public interface Graphics { public interface Graphics {
public String getName(); public String getName();
@@ -1,12 +1,12 @@
package speiger.src.coreengine.graphics.api.core; package speiger.src.coreengine.platform.graphics.api.core;
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer; import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.graphics.api.mesh.Mesh; import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
import speiger.src.coreengine.graphics.api.sampler.Sampler; import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
import speiger.src.coreengine.graphics.api.shader.ShaderPipeline; import speiger.src.coreengine.platform.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.texture.Texture; import speiger.src.coreengine.platform.graphics.api.utils.AccessType;
import speiger.src.coreengine.graphics.api.utils.AccessType; import speiger.src.coreengine.platform.graphics.api.utils.GraphicsResource;
import speiger.src.coreengine.graphics.api.utils.GraphicsResource; import speiger.src.coreengine.platform.graphics.api.utils.SampledTexture;
public interface GraphicsCommandBuffer extends GraphicsResource, CommandBuffer { public interface GraphicsCommandBuffer extends GraphicsResource, CommandBuffer {
GraphicsCommandBuffer begin(); GraphicsCommandBuffer begin();
@@ -14,7 +14,7 @@ public interface GraphicsCommandBuffer extends GraphicsResource, CommandBuffer {
GraphicsCommandBuffer pipeline(ShaderPipeline pipeline); GraphicsCommandBuffer pipeline(ShaderPipeline pipeline);
GraphicsCommandBuffer mesh(Mesh mesh); GraphicsCommandBuffer mesh(Mesh mesh);
GraphicsCommandBuffer texture(int binding, Texture texture, Sampler sampler); GraphicsCommandBuffer texture(int binding, SampledTexture texture);
GraphicsCommandBuffer texture(int binding, Texture texture, AccessType access); GraphicsCommandBuffer texture(int binding, Texture texture, AccessType access);
GraphicsCommandBuffer uniform(int binding, VertexBuffer buffer); GraphicsCommandBuffer uniform(int binding, VertexBuffer buffer);
@@ -1,11 +1,11 @@
package speiger.src.coreengine.graphics.api.core; package speiger.src.coreengine.platform.graphics.api.core;
import speiger.src.coreengine.graphics.api.shader.states.GraphicsDataType;
import speiger.src.coreengine.graphics.api.target.RenderTarget;
import speiger.src.coreengine.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.texture.states.TextureFormat;
import speiger.src.coreengine.graphics.api.utils.PushableResource;
import speiger.src.coreengine.math.vector.floats.Vec4f; import speiger.src.coreengine.math.vector.floats.Vec4f;
import speiger.src.coreengine.platform.graphics.api.shader.states.GraphicsDataType;
import speiger.src.coreengine.platform.graphics.api.target.RenderTarget;
import speiger.src.coreengine.platform.graphics.api.texture.Texture;
import speiger.src.coreengine.platform.graphics.api.texture.states.TextureFormat;
import speiger.src.coreengine.platform.graphics.api.utils.PushableResource;
public interface GraphicsCommandQueue { public interface GraphicsCommandQueue {
public static final int CLEAR_COLOR = 1; public static final int CLEAR_COLOR = 1;
@@ -0,0 +1,33 @@
package speiger.src.coreengine.platform.graphics.api.core;
import java.util.List;
import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferState;
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
import speiger.src.coreengine.platform.graphics.api.compute.ComputePipeline;
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
import speiger.src.coreengine.platform.graphics.api.sampler.Sampler;
import speiger.src.coreengine.platform.graphics.api.sampler.SamplerSettings;
import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
import speiger.src.coreengine.platform.graphics.api.texture.Texture;
import speiger.src.coreengine.platform.graphics.api.texture.TextureSettings;
import speiger.src.coreengine.platform.graphics.api.utils.ExecutionType;
import speiger.src.coreengine.platform.input.window.Window;
public interface GraphicsDevice {
public static final ScopedValue<GraphicsDevice> SCOPE = ScopedValue.newInstance();
public static GraphicsDevice get() { return SCOPE.get(); }
Window window();
GraphicsSurface createSurface();
GraphicsCommandBuffer createCommandBuffer(ExecutionType type);
GraphicsCommandQueue queue();
VertexBuffer createBuffer(BufferType type, BufferState state);
VertexBuffer createBuffer(BufferType type, BufferState state, int allocatedBytes);
Texture createTexture(TextureSettings data, int width, int height);
Sampler createSampler(SamplerSettings settings);
Mesh createMesh(Mesh.Builder builder);
TimeQueryPool createQueryPool(int size);
void preloadPipelines(List<ShaderPipeline> graphics, List<ComputePipeline> compute);
}
@@ -0,0 +1,7 @@
package speiger.src.coreengine.platform.graphics.api.core;
import speiger.src.coreengine.platform.graphics.api.utils.GraphicsResource;
public interface GraphicsFence extends GraphicsResource {
boolean awaitCompletion(long timeout);
}
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.core; package speiger.src.coreengine.platform.graphics.api.core;
public interface GraphicsSurface { public interface GraphicsSurface {
public void setVsync(boolean value); public void setVsync(boolean value);
@@ -1,8 +1,8 @@
package speiger.src.coreengine.graphics.api.core; package speiger.src.coreengine.platform.graphics.api.core;
import java.util.OptionalLong; import java.util.OptionalLong;
import speiger.src.coreengine.graphics.api.utils.GraphicsResource; import speiger.src.coreengine.platform.graphics.api.utils.GraphicsResource;
public interface TimeQueryPool extends GraphicsResource { public interface TimeQueryPool extends GraphicsResource {
public int size(); public int size();
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.mesh; package speiger.src.coreengine.platform.graphics.api.mesh;
import java.util.Objects; import java.util.Objects;
import java.util.OptionalInt; import java.util.OptionalInt;
@@ -7,11 +7,11 @@ import org.jspecify.annotations.Nullable;
import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap; import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap;
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap; import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer; import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.graphics.api.buffer.states.BufferState; import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferState;
import speiger.src.coreengine.graphics.api.buffer.states.IndeciesType; import speiger.src.coreengine.platform.graphics.api.buffer.states.IndeciesType;
import speiger.src.coreengine.graphics.api.utils.GraphicsResource; import speiger.src.coreengine.platform.graphics.api.utils.GraphicsResource;
import speiger.src.coreengine.graphics.api.vertex.VertexLayout; import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout;
public abstract class Mesh implements GraphicsResource { public abstract class Mesh implements GraphicsResource {
protected final Int2ObjectMap<LayoutInfo> layouts; protected final Int2ObjectMap<LayoutInfo> layouts;
@@ -1,6 +1,6 @@
package speiger.src.coreengine.graphics.api.sampler; package speiger.src.coreengine.platform.graphics.api.sampler;
import speiger.src.coreengine.graphics.api.utils.GraphicsResource; import speiger.src.coreengine.platform.graphics.api.utils.GraphicsResource;
public abstract class Sampler implements GraphicsResource { public abstract class Sampler implements GraphicsResource {
protected SamplerSettings settings; protected SamplerSettings settings;
@@ -1,10 +1,10 @@
package speiger.src.coreengine.graphics.api.sampler; package speiger.src.coreengine.platform.graphics.api.sampler;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import speiger.src.coreengine.graphics.api.sampler.states.BorderMode; import speiger.src.coreengine.platform.graphics.api.sampler.states.BorderMode;
import speiger.src.coreengine.graphics.api.sampler.states.SampleMode; import speiger.src.coreengine.platform.graphics.api.sampler.states.SampleMode;
public record SamplerSettings(BorderMode wrapS, BorderMode wrapT, Optional<BorderMode> wrapR, SampleMode minSample, SampleMode magSample) { public record SamplerSettings(BorderMode wrapS, BorderMode wrapT, Optional<BorderMode> wrapR, SampleMode minSample, SampleMode magSample) {
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.sampler.states; package speiger.src.coreengine.platform.graphics.api.sampler.states;
public enum BorderMode { public enum BorderMode {
CLAMP_TO_EDGE, CLAMP_TO_EDGE,
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.sampler.states; package speiger.src.coreengine.platform.graphics.api.sampler.states;
public enum SampleMode { public enum SampleMode {
NEAREST, NEAREST,
@@ -1,8 +1,8 @@
package speiger.src.coreengine.graphics.api.shader; package speiger.src.coreengine.platform.graphics.api.shader;
import java.util.Objects; import java.util.Objects;
import speiger.src.coreengine.graphics.api.shader.states.GraphicsDataType; import speiger.src.coreengine.platform.graphics.api.shader.states.GraphicsDataType;
public record BufferAttribute(String name, int index, int size, GraphicsDataType type, boolean normal) { public record BufferAttribute(String name, int index, int size, GraphicsDataType type, boolean normal) {
public BufferAttribute { public BufferAttribute {
@@ -1,9 +1,9 @@
package speiger.src.coreengine.graphics.api.shader; package speiger.src.coreengine.platform.graphics.api.shader;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import speiger.src.coreengine.graphics.api.shader.states.BlendFunction; import speiger.src.coreengine.platform.graphics.api.shader.states.BlendFunction;
public record ColorTarget(Optional<BlendFunction> blend, int writeMask) { public record ColorTarget(Optional<BlendFunction> blend, int writeMask) {
public static final int RED = 1; public static final int RED = 1;
@@ -1,8 +1,8 @@
package speiger.src.coreengine.graphics.api.shader; package speiger.src.coreengine.platform.graphics.api.shader;
import java.util.Objects; import java.util.Objects;
import speiger.src.coreengine.graphics.api.utils.AlphaFunction; import speiger.src.coreengine.platform.graphics.api.utils.AlphaFunction;
public record DepthTarget(boolean enabled, AlphaFunction function, boolean write) { public record DepthTarget(boolean enabled, AlphaFunction function, boolean write) {
public static final DepthTarget DEFAULT = new DepthTarget(true, AlphaFunction.GEQUAL, true); public static final DepthTarget DEFAULT = new DepthTarget(true, AlphaFunction.GEQUAL, true);
@@ -1,9 +1,9 @@
package speiger.src.coreengine.graphics.api.shader; package speiger.src.coreengine.platform.graphics.api.shader;
import java.util.Objects; import java.util.Objects;
import speiger.src.coreengine.graphics.api.shader.states.DrawMode; import speiger.src.coreengine.platform.graphics.api.shader.states.DrawMode;
import speiger.src.coreengine.graphics.api.shader.states.PolygonMode; import speiger.src.coreengine.platform.graphics.api.shader.states.PolygonMode;
public record RasterizerState(DrawMode mode, PolygonMode fillMode, boolean cullBack) { public record RasterizerState(DrawMode mode, PolygonMode fillMode, boolean cullBack) {
public static final RasterizerState DEFAULT = new RasterizerState(DrawMode.TRIANGLES, PolygonMode.FILL, true); public static final RasterizerState DEFAULT = new RasterizerState(DrawMode.TRIANGLES, PolygonMode.FILL, true);
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.shader; package speiger.src.coreengine.platform.graphics.api.shader;
import java.util.Collections; import java.util.Collections;
import java.util.EnumMap; import java.util.EnumMap;
@@ -9,15 +9,15 @@ import java.util.Objects;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.lists.ObjectList; import speiger.src.collections.objects.lists.ObjectList;
import speiger.src.coreengine.assets.api.ID; import speiger.src.coreengine.assets.api.ID;
import speiger.src.coreengine.graphics.api.shader.states.Bindings.BufferMode; import speiger.src.coreengine.platform.graphics.api.shader.states.DrawMode;
import speiger.src.coreengine.graphics.api.shader.states.Bindings.TextureBinding; import speiger.src.coreengine.platform.graphics.api.shader.states.PolygonMode;
import speiger.src.coreengine.graphics.api.shader.states.Bindings.TextureMode; import speiger.src.coreengine.platform.graphics.api.shader.states.ShaderType;
import speiger.src.coreengine.graphics.api.shader.states.Bindings.BufferBinding; import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.BufferBinding;
import speiger.src.coreengine.graphics.api.shader.states.DrawMode; import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.BufferMode;
import speiger.src.coreengine.graphics.api.shader.states.PolygonMode; import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.TextureBinding;
import speiger.src.coreengine.graphics.api.shader.states.ShaderType; import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.TextureMode;
import speiger.src.coreengine.graphics.api.texture.states.TextureType; import speiger.src.coreengine.platform.graphics.api.texture.states.TextureType;
import speiger.src.coreengine.graphics.api.vertex.VertexLayout; import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout;
public record ShaderPipeline(ID id, Map<ShaderType, ID> shaders, List<VertexBinding> attributes, List<BufferBinding> uniforms, List<TextureBinding> textures, RasterizerState rasterizer, ColorTarget colorTarget, DepthTarget depthTarget) { public record ShaderPipeline(ID id, Map<ShaderType, ID> shaders, List<VertexBinding> attributes, List<BufferBinding> uniforms, List<TextureBinding> textures, RasterizerState rasterizer, ColorTarget colorTarget, DepthTarget depthTarget) {
@@ -1,8 +1,8 @@
package speiger.src.coreengine.graphics.api.shader; package speiger.src.coreengine.platform.graphics.api.shader;
import speiger.src.collections.objects.collections.ObjectIterable; import speiger.src.collections.objects.collections.ObjectIterable;
import speiger.src.coreengine.graphics.api.vertex.VertexLayout; import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout;
import speiger.src.coreengine.graphics.api.vertex.VertexLayout.Element; import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout.Element;
public record VertexBinding(int bindingIndex, VertexLayout layout, int instanceOffset) { public record VertexBinding(int bindingIndex, VertexLayout layout, int instanceOffset) {
public ObjectIterable<Element> elements() { public ObjectIterable<Element> elements() {
@@ -1,8 +1,8 @@
package speiger.src.coreengine.graphics.api.shader.states; package speiger.src.coreengine.platform.graphics.api.shader.states;
import java.util.Objects; import java.util.Objects;
import speiger.src.coreengine.graphics.api.texture.states.TextureType; import speiger.src.coreengine.platform.graphics.api.texture.states.TextureType;
public class Bindings { public class Bindings {
public record BufferBinding(String name, int binding, int slot, int bytes, BufferMode mode) { public record BufferBinding(String name, int binding, int slot, int bytes, BufferMode mode) {
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.shader.states; package speiger.src.coreengine.platform.graphics.api.shader.states;
public enum BlendFactor { public enum BlendFactor {
ZERO, ZERO,
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.shader.states; package speiger.src.coreengine.platform.graphics.api.shader.states;
public record BlendFunction(BlendFactor colorSource, BlendFactor alphaSource, BlendFactor colorTarget, BlendFactor alphaTarget) { public record BlendFunction(BlendFactor colorSource, BlendFactor alphaSource, BlendFactor colorTarget, BlendFactor alphaTarget) {
public static final BlendFunction DEFAULT = new BlendFunction(BlendFactor.ONE, BlendFactor.ZERO); public static final BlendFunction DEFAULT = new BlendFunction(BlendFactor.ONE, BlendFactor.ZERO);
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.shader.states; package speiger.src.coreengine.platform.graphics.api.shader.states;
public enum DrawMode { public enum DrawMode {
POINT(1), POINT(1),
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.shader.states; package speiger.src.coreengine.platform.graphics.api.shader.states;
public enum GraphicsDataType { public enum GraphicsDataType {
BYTE("byte", 1, PrimitiveType.BYTE), BYTE("byte", 1, PrimitiveType.BYTE),
@@ -0,0 +1,7 @@
package speiger.src.coreengine.platform.graphics.api.shader.states;
public enum PolygonMode {
POINT,
LINE,
FILL;
}
@@ -0,0 +1,10 @@
package speiger.src.coreengine.platform.graphics.api.shader.states;
public enum PrimitiveType {
BYTE,
SHORT,
INT,
LONG,
FLOAT,
DOUBLE;
}
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.shader.states; package speiger.src.coreengine.platform.graphics.api.shader.states;
public enum ShaderType { public enum ShaderType {
VERTEX, VERTEX,
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.target; package speiger.src.coreengine.platform.graphics.api.target;
public sealed interface RenderTarget permits ScreenTarget, TextureTarget { public sealed interface RenderTarget permits ScreenTarget, TextureTarget {
} }
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.target; package speiger.src.coreengine.platform.graphics.api.target;
public final class ScreenTarget implements RenderTarget { public final class ScreenTarget implements RenderTarget {
public static final ScreenTarget INSTANCE = new ScreenTarget(); public static final ScreenTarget INSTANCE = new ScreenTarget();
@@ -1,8 +1,8 @@
package speiger.src.coreengine.graphics.api.target; package speiger.src.coreengine.platform.graphics.api.target;
import speiger.src.coreengine.assets.api.ID; import speiger.src.coreengine.assets.api.ID;
import speiger.src.coreengine.graphics.api.texture.Texture; import speiger.src.coreengine.platform.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.texture.states.TextureType; import speiger.src.coreengine.platform.graphics.api.texture.states.TextureType;
public record TextureTarget(ID id, Texture color, Texture depth) implements RenderTarget { public record TextureTarget(ID id, Texture color, Texture depth) implements RenderTarget {
public TextureTarget { public TextureTarget {
@@ -1,6 +1,6 @@
package speiger.src.coreengine.graphics.api.texture; package speiger.src.coreengine.platform.graphics.api.texture;
import speiger.src.coreengine.graphics.api.utils.GraphicsResource; import speiger.src.coreengine.platform.graphics.api.utils.GraphicsResource;
public abstract class Texture implements GraphicsResource { public abstract class Texture implements GraphicsResource {
final TextureSettings settings; final TextureSettings settings;
@@ -1,14 +1,14 @@
package speiger.src.coreengine.graphics.api.texture; package speiger.src.coreengine.platform.graphics.api.texture;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalInt; import java.util.OptionalInt;
import speiger.src.collections.objects.lists.ImmutableObjectList; import speiger.src.collections.objects.lists.ImmutableObjectList;
import speiger.src.coreengine.graphics.api.texture.states.StencilType; import speiger.src.coreengine.platform.graphics.api.texture.states.StencilType;
import speiger.src.coreengine.graphics.api.texture.states.SwizzleMask; import speiger.src.coreengine.platform.graphics.api.texture.states.SwizzleMask;
import speiger.src.coreengine.graphics.api.texture.states.TextureFormat; import speiger.src.coreengine.platform.graphics.api.texture.states.TextureFormat;
import speiger.src.coreengine.graphics.api.texture.states.TextureType; import speiger.src.coreengine.platform.graphics.api.texture.states.TextureType;
public record TextureSettings(TextureType type, TextureFormat internal, boolean generateMipmapping, OptionalInt baseLevel, OptionalInt maxLevel, ImmutableObjectList<Optional<SwizzleMask>> swizzle, Optional<StencilType> stencilType) { public record TextureSettings(TextureType type, TextureFormat internal, boolean generateMipmapping, OptionalInt baseLevel, OptionalInt maxLevel, ImmutableObjectList<Optional<SwizzleMask>> swizzle, Optional<StencilType> stencilType) {
@@ -0,0 +1,210 @@
package speiger.src.coreengine.platform.graphics.api.texture.atlas;
import java.util.List;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.utils.ObjectIterables;
import speiger.src.collections.utils.HashUtil;
import speiger.src.coreengine.assets.api.ID;
import speiger.src.coreengine.platform.graphics.api.texture.atlas.AtlasStitcher.Entry;
/**
* Inspired by: <a href=https://github.com/lukaszdk/texture-atlas-generator/blob/master/AtlasGenerator.java>AtlasGenerator</a>
*/
public class AtlasStitcher<T extends Entry> {
final int maxWidth;
final int maxHeight;
int width;
int height;
int pixelsUsed;
boolean valid = true;
List<Record<T>> toStitch = new ObjectArrayList<>();
Slot<T> slot = null;
public AtlasStitcher(int bounds) {
this(bounds, bounds);
}
public AtlasStitcher(int maxWidth, int maxHeight) {
this.maxWidth = maxWidth;
this.maxHeight = maxHeight;
if(maxWidth < 256 || maxHeight < 256) throw new IndexOutOfBoundsException("Minimum Size of the Maximum Size has to be 256x256 pixels");
}
public int width() { return width; }
public int height() { return height; }
public boolean isValid() { return valid; }
public void add(T entry) { add(new Record<>(entry)); }
public void addAll(Iterable<? extends T> iterables) { ObjectIterables.map(iterables, Record<T>::new).forEach(this::add); }
@SuppressWarnings("unchecked")
public void addAll(T...entries) {
for(T entry : entries) {
add(new Record<>(entry));
}
}
private void add(Record<T> entry) {
toStitch.add(entry);
pixelsUsed += entry.pixels();
}
public void stitch() {
toStitch.sort(null);
int expected = HashUtil.nextPowerOfTwo((int)Math.sqrt(pixelsUsed)) >> 1;
if(expected > maxWidth && expected > maxHeight) {
valid = false;
return;
}
for(Record<T> entry : toStitch) {
if(!addToSlot(entry)) {
valid = false;
return;
}
}
}
public void process(IAtlasScanner<T> scanner) {
if(slot == null) return;
slot.scan(scanner);
}
private boolean addToSlot(Record<T> entry) {
if(slot != null && slot.insert(entry)) return true;
if(expand(entry)) {
width = slot.width;
height = slot.height;
return true;
}
return false;
}
private boolean expand(Record<T> entry) {
int width = HashUtil.nextPowerOfTwo(entry.width());
int height = HashUtil.nextPowerOfTwo(entry.height());
if(width > maxWidth || height > maxHeight) return false;
if(slot == null) {
int min = HashUtil.nextPowerOfTwo((int)Math.sqrt(pixelsUsed)) / 2;
slot = new Slot<>(0, 0, Math.max(width, min), Math.max(height, min));
return slot.insert(entry);
}
if(width > slot.width) {
if(slot.height * 2 > maxHeight) return false;
slot = new Slot<>(slot, width - slot.width, slot.height);
return slot.insert(entry);
}
slot = slot.height >= slot.width ? new Slot<>(slot, slot.width, 0) : new Slot<>(slot, 0, slot.height);
return slot.insert(entry);
}
private static record Record<T extends Entry>(T entry, int width, int height) implements Comparable<Record<T>> {
public Record(T entry) {
this(entry, entry.width(), entry.height());
}
public int pixels() { return width() * height(); }
@Override
public int compareTo(Record<T> o) {
int comp = Integer.compare(o.height, height);
if(comp != 0) return comp;
comp = Integer.compare(o.width, width);
if(comp != 0) return comp;
return entry.id().compareTo(o.entry.id());
}
}
private static class Slot<T extends Entry> {
int x;
int y;
int width;
int height;
Record<T> record;
Slot<T>[] children = null;
public Slot(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
@SuppressWarnings("unchecked")
public Slot(Slot<T> slot, int eWidth, int eHeight) {
x = 0;
y = 0;
width = slot.width + eWidth;
height = slot.height + eHeight;
children = new Slot[eWidth > 0 && eHeight > 0 ? 3 : 2];
children[0] = slot;
expandSlot(slot.width, slot.height, eWidth, eHeight);
}
public boolean isLeaf() { return children == null; }
public void scan(IAtlasScanner<T> scanner) {
if(record != null) {
scanner.accept(record.entry(), x, y);
return;
}
if(children != null) {
for(int i = 0,m = children.length;i < m;i++) {
children[i].scan(scanner);
}
}
}
@SuppressWarnings("unchecked")
public boolean insert(Record<T> record) {
if(isLeaf()) {
int rw = record.width();
int rh = record.height();
if(this.record != null || rw > width || rh > height) return false;
if(rw == width && rh == height) {
this.record = record;
return true;
}
int dw = width - rw;
int dh = height - rh;
children = new Slot[dw > 0 && dh > 0 ? 3 : 2];
children[0] = new Slot<>(x, y, rw, rh);
expandSlot(rw, rh, dw, dh);
return children[0].insert(record);
}
for(int i = 0,m = children.length;i < m;i++) {
if(children[i].insert(record)) return true;
}
return false;
}
private void expandSlot(int rw, int rh, int dw, int dh) {
if(dw > 0 && dh > 0) {
if(dw >= dh) {
children[1] = new Slot<>(x + rw, y, dw, rh);
children[2] = new Slot<>(x, y + rh, width, dh);
}
else {
children[1] = new Slot<>(x, y + rh, rw, dh);
children[2] = new Slot<>(x + rw, y, dw, height);
}
}
else if(dw == 0) children[1] = new Slot<>(x, y + rh, rw, dh);
else if(dh == 0) children[1] = new Slot<>(x + rw, y, dw, rh);
}
@Override
public String toString() {
return "Slot[x="+x+", y="+y+", w="+width+", h="+height+"]";
}
}
public static interface IAtlasScanner<T> {
public void accept(T entry, int x, int y);
}
public static interface Entry {
public ID id();
public int width();
public int height();
}
}
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.texture.drawable; package speiger.src.coreengine.platform.graphics.api.texture.drawable;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Objects; import java.util.Objects;
@@ -12,11 +12,11 @@ import org.lwjgl.util.freetype.FT_Face;
import org.lwjgl.util.freetype.FT_GlyphSlot; import org.lwjgl.util.freetype.FT_GlyphSlot;
import org.lwjgl.util.freetype.FreeType; import org.lwjgl.util.freetype.FreeType;
import speiger.src.coreengine.graphics.api.core.GraphicsCommandQueue;
import speiger.src.coreengine.graphics.api.shader.states.GraphicsDataType;
import speiger.src.coreengine.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.texture.states.TextureFormat;
import speiger.src.coreengine.math.color.ColorSpaces; import speiger.src.coreengine.math.color.ColorSpaces;
import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandQueue;
import speiger.src.coreengine.platform.graphics.api.shader.states.GraphicsDataType;
import speiger.src.coreengine.platform.graphics.api.texture.Texture;
import speiger.src.coreengine.platform.graphics.api.texture.states.TextureFormat;
public class Drawable implements IDrawable, AutoCloseable { public class Drawable implements IDrawable, AutoCloseable {
TextureFormat format; TextureFormat format;
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.texture.drawable; package speiger.src.coreengine.platform.graphics.api.texture.drawable;
import speiger.src.coreengine.math.color.ColorSpaces; import speiger.src.coreengine.math.color.ColorSpaces;
@@ -0,0 +1,6 @@
package speiger.src.coreengine.platform.graphics.api.texture.states;
public enum StencilType {
GL_COMPARE_REF_TO_TEXTURE,
GL_NONE
}
@@ -0,0 +1,10 @@
package speiger.src.coreengine.platform.graphics.api.texture.states;
public enum SwizzleMask {
ZERO,
ONE,
RED,
GREEN,
BLUE,
ALPHA;
}
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.texture.states; package speiger.src.coreengine.platform.graphics.api.texture.states;
public enum TextureFormat { public enum TextureFormat {
R(1, 0, -1, -1, -1), R(1, 0, -1, -1, -1),
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.texture.states; package speiger.src.coreengine.platform.graphics.api.texture.states;
public enum TextureType { public enum TextureType {
TEXTURE_1D, TEXTURE_1D,
@@ -0,0 +1,7 @@
package speiger.src.coreengine.platform.graphics.api.utils;
public enum AccessType {
READ,
WRITE,
BOTH;
}
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.utils; package speiger.src.coreengine.platform.graphics.api.utils;
public enum AlphaFunction { public enum AlphaFunction {
NEVER, NEVER,
@@ -0,0 +1,6 @@
package speiger.src.coreengine.platform.graphics.api.utils;
public enum BufferOwner {
KEPT,
GIVEN;
}
@@ -0,0 +1,6 @@
package speiger.src.coreengine.platform.graphics.api.utils;
public enum ExecutionType {
IMMEDIATE,
RECORDED;
}
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.utils; package speiger.src.coreengine.platform.graphics.api.utils;
public interface GraphicsResource extends AutoCloseable { public interface GraphicsResource extends AutoCloseable {
public boolean isRemoved(); public boolean isRemoved();
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.utils; package speiger.src.coreengine.platform.graphics.api.utils;
public interface PushableResource extends AutoCloseable { public interface PushableResource extends AutoCloseable {
@Override @Override
@@ -0,0 +1,13 @@
package speiger.src.coreengine.platform.graphics.api.utils;
import java.util.Objects;
import speiger.src.coreengine.platform.graphics.api.sampler.Sampler;
import speiger.src.coreengine.platform.graphics.api.texture.Texture;
public record SampledTexture(Texture texture, Sampler sampler) {
public SampledTexture {
Objects.requireNonNull(texture);
Objects.requireNonNull(sampler);
}
}
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.utils; package speiger.src.coreengine.platform.graphics.api.utils;
import java.util.Objects; import java.util.Objects;
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.vertex; package speiger.src.coreengine.platform.graphics.api.vertex;
import java.util.Objects; import java.util.Objects;
@@ -10,8 +10,8 @@ import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.lists.ObjectList; import speiger.src.collections.objects.lists.ObjectList;
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap; import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap;
import speiger.src.collections.objects.utils.ObjectIterators; import speiger.src.collections.objects.utils.ObjectIterators;
import speiger.src.coreengine.graphics.api.shader.states.GraphicsDataType; import speiger.src.coreengine.platform.graphics.api.shader.states.GraphicsDataType;
import speiger.src.coreengine.graphics.api.vertex.VertexLayout.Element; import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout.Element;
public class VertexLayout implements ObjectIterable<Element> { public class VertexLayout implements ObjectIterable<Element> {
Object2ObjectMap<String, Element> mapped = Object2ObjectMap.builder().linkedMap(); Object2ObjectMap<String, Element> mapped = Object2ObjectMap.builder().linkedMap();
@@ -0,0 +1,50 @@
package speiger.src.coreengine.platform.graphics.api.vertex.builder;
import speiger.src.coreengine.math.vector.matrix.Matrix4f;
import speiger.src.coreengine.platform.graphics.api.shader.states.DrawMode;
import speiger.src.coreengine.platform.graphics.api.shader.states.GraphicsDataType;
import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout.Element;
import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout.Usage;
public interface IVertexBuffer extends IVertexBuilder {
Element current();
IVertexBuffer next();
BufferResult finish();
default IVertexBuffer validate(Usage usage, GraphicsDataType type, int size) { return validate(this, usage, type, size); }
IVertexBuffer put(int byteOffset, byte value);
IVertexBuffer putShort(int byteOffset, short value);
IVertexBuffer putInt(int byteOffset, int value);
IVertexBuffer putFloat(int byteOffset, float value);
int vertecies();
@Override
default IVertexBuffer pos(float x, float y) { return validate(Usage.POS, GraphicsDataType.FLOAT, 2).putFloat(0, x).putFloat(4, y).next(); }
@Override
default IVertexBuffer pos(float x, float y, float z) { return validate(Usage.POS, GraphicsDataType.FLOAT, 3).putFloat(0, x).putFloat(4, y).putFloat(8, z).next(); }
@Override
default IVertexBuffer rgb(int r, int g, int b) { return validate(Usage.COLOR, GraphicsDataType.UNSIGNED_BYTE, 3).put(0, (byte)r).put(1, (byte)g).put(2, (byte)b).next(); }
@Override
default IVertexBuffer rgba(int r, int g, int b, int a) { return validate(Usage.COLOR, GraphicsDataType.UNSIGNED_BYTE, 4).put(0, (byte)r).put(1, (byte)g).put(2, (byte)b).put(3, (byte)a).next(); }
@Override
default IVertexBuffer tex(float u, float v) { return validate(Usage.UV, GraphicsDataType.FLOAT, 2).putFloat(0, u).putFloat(4, v).next(); }
@Override
default IVertexBuffer normal(float x, float y, float z) { return validate(Usage.NORMAL, GraphicsDataType.FLOAT, 3).putFloat(0, x).putFloat(4, y).putFloat(8, z).next(); }
default IVertexBuffer matrix(Matrix4f mat) {
validate(Usage.MATRIX, GraphicsDataType.FLOAT, 16);
for(int i = 0;i<16;i++) {
putFloat(i*4, mat.get(i));
}
return next();
}
static IVertexBuffer validate(IVertexBuffer builder, Usage usage, GraphicsDataType type, int size) {
Element current = builder.current();
if(current.size() == size && current.usage() == usage && current.type() == type) return builder;
throw new IllegalStateException("Expected State [Usage="+current.usage()+", Size="+current.size()+", Type="+current.type()+"], wasn't present. Actual State [Usage="+usage+", Size="+size+", Type="+type+"]");
}
public record BufferResult(DrawMode mode, int startVertex, int endVertex) {}
}
@@ -0,0 +1,16 @@
package speiger.src.coreengine.platform.graphics.api.vertex.builder;
import speiger.src.coreengine.math.color.ColorUtils;
public interface IVertexBuilder {
IVertexBuffer pos(float x, float y);
IVertexBuffer pos(float x, float y, float z);
default IVertexBuffer rgb(int color) { return rgb(ColorUtils.getR(color), ColorUtils.getG(color), ColorUtils.getB(color)); }
IVertexBuffer rgb(int r, int g, int b);
default IVertexBuffer rgba(int color) { return rgba(ColorUtils.getR(color), ColorUtils.getG(color), ColorUtils.getB(color), ColorUtils.getA(color)); }
IVertexBuffer rgba(int r, int g, int b, int a);
IVertexBuffer tex(float u, float v);
IVertexBuffer normal(float x, float y, float z);
}
@@ -0,0 +1,161 @@
package speiger.src.coreengine.platform.graphics.api.vertex.builder;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import speiger.src.coreengine.platform.graphics.api.shader.states.DrawMode;
import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout;
import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout.Element;
public class VertexBuilder implements IVertexBuffer, AutoCloseable {
boolean noFree = false;
DrawMode mode;
ByteBuffer buffer;
VertexLayout layout;
int vertecies;
int index;
int totalStoredBytes;
int vertexBytes;
int elementBytes;
int lastVertecies = 0;
public VertexBuilder(int size) {
this(MemoryUtil.memAlloc(size));
}
public VertexBuilder(ByteBuffer buffer) {
this.buffer = buffer;
}
public VertexBuilder withoutFree() {
noFree = true;
return this;
}
public VertexBuilder start(DrawMode mode, VertexLayout layout) {
if(index != 0) throw new IllegalStateException("Can't change Layout mid Writing");
this.mode = mode;
this.layout = layout;
return this;
}
public VertexBuilder reset() {
index = 0;
vertecies = 0;
elementBytes = 0;
totalStoredBytes = 0;
vertexBytes = 0;
lastVertecies = 0;
return this;
}
public boolean hasVertecies() { return lastVertecies < vertecies; }
public boolean is(DrawMode mode, VertexLayout layout) { return this.mode == mode && this.layout == layout; }
public DrawMode mode() { return mode; }
public VertexLayout getFormat() { return layout; }
@Override
public void close() {
if(buffer == null || !buffer.isDirect()) return;
if(!noFree) MemoryUtil.memFree(buffer);
buffer = null;
}
@Override
public Element current() {
return layout.get(index);
}
@Override
public BufferResult finish() {
BufferResult result = new BufferResult(mode, lastVertecies, vertecies);
lastVertecies = vertecies;
return result;
}
@Override
public VertexBuilder next() {
index = (index + 1) % layout.size();
totalStoredBytes += elementBytes;
vertexBytes += elementBytes;
elementBytes = 0;
if(index == 0) {
vertecies++;
vertexBytes = 0;
ensureCapacity(totalStoredBytes + (layout.bytes() * mode.primitiveLength()));
}
return this;
}
@Override
public VertexBuilder put(int byteOffset, byte value) {
buffer.put(totalStoredBytes + byteOffset, value);
elementBytes+=1;
return this;
}
@Override
public VertexBuilder putShort(int byteOffset, short value) {
buffer.putShort(totalStoredBytes + byteOffset, value);
elementBytes+=2;
return this;
}
@Override
public VertexBuilder putInt(int byteOffset, int value) {
buffer.putInt(totalStoredBytes + byteOffset, value);
elementBytes+=4;
return this;
}
@Override
public VertexBuilder putFloat(int byteOffset, float value) {
buffer.putFloat(totalStoredBytes + byteOffset, value);
elementBytes+=4;
return this;
}
@Override
public int vertecies() {
return vertecies;
}
public VertexBuilder putBulk(byte[] source) {
if(index != 0) throw new IllegalStateException("Can't do bulk iterations when mid Building");
ensureCapacity(source.length + layout.bytes());
buffer.position(totalStoredBytes).put(source).position(0);
vertecies += source.length / layout.bytes();
totalStoredBytes += source.length;
return this;
}
public VertexBuilder putBulk(ByteBuffer source) {
if(index != 0) throw new IllegalStateException("Can't do bulk iterations when mid Building");
ensureCapacity(source.limit() + layout.bytes());
buffer.position(totalStoredBytes).put(source).position(0);
vertecies += source.limit() / layout.bytes();
totalStoredBytes += source.limit();
return this;
}
public VertexBuilder copy(ByteBuffer buffer) {
buffer.put(buffer.position(), this.buffer, 0, totalStoredBytes);
return this;
}
public byte[] bytes() {
byte[] data = new byte[totalStoredBytes];
buffer.get(0, data);
return data;
}
private void ensureCapacity(int newValue) {
if(totalStoredBytes + newValue >= buffer.capacity()) {
int oldSize = buffer.capacity();
int newSize = Math.max(oldSize + (oldSize >> 1), oldSize + newValue);
buffer = buffer.isDirect() ? MemoryUtil.memRealloc(buffer, newSize) : ByteBuffer.allocate(newSize).put(buffer).position(0);
}
}
}
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.opengl.buffer; package speiger.src.coreengine.platform.graphics.opengl.buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.List; import java.util.List;
@@ -10,13 +10,11 @@ import org.lwjgl.opengl.GL45;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import speiger.src.collections.ints.misc.pairs.IntObjectPair; import speiger.src.collections.ints.misc.pairs.IntObjectPair;
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer; import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.graphics.api.buffer.states.BufferState; import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferState;
import speiger.src.coreengine.graphics.api.buffer.states.BufferType; import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
import speiger.src.coreengine.graphics.api.utils.BufferOwner; import speiger.src.coreengine.platform.graphics.api.utils.BufferOwner;
import speiger.src.coreengine.graphics.opengl.utils.GLUtils; import speiger.src.coreengine.platform.graphics.opengl.utils.GLUtils;
import speiger.src.coreengine.rendering.utils.AllocationTracker;
import speiger.src.coreengine.utils.io.GameLog;
public class GLVertexBuffer extends VertexBuffer { public class GLVertexBuffer extends VertexBuffer {
int id; int id;
@@ -98,7 +96,7 @@ public class GLVertexBuffer extends VertexBuffer {
buffer.put(entry.getValue()); buffer.put(entry.getValue());
} }
buffer.flip(); buffer.flip();
if(!GL45.glUnmapNamedBuffer(id)) GameLog.info("Memory Corruption?"); if(!GL45.glUnmapNamedBuffer(id)) System.out.println("Memory Corruption?");
} }
return this; return this;
} }
@@ -132,7 +130,6 @@ public class GLVertexBuffer extends VertexBuffer {
if(source < 0 || source + length >= size) throw new ArrayIndexOutOfBoundsException(); if(source < 0 || source + length >= size) throw new ArrayIndexOutOfBoundsException();
if(dest < 0 || dest + length >= size) throw new ArrayIndexOutOfBoundsException(); if(dest < 0 || dest + length >= size) throw new ArrayIndexOutOfBoundsException();
GL45.glCopyNamedBufferSubData(id, id, source, dest, length); GL45.glCopyNamedBufferSubData(id, id, source, dest, length);
AllocationTracker.INSTANCE.addGPUBytes(length*2);
return this; return this;
} }
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.opengl.core; package speiger.src.coreengine.platform.graphics.opengl.core;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Deque; import java.util.Deque;
@@ -11,24 +11,24 @@ import org.lwjgl.opengl.GL32;
import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45;
import speiger.src.coreengine.assets.api.ID; import speiger.src.coreengine.assets.api.ID;
import speiger.src.coreengine.graphics.api.core.CommandBuffer;
import speiger.src.coreengine.graphics.api.core.GraphicsCommandQueue;
import speiger.src.coreengine.graphics.api.shader.states.GraphicsDataType;
import speiger.src.coreengine.graphics.api.target.RenderTarget;
import speiger.src.coreengine.graphics.api.target.ScreenTarget;
import speiger.src.coreengine.graphics.api.target.TextureTarget;
import speiger.src.coreengine.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.texture.states.TextureFormat;
import speiger.src.coreengine.graphics.api.utils.PushableResource;
import speiger.src.coreengine.graphics.opengl.texture.FrameBufferCache;
import speiger.src.coreengine.graphics.opengl.texture.GLTexture;
import speiger.src.coreengine.graphics.opengl.utils.GLStates;
import speiger.src.coreengine.graphics.opengl.utils.GLUtils;
import speiger.src.coreengine.graphics.opengl.utils.ViewPortStack;
import speiger.src.coreengine.graphics.opengl.utils.states.ScissorState;
import speiger.src.coreengine.input.window.Window;
import speiger.src.coreengine.math.vector.floats.Vec4f; import speiger.src.coreengine.math.vector.floats.Vec4f;
import speiger.src.coreengine.math.vector.ints.Vec4i; import speiger.src.coreengine.math.vector.ints.Vec4i;
import speiger.src.coreengine.platform.graphics.api.core.CommandBuffer;
import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandQueue;
import speiger.src.coreengine.platform.graphics.api.shader.states.GraphicsDataType;
import speiger.src.coreengine.platform.graphics.api.target.RenderTarget;
import speiger.src.coreengine.platform.graphics.api.target.ScreenTarget;
import speiger.src.coreengine.platform.graphics.api.target.TextureTarget;
import speiger.src.coreengine.platform.graphics.api.texture.Texture;
import speiger.src.coreengine.platform.graphics.api.texture.states.TextureFormat;
import speiger.src.coreengine.platform.graphics.api.utils.PushableResource;
import speiger.src.coreengine.platform.graphics.opengl.texture.FrameBufferCache;
import speiger.src.coreengine.platform.graphics.opengl.texture.GLTexture;
import speiger.src.coreengine.platform.graphics.opengl.utils.GLStates;
import speiger.src.coreengine.platform.graphics.opengl.utils.GLUtils;
import speiger.src.coreengine.platform.graphics.opengl.utils.ViewPortStack;
import speiger.src.coreengine.platform.graphics.opengl.utils.states.ScissorState;
import speiger.src.coreengine.platform.input.window.Window;
public class GLCommandQueue implements GraphicsCommandQueue { public class GLCommandQueue implements GraphicsCommandQueue {
GLGraphicsDevice device; GLGraphicsDevice device;
@@ -1,7 +1,7 @@
package speiger.src.coreengine.graphics.opengl.core; package speiger.src.coreengine.platform.graphics.opengl.core;
import speiger.src.coreengine.graphics.api.core.GraphicsFence; import speiger.src.coreengine.platform.graphics.api.core.GraphicsFence;
import speiger.src.coreengine.graphics.opengl.core.GLCommandQueue.Frame; import speiger.src.coreengine.platform.graphics.opengl.core.GLCommandQueue.Frame;
public class GLFence implements GraphicsFence { public class GLFence implements GraphicsFence {
boolean removed = false; boolean removed = false;
@@ -1,11 +1,11 @@
package speiger.src.coreengine.graphics.opengl.core; package speiger.src.coreengine.platform.graphics.opengl.core;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GL;
import speiger.src.coreengine.assets.manager.AssetManager; import speiger.src.coreengine.assets.manager.AssetManager;
import speiger.src.coreengine.graphics.api.core.Graphics; import speiger.src.coreengine.platform.graphics.api.core.Graphics;
import speiger.src.coreengine.input.window.Window; import speiger.src.coreengine.platform.input.window.Window;
public class GLGraphics implements Graphics { public class GLGraphics implements Graphics {
AssetManager manager; AssetManager manager;
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.opengl.core; package speiger.src.coreengine.platform.graphics.opengl.core;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.List; import java.util.List;
@@ -10,6 +10,7 @@ import java.util.OptionalInt;
import java.util.function.IntPredicate; import java.util.function.IntPredicate;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12; import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL20;
@@ -37,41 +38,41 @@ import speiger.src.coreengine.assets.api.IAssetProvider;
import speiger.src.coreengine.assets.api.ID; import speiger.src.coreengine.assets.api.ID;
import speiger.src.coreengine.assets.api.MultiAsset; import speiger.src.coreengine.assets.api.MultiAsset;
import speiger.src.coreengine.assets.manager.AssetManager; import speiger.src.coreengine.assets.manager.AssetManager;
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer; import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.graphics.api.buffer.states.BufferState; import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferState;
import speiger.src.coreengine.graphics.api.buffer.states.BufferType; import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
import speiger.src.coreengine.graphics.api.compute.ComputePipeline; import speiger.src.coreengine.platform.graphics.api.compute.ComputePipeline;
import speiger.src.coreengine.graphics.api.core.GraphicsCommandBuffer; import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandBuffer;
import speiger.src.coreengine.graphics.api.core.GraphicsDevice; import speiger.src.coreengine.platform.graphics.api.core.GraphicsDevice;
import speiger.src.coreengine.graphics.api.core.TimeQueryPool; import speiger.src.coreengine.platform.graphics.api.core.TimeQueryPool;
import speiger.src.coreengine.graphics.api.mesh.Mesh; import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
import speiger.src.coreengine.graphics.api.mesh.Mesh.LayoutInfo; import speiger.src.coreengine.platform.graphics.api.mesh.Mesh.LayoutInfo;
import speiger.src.coreengine.graphics.api.sampler.SamplerSettings; import speiger.src.coreengine.platform.graphics.api.sampler.SamplerSettings;
import speiger.src.coreengine.graphics.api.shader.ShaderPipeline; import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
import speiger.src.coreengine.graphics.api.shader.VertexBinding; import speiger.src.coreengine.platform.graphics.api.shader.VertexBinding;
import speiger.src.coreengine.graphics.api.shader.states.Bindings.BufferBinding; import speiger.src.coreengine.platform.graphics.api.shader.states.ShaderType;
import speiger.src.coreengine.graphics.api.shader.states.Bindings.BufferMode; import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.BufferBinding;
import speiger.src.coreengine.graphics.api.shader.states.Bindings.TextureBinding; import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.BufferMode;
import speiger.src.coreengine.graphics.api.shader.states.Bindings.TextureMode; import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.TextureBinding;
import speiger.src.coreengine.graphics.api.shader.states.ShaderType; import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.TextureMode;
import speiger.src.coreengine.graphics.api.texture.TextureSettings; import speiger.src.coreengine.platform.graphics.api.texture.TextureSettings;
import speiger.src.coreengine.graphics.api.texture.states.SwizzleMask; import speiger.src.coreengine.platform.graphics.api.texture.states.SwizzleMask;
import speiger.src.coreengine.graphics.api.texture.states.TextureType; import speiger.src.coreengine.platform.graphics.api.texture.states.TextureType;
import speiger.src.coreengine.graphics.api.utils.ExecutionType; import speiger.src.coreengine.platform.graphics.api.utils.ExecutionType;
import speiger.src.coreengine.graphics.api.vertex.VertexLayout.Element; import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout.Element;
import speiger.src.coreengine.graphics.opengl.buffer.GLVertexBuffer; import speiger.src.coreengine.platform.graphics.opengl.buffer.GLVertexBuffer;
import speiger.src.coreengine.graphics.opengl.mesh.GLMesh; import speiger.src.coreengine.platform.graphics.opengl.mesh.GLMesh;
import speiger.src.coreengine.graphics.opengl.sampler.GLSampler; import speiger.src.coreengine.platform.graphics.opengl.sampler.GLSampler;
import speiger.src.coreengine.graphics.opengl.shader.ShaderCache; import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderCache;
import speiger.src.coreengine.graphics.opengl.shader.ShaderInstance; import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance;
import speiger.src.coreengine.graphics.opengl.shader.ShaderInstance.BufferObject; import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance.BufferObject;
import speiger.src.coreengine.graphics.opengl.shader.ShaderInstance.ShaderStorage; import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance.ShaderStorage;
import speiger.src.coreengine.graphics.opengl.shader.ShaderInstance.TextureObject; import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance.TextureObject;
import speiger.src.coreengine.graphics.opengl.texture.GLTexture; import speiger.src.coreengine.platform.graphics.opengl.texture.GLTexture;
import speiger.src.coreengine.graphics.opengl.utils.GLFunctions; import speiger.src.coreengine.platform.graphics.opengl.utils.GLFunctions;
import speiger.src.coreengine.graphics.opengl.utils.GLStates; import speiger.src.coreengine.platform.graphics.opengl.utils.GLStates;
import speiger.src.coreengine.graphics.opengl.utils.GLUtils; import speiger.src.coreengine.platform.graphics.opengl.utils.GLUtils;
import speiger.src.coreengine.input.window.Window; import speiger.src.coreengine.platform.input.window.Window;
public class GLGraphicsDevice implements GraphicsDevice { public class GLGraphicsDevice implements GraphicsDevice {
static final Map<ID, String> IMPORTS = Object2ObjectMap.builder().<ID, String>map().synchronize(); static final Map<ID, String> IMPORTS = Object2ObjectMap.builder().<ID, String>map().synchronize();
@@ -88,6 +89,7 @@ public class GLGraphicsDevice implements GraphicsDevice {
this.owner = owner; this.owner = owner;
this.manager = manager; this.manager = manager;
this.capabilities = capbilities; this.capabilities = capbilities;
GL.setCapabilities(capbilities);
this.queue = new GLCommandQueue(this); this.queue = new GLCommandQueue(this);
} }
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.opengl.core; package speiger.src.coreengine.platform.graphics.opengl.core;
import java.util.Objects; import java.util.Objects;
@@ -8,26 +8,26 @@ import org.lwjgl.opengl.GL31;
import org.lwjgl.opengl.GL43; import org.lwjgl.opengl.GL43;
import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45;
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer; import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.graphics.api.buffer.states.BufferType; import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
import speiger.src.coreengine.graphics.api.core.GraphicsCommandBuffer; import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandBuffer;
import speiger.src.coreengine.graphics.api.mesh.Mesh; import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
import speiger.src.coreengine.graphics.api.sampler.Sampler; import speiger.src.coreengine.platform.graphics.api.shader.ColorTarget;
import speiger.src.coreengine.graphics.api.shader.ColorTarget; import speiger.src.coreengine.platform.graphics.api.shader.DepthTarget;
import speiger.src.coreengine.graphics.api.shader.DepthTarget; import speiger.src.coreengine.platform.graphics.api.shader.RasterizerState;
import speiger.src.coreengine.graphics.api.shader.RasterizerState; import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
import speiger.src.coreengine.graphics.api.shader.ShaderPipeline; import speiger.src.coreengine.platform.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.texture.Texture; import speiger.src.coreengine.platform.graphics.api.utils.AccessType;
import speiger.src.coreengine.graphics.api.utils.AccessType; import speiger.src.coreengine.platform.graphics.api.utils.SampledTexture;
import speiger.src.coreengine.graphics.api.utils.ScissorsManager; import speiger.src.coreengine.platform.graphics.api.utils.ScissorsManager;
import speiger.src.coreengine.graphics.opengl.buffer.GLVertexBuffer; import speiger.src.coreengine.platform.graphics.opengl.buffer.GLVertexBuffer;
import speiger.src.coreengine.graphics.opengl.mesh.GLMesh; import speiger.src.coreengine.platform.graphics.opengl.mesh.GLMesh;
import speiger.src.coreengine.graphics.opengl.sampler.GLSampler; import speiger.src.coreengine.platform.graphics.opengl.sampler.GLSampler;
import speiger.src.coreengine.graphics.opengl.shader.ShaderInstance; import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance;
import speiger.src.coreengine.graphics.opengl.texture.GLTexture; import speiger.src.coreengine.platform.graphics.opengl.texture.GLTexture;
import speiger.src.coreengine.graphics.opengl.utils.GLScissorsHandler; import speiger.src.coreengine.platform.graphics.opengl.utils.GLScissorsHandler;
import speiger.src.coreengine.graphics.opengl.utils.GLStates; import speiger.src.coreengine.platform.graphics.opengl.utils.GLStates;
import speiger.src.coreengine.graphics.opengl.utils.GLUtils; import speiger.src.coreengine.platform.graphics.opengl.utils.GLUtils;
public class GLImmidateCommandBuffer implements GraphicsCommandBuffer { public class GLImmidateCommandBuffer implements GraphicsCommandBuffer {
GLGraphicsDevice device; GLGraphicsDevice device;
@@ -118,15 +118,14 @@ public class GLImmidateCommandBuffer implements GraphicsCommandBuffer {
} }
@Override @Override
public GraphicsCommandBuffer texture(int binding, Texture texture, Sampler sampler) { public GraphicsCommandBuffer texture(int binding, SampledTexture texture) {
Objects.requireNonNull(texture); Objects.requireNonNull(texture);
Objects.requireNonNull(sampler);
ensureDrawing(); ensureDrawing();
Objects.requireNonNull(shader, "No Pipeline found"); Objects.requireNonNull(shader, "No Pipeline found");
Objects.requireNonNull(shader.samplers().byIndex(binding), "Texture["+binding+"] binding not found"); Objects.requireNonNull(shader.samplers().byIndex(binding), "Texture["+binding+"] binding not found");
GLStates states = device.states; GLStates states = device.states;
states.textures.bind(binding, ((GLTexture)texture).id()); states.textures.bind(binding, ((GLTexture)texture.texture()).id());
states.samplers.bind(binding, ((GLSampler)sampler).id()); states.samplers.bind(binding, ((GLSampler)texture.sampler()).id());
recorded++; recorded++;
return this; return this;
} }
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.opengl.core; package speiger.src.coreengine.platform.graphics.opengl.core;
import java.util.Objects; import java.util.Objects;
@@ -8,20 +8,20 @@ import org.lwjgl.opengl.GL42;
import org.lwjgl.opengl.GL43; import org.lwjgl.opengl.GL43;
import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45;
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer; import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.graphics.api.buffer.states.BufferType; import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
import speiger.src.coreengine.graphics.api.compute.BarrierType; import speiger.src.coreengine.platform.graphics.api.compute.BarrierType;
import speiger.src.coreengine.graphics.api.compute.ComputePipeline; import speiger.src.coreengine.platform.graphics.api.compute.ComputePipeline;
import speiger.src.coreengine.graphics.api.core.ComputeCommandBuffer; import speiger.src.coreengine.platform.graphics.api.core.ComputeCommandBuffer;
import speiger.src.coreengine.graphics.api.sampler.Sampler; import speiger.src.coreengine.platform.graphics.api.sampler.Sampler;
import speiger.src.coreengine.graphics.api.texture.Texture; import speiger.src.coreengine.platform.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.utils.AccessType; import speiger.src.coreengine.platform.graphics.api.utils.AccessType;
import speiger.src.coreengine.graphics.opengl.buffer.GLVertexBuffer; import speiger.src.coreengine.platform.graphics.opengl.buffer.GLVertexBuffer;
import speiger.src.coreengine.graphics.opengl.sampler.GLSampler; import speiger.src.coreengine.platform.graphics.opengl.sampler.GLSampler;
import speiger.src.coreengine.graphics.opengl.shader.ShaderInstance; import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance;
import speiger.src.coreengine.graphics.opengl.texture.GLTexture; import speiger.src.coreengine.platform.graphics.opengl.texture.GLTexture;
import speiger.src.coreengine.graphics.opengl.utils.GLStates; import speiger.src.coreengine.platform.graphics.opengl.utils.GLStates;
import speiger.src.coreengine.graphics.opengl.utils.GLUtils; import speiger.src.coreengine.platform.graphics.opengl.utils.GLUtils;
public class GLImmidateComputeCommandBuffer implements ComputeCommandBuffer { public class GLImmidateComputeCommandBuffer implements ComputeCommandBuffer {
GLGraphicsDevice device; GLGraphicsDevice device;
@@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.opengl.core; package speiger.src.coreengine.platform.graphics.opengl.core;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -10,29 +10,29 @@ import org.lwjgl.opengl.GL43;
import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.graphics.api.buffer.states.BufferType;
import speiger.src.coreengine.graphics.api.buffer.states.IndeciesType;
import speiger.src.coreengine.graphics.api.core.GraphicsCommandBuffer;
import speiger.src.coreengine.graphics.api.mesh.Mesh;
import speiger.src.coreengine.graphics.api.sampler.Sampler;
import speiger.src.coreengine.graphics.api.shader.ColorTarget;
import speiger.src.coreengine.graphics.api.shader.DepthTarget;
import speiger.src.coreengine.graphics.api.shader.RasterizerState;
import speiger.src.coreengine.graphics.api.shader.ShaderPipeline;
import speiger.src.coreengine.graphics.api.shader.states.DrawMode;
import speiger.src.coreengine.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.utils.AccessType;
import speiger.src.coreengine.graphics.api.utils.ScissorsManager;
import speiger.src.coreengine.graphics.api.utils.ScissorsManager.NoOp;
import speiger.src.coreengine.graphics.opengl.buffer.GLVertexBuffer;
import speiger.src.coreengine.graphics.opengl.mesh.GLMesh;
import speiger.src.coreengine.graphics.opengl.sampler.GLSampler;
import speiger.src.coreengine.graphics.opengl.shader.ShaderInstance;
import speiger.src.coreengine.graphics.opengl.texture.GLTexture;
import speiger.src.coreengine.graphics.opengl.utils.GLStates;
import speiger.src.coreengine.graphics.opengl.utils.GLUtils;
import speiger.src.coreengine.math.vector.ints.Vec4i; import speiger.src.coreengine.math.vector.ints.Vec4i;
import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
import speiger.src.coreengine.platform.graphics.api.buffer.states.IndeciesType;
import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandBuffer;
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
import speiger.src.coreengine.platform.graphics.api.shader.ColorTarget;
import speiger.src.coreengine.platform.graphics.api.shader.DepthTarget;
import speiger.src.coreengine.platform.graphics.api.shader.RasterizerState;
import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
import speiger.src.coreengine.platform.graphics.api.shader.states.DrawMode;
import speiger.src.coreengine.platform.graphics.api.texture.Texture;
import speiger.src.coreengine.platform.graphics.api.utils.AccessType;
import speiger.src.coreengine.platform.graphics.api.utils.SampledTexture;
import speiger.src.coreengine.platform.graphics.api.utils.ScissorsManager;
import speiger.src.coreengine.platform.graphics.api.utils.ScissorsManager.NoOp;
import speiger.src.coreengine.platform.graphics.opengl.buffer.GLVertexBuffer;
import speiger.src.coreengine.platform.graphics.opengl.mesh.GLMesh;
import speiger.src.coreengine.platform.graphics.opengl.sampler.GLSampler;
import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance;
import speiger.src.coreengine.platform.graphics.opengl.texture.GLTexture;
import speiger.src.coreengine.platform.graphics.opengl.utils.GLStates;
import speiger.src.coreengine.platform.graphics.opengl.utils.GLUtils;
public class GLRecordingCommandBuffer implements GraphicsCommandBuffer { public class GLRecordingCommandBuffer implements GraphicsCommandBuffer {
List<Runnable> tasks = new ObjectArrayList<>(); List<Runnable> tasks = new ObjectArrayList<>();
@@ -110,13 +110,12 @@ public class GLRecordingCommandBuffer implements GraphicsCommandBuffer {
} }
@Override @Override
public GraphicsCommandBuffer texture(int binding, Texture texture, Sampler sampler) { public GraphicsCommandBuffer texture(int binding, SampledTexture texture) {
Objects.requireNonNull(texture); Objects.requireNonNull(texture);
Objects.requireNonNull(sampler);
ensureDrawing(); ensureDrawing();
Objects.requireNonNull(shader, "No Pipeline found"); Objects.requireNonNull(shader, "No Pipeline found");
Objects.requireNonNull(shader.samplers().byIndex(binding), "Texture["+binding+"] binding not found"); Objects.requireNonNull(shader.samplers().byIndex(binding), "Texture["+binding+"] binding not found");
tasks.add(new SetTexture(binding, (GLTexture)texture, (GLSampler)sampler, device.states)); tasks.add(new SetTexture(binding, (GLTexture)texture.texture(), (GLSampler)texture.sampler(), device.states));
return this; return this;
} }

Some files were not shown because too many files have changed in this diff Show More