Skip to content

Commit

Permalink
basic automated testing
Browse files Browse the repository at this point in the history
  • Loading branch information
RogueLogix committed Feb 27, 2024
1 parent 310fc60 commit b6ce014
Show file tree
Hide file tree
Showing 30 changed files with 1,295 additions and 31 deletions.
11 changes: 11 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ runs {
systemProperty 'forge.logging.console.level', 'debug'

modSource project.sourceSets.main
modSource project.sourceSets.test
modSource project(':Phosphophyllite').sourceSets.main

dependencies {
Expand Down Expand Up @@ -94,6 +95,7 @@ dependencies {
implementation "net.neoforged:neoforge:${neo_version}"

compileOnly project(':Phosphophyllite')
testCompileOnly project(':Phosphophyllite')
compileOnly("org.lwjgl:lwjgl-vulkan:3.3.1") {
transitive(false)
}
Expand Down
44 changes: 44 additions & 0 deletions runTests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import os
import shutil
import subprocess

runDirectory = "run/client/"
configDirectory = runDirectory + "config/phosphophyllite/"

runMode = os.environ.get("QUARTZ_TEST_RUN_MODE")
if runMode is None:
runMode = "Automatic"
pass

mainConfigName = "quartz-client.json5"
mainConfig = f"""
{{
debug: false,
mode: "{runMode}",
}}
"""

testConfigName = "quartz-testing-client.json5"
testConfig = """
{
Enabled: true,
AutoRun: true,
}
"""

if __name__ == '__main__':
print(mainConfig)
print(testConfig)
shutil.rmtree(runDirectory)
os.makedirs(configDirectory)

mainConfigFile = open(configDirectory + mainConfigName, "w")
mainConfigFile.write(mainConfig)
mainConfigFile.close()

testConfigFile = open(configDirectory + testConfigName, "w")
testConfigFile.write(testConfig)
testConfigFile.close()

subprocess.call(["./gradlew", ":runClient"])
pass
4 changes: 3 additions & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0'
}

include 'Phosphophyllite'
include 'Phosphophyllite'

startParameter.excludedTaskNames << ':Phosphophyllite:runClient'
2 changes: 1 addition & 1 deletion src/main/java/net/roguelogix/quartz/QuartzConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ private static boolean isValidPhosLoaading() {
}

private static boolean setup() {
if (!QuartzDebug.doesForgeExist()) {
if (!QuartzDebug.Util.doesForgeExist()) {
// loading without forge present
return false;
}
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/net/roguelogix/quartz/QuartzEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public static class ResourcesReloaded extends ResourcesLoaded {
}

public static class FrameStart extends QuartzEvent {
public FrameStart() {
}
}

public static class FrameEnd extends QuartzEvent {
}
}
45 changes: 39 additions & 6 deletions src/main/java/net/roguelogix/quartz/internal/QuartzCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,51 @@
import net.roguelogix.quartz.internal.world.WorldEngine;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.ref.Cleaner;
import java.util.List;

import static net.roguelogix.quartz.internal.QuartzDebug.doesForgeExist;

@ClientOnly
@NonnullDefault
public abstract class QuartzCore {

public static final Logger LOGGER = LogManager.getLogger("Quartz");

@Nonnull
// this should help the JIT with removing the code used for testing, and the branch testing that goes along with it
public static final boolean TESTING_ALLOWED;

static {
boolean testingAllowed = false;
try {
final var testingClass = QuartzCore.class.getClassLoader().loadClass("net.roguelogix.quartz.testing.QuartzTestingConfig");
final var instanceField = testingClass.getField("INSTANCE");
final var enabledField = testingClass.getField("Enabled");
final var isEnabled = enabledField.get(instanceField.get(null));
testingAllowed = (Boolean)isEnabled;
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
TESTING_ALLOWED = testingAllowed;
}

private static boolean TESTING_RUNNING = false;

private static void onTestingStatusEvent(QuartzInternalEvent.TestingStatus testingStatus) {
if(!TESTING_ALLOWED){
return;
}
TESTING_RUNNING = testingStatus.running;
}

public static boolean isTestingRunning() {
if(!TESTING_ALLOWED){
return false;
}
return TESTING_RUNNING;
}

public static final QuartzCore INSTANCE;
public static final Cleaner CLEANER = Cleaner.create();
public static final WorkQueue deletionQueue = new WorkQueue();
Expand All @@ -54,8 +83,9 @@ public static void mainThreadClean(Object referent, Runnable cleanFunc) {
}

static {
@Nullable
QuartzCore instance = null;
if (!DatagenModLoader.isRunningDataGen() && doesForgeExist()) {
if (!DatagenModLoader.isRunningDataGen() && QuartzDebug.Util.doesForgeExist()) {
if (!Thread.currentThread().getStackTrace()[2].getClassName().equals(EventListener.class.getName())) {
throw new IllegalStateException("Attempt to init quartz before it is ready");
}
Expand Down Expand Up @@ -142,6 +172,7 @@ public static void onModelRegisterEvent(ModelEvent.RegisterAdditional event) {

@OnModLoad
private static void onModLoad() {
Quartz.EVENT_BUS.addListener(QuartzCore::onTestingStatusEvent);
ModLoadingContext.get().getActiveContainer().getEventBus().addListener(QuartzCore::onModelRegisterEvent);
}

Expand Down Expand Up @@ -216,6 +247,8 @@ public DrawBatch getEntityBatcher() {

public abstract void waitIdle();

public abstract void fullSyncWait();

public abstract int frameInFlight();

public abstract void sectionDirty(int x, int y, int z);
Expand Down
30 changes: 16 additions & 14 deletions src/main/java/net/roguelogix/quartz/internal/QuartzDebug.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,28 @@ public class QuartzDebug {
public static final boolean DEBUG;

static {
if (!doesForgeExist() || runningDatagen()) {
if (!Util.doesForgeExist() || Util.runningDatagen()) {
DEBUG = false;
} else {
DEBUG = QuartzConfig.INSTANCE.debug;
DEBUG = QuartzCore.TESTING_ALLOWED || QuartzConfig.INSTANCE.debug;
}
}

public static boolean runningDatagen(){
try{
return DatagenModLoader.isRunningDataGen();
} catch (Throwable e){
return false;
public static class Util {
public static boolean runningDatagen() {
try {
return DatagenModLoader.isRunningDataGen();
} catch (Throwable e) {
return false;
}
}
}

public static boolean doesForgeExist(){
try{
return FMLLoader.getLoadingModList() != null;
} catch (Throwable e){
return false;
public static boolean doesForgeExist() {
try {
return FMLLoader.getLoadingModList() != null;
} catch (Throwable e) {
return false;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package net.roguelogix.quartz.internal;

import net.minecraft.client.renderer.RenderType;
import net.neoforged.bus.api.Event;
import net.roguelogix.phosphophyllite.util.NonnullDefault;
import net.roguelogix.phosphophyllite.util.Pair;
import net.roguelogix.quartz.internal.util.PointerWrapper;

import java.util.List;
import java.util.Map;

@NonnullDefault
public class QuartzInternalEvent extends Event {
public static class CreateTests extends QuartzInternalEvent {
}

public static class TestingStatus extends QuartzInternalEvent {
public final boolean running;

public TestingStatus(boolean running) {
this.running = running;
}
}

public static class FeedbackCollected extends QuartzInternalEvent {

public final List<RenderType> renderTypes;
// note: readOnly pointers
public final Map<RenderType, Pair<PointerWrapper, Integer>> feedbackBuffers;

public FeedbackCollected(List<RenderType> renderTypes, Map<RenderType, Pair<PointerWrapper, Integer>> feedbackBuffers) {
this.renderTypes = renderTypes;
this.feedbackBuffers = feedbackBuffers;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ public void waitIdle() {
// no need to wait for GPU idle
}

@Override
public void fullSyncWait() {
// no syncing needed
}

@Override
public int frameInFlight() {
return 0;
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/net/roguelogix/quartz/internal/gl46/GL46Core.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import net.minecraft.client.renderer.RenderType;
import net.roguelogix.phosphophyllite.util.NonnullDefault;
import net.roguelogix.quartz.DrawBatch;
import net.roguelogix.quartz.Quartz;
import net.roguelogix.quartz.QuartzEvent;
import net.roguelogix.quartz.internal.Buffer;
import net.roguelogix.quartz.internal.IrisDetection;
import net.roguelogix.quartz.internal.QuartzCore;
Expand All @@ -20,7 +22,7 @@

import java.util.List;

import static org.lwjgl.opengl.GL46C.glFinish;
import static org.lwjgl.opengl.GL45C.*;

@NonnullDefault
public class GL46Core extends QuartzCore {
Expand Down Expand Up @@ -112,6 +114,8 @@ public void frameStart(PoseStack pMatrixStack, float pPartialTicks, long pFinish
drawInfo.deltaNano = deltaNano;
drawInfo.partialTicks = pPartialTicks;

Quartz.EVENT_BUS.post(new QuartzEvent.FrameStart());

GL46FeedbackDrawing.beginFrame();
}

Expand Down Expand Up @@ -184,14 +188,20 @@ public void endOpaque() {

@Override
public void endTranslucent() {

Quartz.EVENT_BUS.post(new QuartzEvent.FrameEnd());
}

@Override
public void waitIdle() {
glFinish();
}

@Override
public void fullSyncWait() {
glMemoryBarrier(GL_ALL_BARRIER_BITS);
glFinish();
}

@Override
public int frameInFlight() {
return frameInFlight;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
import com.mojang.blaze3d.systems.RenderSystem;
import it.unimi.dsi.fastutil.objects.*;
import net.minecraft.client.renderer.RenderType;
import net.roguelogix.phosphophyllite.util.Pair;
import net.roguelogix.quartz.DrawBatch;
import net.roguelogix.quartz.Quartz;
import net.roguelogix.quartz.internal.*;
import net.roguelogix.quartz.internal.common.B3DStateHelper;
import net.roguelogix.quartz.internal.gl46.batching.GL46DrawBatch;
import net.roguelogix.quartz.internal.util.PointerWrapper;
import net.roguelogix.quartz.internal.util.VertexFormatOutput;
import org.joml.Matrix4f;

Expand Down Expand Up @@ -46,8 +49,8 @@ public static void dirtyAll() {
private record FeedbackBuffer(int buffer, int size) {
private FeedbackBuffer(int size) {
this(glCreateBuffers(), roundUpPo2(size));
// no flags, only used on the server side
glNamedBufferStorage(buffer, this.size, 0);
// no flags, only used on the server side, unless testing
glNamedBufferStorage(buffer, this.size, QuartzCore.TESTING_ALLOWED ? GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT : 0);
}

void delete() {
Expand All @@ -63,7 +66,8 @@ private static int roundUpPo2(int minSize) {
}
}

private static final Object2ObjectMap<RenderType, FeedbackBuffer> renderTypeFeedbackBuffers = new Object2ObjectArrayMap<>();
private static final Reference2ObjectMap<RenderType, FeedbackBuffer> renderTypeFeedbackBuffers = new Reference2ObjectArrayMap<>();
private static final Reference2LongMap<RenderType> renderTypeFeedbackBufferMappings = new Reference2LongArrayMap<>();

private static Buffer.CallbackHandle rebuildCallbackHandle;

Expand Down Expand Up @@ -274,6 +278,14 @@ public static void collectAllFeedback(boolean shadowsEnabled) {
drawBatch.setFrameSync(frameSync);
}
prevousFrameSyncs[frameInFlight] = frameSync;

if(QuartzCore.TESTING_ALLOWED && QuartzCore.isTestingRunning()){
var buffers = new Object2ObjectOpenHashMap<RenderType, Pair<PointerWrapper, Integer>>();
for (RenderType renderType : inUseRenderTypes) {
buffers.put(renderType, new Pair<>(null, 0));
}
Quartz.EVENT_BUS.post(new QuartzInternalEvent.FeedbackCollected(inUseRenderTypes, buffers));
}
}

private static Matrix4f projection;
Expand Down
Loading

0 comments on commit b6ce014

Please sign in to comment.