mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-10-25 20:22:22 +00:00
A few fixes (#1994)
This commit is contained in:
1 parent
8da561d3b6
commit
4b21bc77b6
13 files changed
+198
-5
No files matched your search
@@ -201,6 +201,7 @@ fun Test.configureAngelicaJava8() {
|
||||
tasks.test {
|
||||
useJUnitPlatform { excludeTags = setOf("gl-core") }
|
||||
configureAngelicaJava8()
|
||||
dependsOn(":glsm:classes", ":lwjgl3-backend:classes", ":sdl-gpu:classes")
|
||||
}
|
||||
|
||||
val downgradeRootMainClasses = tasks.named<DowngradeFiles>("downgradeMainClasses")
|
||||
|
||||
@@ -10,4 +10,5 @@ repositories {
|
||||
// Re-export Gradle's generated typed catalog accessors so applied scripts (dependencies.gradle.kts) can use them.
|
||||
dependencies {
|
||||
implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
|
||||
implementation(libs.asm.build)
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import org.objectweb.asm.AnnotationVisitor
|
||||
import org.objectweb.asm.ClassReader
|
||||
import org.objectweb.asm.ClassVisitor
|
||||
import org.objectweb.asm.ClassWriter
|
||||
import org.objectweb.asm.Opcodes
|
||||
import java.io.File
|
||||
|
||||
private const val LWJGL3_AWARE_DESC = "Lme/eigenraven/lwjgl3ify/api/Lwjgl3Aware;"
|
||||
|
||||
/**
|
||||
* Stamps @Lwjgl3Aware onto every class under [classesDir] - classes that already carry the annotation are left untouched.
|
||||
*/
|
||||
fun injectLwjgl3Aware(classesDir: File) {
|
||||
if (!classesDir.isDirectory) return
|
||||
|
||||
classesDir.walkTopDown()
|
||||
.filter { it.isFile && it.extension == "class" && it.name != "module-info.class" }
|
||||
.forEach { classFile ->
|
||||
val reader = ClassReader(classFile.readBytes())
|
||||
if (hasLwjgl3Aware(reader)) return@forEach
|
||||
|
||||
val writer = ClassWriter(reader, 0)
|
||||
reader.accept(object : ClassVisitor(Opcodes.ASM9, writer) {
|
||||
override fun visit(
|
||||
version: Int,
|
||||
access: Int,
|
||||
name: String?,
|
||||
signature: String?,
|
||||
superName: String?,
|
||||
interfaces: Array<out String>?
|
||||
) {
|
||||
super.visit(version, access, name, signature, superName, interfaces)
|
||||
super.visitAnnotation(LWJGL3_AWARE_DESC, true)?.visitEnd()
|
||||
}
|
||||
}, 0)
|
||||
classFile.writeBytes(writer.toByteArray())
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasLwjgl3Aware(reader: ClassReader): Boolean {
|
||||
var found = false
|
||||
reader.accept(object : ClassVisitor(Opcodes.ASM9) {
|
||||
override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? {
|
||||
if (descriptor == LWJGL3_AWARE_DESC) found = true
|
||||
return null
|
||||
}
|
||||
}, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES)
|
||||
return found
|
||||
}
|
||||
+1
@@ -282,6 +282,7 @@ public class TessellatorStreamingDrawer {
|
||||
}
|
||||
|
||||
drawWithQuadConversion(drawMode, firstVertex, vertexCount);
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
} finally {
|
||||
if (locked) GLStateManager.releaseDrawLock();
|
||||
Tracy.endZone();
|
||||
|
||||
@@ -26,6 +26,7 @@ commonsLang3 = "3.17.0"
|
||||
jvmDowngrader = "1.3.5"
|
||||
junit = "5.14.1"
|
||||
asmTest = "9.7"
|
||||
asmBuild = "9.7"
|
||||
mockito = "3.12.4"
|
||||
archunit = "1.4.1"
|
||||
ant = "1.8.2"
|
||||
@@ -59,6 +60,7 @@ archunit-junit5 = { module = "com.tngtech.archunit:archunit-junit5", version.ref
|
||||
ant = { module = "org.apache.ant:ant", version.ref = "ant" }
|
||||
asm-tree-compile = { module = "org.ow2.asm:asm-tree", version.ref = "asmCompile" }
|
||||
asm-tree-test = { module = "org.ow2.asm:asm-tree", version.ref = "asmTest" }
|
||||
asm-build = { module = "org.ow2.asm:asm", version.ref = "asmBuild" }
|
||||
lwjgl2 = { module = "org.lwjgl.lwjgl:lwjgl", version.ref = "lwjgl2" }
|
||||
lwjgl2-util = { module = "org.lwjgl.lwjgl:lwjgl_util", version.ref = "lwjgl2" }
|
||||
lwjgl3 = { module = "org.lwjgl:lwjgl", version.ref = "lwjgl3" }
|
||||
|
||||
@@ -74,6 +74,11 @@ dependencies {
|
||||
compileOnly(libs.annotations)
|
||||
}
|
||||
|
||||
tasks.named<JavaCompile>("compileJava") {
|
||||
val classesDir = destinationDirectory
|
||||
doLast { injectLwjgl3Aware(classesDir.get().asFile) }
|
||||
}
|
||||
|
||||
tasks.named<Jar>("jar") {
|
||||
manifest {
|
||||
attributes(
|
||||
|
||||
+2
-2
@@ -1613,9 +1613,9 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
|
||||
@Override
|
||||
public void bindImageTexture(int unit, int texture, int level, boolean layered, int layer, int access, int format) {
|
||||
if (GLStateManager.capabilities.OpenGL42 || GLStateManager.capabilities.GL_ARB_shader_image_load_store) {
|
||||
if (caps.OpenGL42 || caps.GL_ARB_shader_image_load_store) {
|
||||
GL42C.glBindImageTexture(unit, texture, level, layered, layer, access, format);
|
||||
} else if (GLStateManager.capabilities.GL_EXT_shader_image_load_store) {
|
||||
} else if (caps.GL_EXT_shader_image_load_store) {
|
||||
EXTShaderImageLoadStore.glBindImageTextureEXT(unit, texture, level, layered, layer, access, format);
|
||||
} else {
|
||||
GLStateManager.warnOnce("bindImageTexture", "glBindImageTexture ignored: no image load/store support");
|
||||
|
||||
@@ -91,6 +91,11 @@ tasks.test {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named<JavaCompile>("compileJava") {
|
||||
val classesDir = destinationDirectory
|
||||
doLast { injectLwjgl3Aware(classesDir.get().asFile) }
|
||||
}
|
||||
|
||||
tasks.named<Jar>("jar") {
|
||||
manifest {
|
||||
attributes(
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ class ChunkCullSpirvCompileTest {
|
||||
final ShaderManager.ComputeBindingMap map = ShaderManager.remapSpirvForComputeSDLGPU(spirv);
|
||||
assertEquals(0, map.samplerGlSlots().length, "the frustum cull samples no textures");
|
||||
assertEquals(1, map.uboGlSlots().length, "Frustum UBO");
|
||||
assertEquals(0, map.uboGlSlots()[0], "Frustum UBO is at binding 0");
|
||||
assertEquals(1, map.uboGlSlots()[0], "Frustum UBO is at binding 1");
|
||||
assertEquals(160, map.uboSizes()[0], "Frustum UBO is 160 bytes");
|
||||
assertEquals(3, map.roSsboGlSlots().length + map.rwSsboGlSlots().length, "visible + meta + indirect");
|
||||
assertTrue(IntStream.concat(Arrays.stream(map.roSsboGlSlots()), Arrays.stream(map.rwSsboGlSlots())).allMatch(s -> s >= 0 && s < 8), "a storage binding outside 0..7 exceeds the GL 4.3 guaranteed minimum");
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ public final class GpuDrivenChunkCuller {
|
||||
static final int VISIBLE_SSBO_BINDING = 0;
|
||||
static final int META_SSBO_BINDING = 1;
|
||||
static final int INDIRECT_SSBO_BINDING = 2;
|
||||
static final int FRUSTUM_UBO_BINDING = 0;
|
||||
static final int FRUSTUM_UBO_BINDING = 1;
|
||||
|
||||
private boolean ready;
|
||||
private boolean disabled;
|
||||
|
||||
@@ -33,7 +33,7 @@ layout(std430, binding = 2) writeonly buffer IndirectCmds {
|
||||
DrawElementsIndirectCommand cmds[];
|
||||
} indirect;
|
||||
|
||||
layout(std140, binding = 0) uniform Frustum {
|
||||
layout(std140, binding = 1) uniform Frustum {
|
||||
vec4 planes[6]; // camera-relative planes from `proj * mv` (no translate baked in)
|
||||
// control.x = visibleCount (iteration bound)
|
||||
// control.y = indexPointerMask (0 non-sorted -> firstIndex masked to 0; 0xFFFFFFFF sorted)
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
package com.gtnewhorizons.angelica.arch;
|
||||
|
||||
import com.tngtech.archunit.core.domain.AccessTarget;
|
||||
import com.tngtech.archunit.core.domain.JavaAccess;
|
||||
import com.tngtech.archunit.core.domain.JavaClass;
|
||||
import com.tngtech.archunit.core.domain.JavaClasses;
|
||||
import com.tngtech.archunit.core.domain.JavaMethod;
|
||||
import com.tngtech.archunit.core.importer.ClassFileImporter;
|
||||
import com.tngtech.archunit.core.importer.ImportOption;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* Enforces the lwjgl3ify remap boundary.
|
||||
*/
|
||||
class Lwjgl3AwareBoundaryTest {
|
||||
|
||||
private static final String AWARE = "me.eigenraven.lwjgl3ify.api.Lwjgl3Aware";
|
||||
|
||||
/** Packages whose classes lwjgl3ify never transforms, so their descriptors match on both sides. */
|
||||
private static final List<String> UNTRANSFORMED_PACKAGES = List.of("org.lwjgl.", "org.lwjglx.");
|
||||
|
||||
/** Modules built against native LWJGL3; every class in them must be aware. */
|
||||
private static final List<String> AWARE_MODULES = List.of(
|
||||
"com.gtnewhorizons.angelica.sdlgpu.",
|
||||
"com.gtnewhorizons.angelica.lwjgl3.");
|
||||
|
||||
private static final JavaClasses classes = new ClassFileImporter()
|
||||
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
|
||||
.importPaths(
|
||||
"build/classes/java/main",
|
||||
"build/classes/java/mixin",
|
||||
"glsm/build/classes/java/main",
|
||||
"lwjgl3-backend/build/classes/java/main",
|
||||
"sdl-gpu/build/classes/java/main");
|
||||
|
||||
@Test
|
||||
void awareClassesDoNotReadRemappedMembers() {
|
||||
final List<String> violations = new ArrayList<>();
|
||||
for (JavaClass origin : classes) {
|
||||
if (!isAware(origin)) continue;
|
||||
for (JavaAccess<?> access : origin.getAccessesFromSelf()) {
|
||||
final JavaClass owner = access.getTargetOwner();
|
||||
if (isUntransformed(owner) || isAware(owner)) continue;
|
||||
if (mentionsLwjgl3Type(access.getTarget())) violations.add(describe(access));
|
||||
}
|
||||
}
|
||||
assertTrue(violations.isEmpty(), "@Lwjgl3Aware code referencing a remapped member with an org.lwjgl type in its descriptor:\n" + String.join("\n", violations));
|
||||
}
|
||||
|
||||
@Test
|
||||
void remappedClassesDoNotReadAwareMembers() {
|
||||
final List<String> violations = new ArrayList<>();
|
||||
for (JavaClass origin : classes) {
|
||||
if (isAware(origin) || isUntransformed(origin)) continue;
|
||||
for (JavaAccess<?> access : origin.getAccessesFromSelf()) {
|
||||
if (!isAware(access.getTargetOwner())) continue;
|
||||
if (mentionsLwjgl3Type(access.getTarget())) violations.add(describe(access));
|
||||
}
|
||||
}
|
||||
assertTrue(violations.isEmpty(), "Remapped code referencing an @Lwjgl3Aware member with an org.lwjgl type in its descriptor:\n" + String.join("\n", violations));
|
||||
}
|
||||
|
||||
/** Verifies the build-time injection in :sdl-gpu / :lwjgl3-backend actually ran over the class output. */
|
||||
@Test
|
||||
void nativeLwjgl3ModulesAreFullyAware() {
|
||||
final List<String> missing = new ArrayList<>();
|
||||
for (JavaClass c : classes) {
|
||||
if (AWARE_MODULES.stream().anyMatch(p -> c.getName().startsWith(p)) && !isAware(c)) {
|
||||
missing.add(c.getName());
|
||||
}
|
||||
}
|
||||
assertTrue(missing.isEmpty(), "Classes missing @Lwjgl3Aware:\n" + String.join("\n", missing));
|
||||
}
|
||||
|
||||
@Test
|
||||
void renderBackendSignaturesAreRemapSafe() {
|
||||
final JavaClass renderBackend = classes.get("com.gtnewhorizons.angelica.glsm.backend.RenderBackend");
|
||||
final List<String> violations = new ArrayList<>();
|
||||
for (JavaMethod method : renderBackend.getMethods()) {
|
||||
final List<JavaClass> types = new ArrayList<>(method.getRawParameterTypes());
|
||||
types.add(method.getRawReturnType());
|
||||
if (types.stream().anyMatch(Lwjgl3AwareBoundaryTest::isLwjgl3Type)) {
|
||||
violations.add(method.getFullName());
|
||||
}
|
||||
}
|
||||
assertTrue(violations.isEmpty(), "RenderBackend methods with an org.lwjgl type in their signature:\n" + String.join("\n", violations));
|
||||
}
|
||||
|
||||
private static boolean isAware(JavaClass c) {
|
||||
return c.isAnnotatedWith(AWARE);
|
||||
}
|
||||
|
||||
private static boolean isUntransformed(JavaClass c) {
|
||||
return UNTRANSFORMED_PACKAGES.stream().anyMatch(p -> c.getName().startsWith(p));
|
||||
}
|
||||
|
||||
private static boolean isLwjgl3Type(JavaClass type) {
|
||||
return type.getName().startsWith("org.lwjgl.");
|
||||
}
|
||||
|
||||
private static boolean mentionsLwjgl3Type(AccessTarget target) {
|
||||
return descriptorTypes(target).stream().anyMatch(Lwjgl3AwareBoundaryTest::isLwjgl3Type);
|
||||
}
|
||||
|
||||
private static List<JavaClass> descriptorTypes(AccessTarget target) {
|
||||
if (target instanceof AccessTarget.FieldAccessTarget field) {
|
||||
return List.of(field.getRawType());
|
||||
}
|
||||
if (target instanceof AccessTarget.CodeUnitCallTarget call) {
|
||||
final List<JavaClass> types = new ArrayList<>(call.getRawParameterTypes());
|
||||
if (target instanceof AccessTarget.MethodCallTarget method) {
|
||||
types.add(method.getRawReturnType());
|
||||
}
|
||||
return types;
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
|
||||
private static String describe(JavaAccess<?> access) {
|
||||
return " " + access.getOwner().getFullName() + " -> " + access.getTarget().getFullName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
# The arch tests only need names and descriptors off the imported bytecode.
|
||||
resolveMissingDependenciesFromClassPath=false
|
||||
Reference in new issue
Block a user