mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-08 12:35:01 +00:00
Fix Complementary + Euphoria Patches ULTRA on SDL-GPU (#2195)
This commit is contained in:
1 parent
37afddab5d
commit
bdcb4d1882
6 files changed
+141
-4
No files matched your search
+12
-1
@@ -28,6 +28,15 @@ public final class GlslVulkanPreprocess {
|
||||
|
||||
public static final String SAMPLER_RENAMED = "angelica_sampler_renamed";
|
||||
|
||||
public static final String RESERVED_RENAMED_PREFIX = "angelica_renamed_";
|
||||
|
||||
private static final Set<String> TARGET_RESERVED = Set.of(
|
||||
"try", "catch", "throw", "delete", "operator", "private", "protected", "friend", "virtual", "explicit",
|
||||
"mutable", "typename", "typeid", "register", "signed", "char", "auto", "nullptr", "constexpr", "decltype",
|
||||
"noexcept", "alignas", "alignof", "static_assert", "thread_local", "wchar_t", "char16_t", "char32_t",
|
||||
"const_cast", "dynamic_cast", "reinterpret_cast", "static_cast", "export",
|
||||
"and", "or", "xor", "bitand", "bitor", "compl", "and_eq", "or_eq", "xor_eq", "not_eq");
|
||||
|
||||
public static final String SAMPLERLESS_EXTENSION = "#extension GL_EXT_samplerless_texture_functions : require";
|
||||
|
||||
private static final int MAX_VS_INPUT_LOCATIONS = 16;
|
||||
@@ -211,7 +220,9 @@ public final class GlslVulkanPreprocess {
|
||||
case "sampler" -> edits.add(new Edit(tok.getStartIndex(), tok.getStopIndex(), SAMPLER_RENAMED));
|
||||
case "gl_VertexID" -> edits.add(new Edit(tok.getStartIndex(), tok.getStopIndex(), "gl_VertexIndex"));
|
||||
case "gl_InstanceID" -> edits.add(new Edit(tok.getStartIndex(), tok.getStopIndex(), "gl_InstanceIndex"));
|
||||
default -> {}
|
||||
default -> {
|
||||
if (TARGET_RESERVED.contains(text)) edits.add(new Edit(tok.getStartIndex(), tok.getStopIndex(), RESERVED_RENAMED_PREFIX + text));
|
||||
}
|
||||
}
|
||||
}
|
||||
}, root);
|
||||
|
||||
+24
@@ -297,6 +297,30 @@ class SpirvShaderTranslatorTest {
|
||||
assertTrue(es.contains("sampler2D"), "sampler2D type must not be touched by the rename");
|
||||
}
|
||||
|
||||
@Test
|
||||
void cppKeywordsAsIdentifiers_areRenamed() {
|
||||
final String src = """
|
||||
#version 330 core
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
void main() {
|
||||
vec4 try = vec4(texCoord, 0.0, 1.0);
|
||||
float catch = try.x;
|
||||
bvec2 flipped = not(lessThan(texCoord, vec2(0.5)));
|
||||
fragColor = flipped.x ? try : vec4(catch);
|
||||
}
|
||||
""";
|
||||
|
||||
final String es = SpirvShaderTranslator.glslToGlslEs(src, GL20.GL_FRAGMENT_SHADER, "reserved.frag");
|
||||
dumpOnFailure("reserved.frag", src, es);
|
||||
|
||||
assertNotNull(es);
|
||||
assertTrue(es.contains("angelica_renamed_try"), es);
|
||||
assertTrue(es.contains("angelica_renamed_catch"), es);
|
||||
assertTrue(es.contains("not("), "the not() builtin must not be touched by the rename\n" + es);
|
||||
assertFalse(es.contains("angelica_renamed_not"), es);
|
||||
}
|
||||
|
||||
@Test
|
||||
void uniformBool_multiDeclarator_allRestored() {
|
||||
final String src = """
|
||||
|
||||
+14
@@ -106,6 +106,20 @@ class PrewarmTreeHandoffEquivalenceTest {
|
||||
GL20.GL_FRAGMENT_SHADER);
|
||||
}
|
||||
|
||||
@Test
|
||||
void cppKeywordLocal() {
|
||||
assertHandoffEquivalent("cpp-keyword-local",
|
||||
"layout(location = 0) in vec4 v_Color;\n"
|
||||
+ "layout(location = 0) out vec4 fragColor;\n"
|
||||
+ "vec4 trace(vec4 c) {\n"
|
||||
+ " vec4 try = c * 0.5;\n"
|
||||
+ " if (try.a > -0.5) return try;\n"
|
||||
+ " return c;\n"
|
||||
+ "}\n"
|
||||
+ "void main() { fragColor = trace(v_Color); }\n",
|
||||
GL20.GL_FRAGMENT_SHADER);
|
||||
}
|
||||
|
||||
@Test
|
||||
void geometryStage() {
|
||||
assertHandoffEquivalent("geometry",
|
||||
|
||||
+34
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.shader.msl;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.shader.GlslVulkanPreprocess;
|
||||
import com.gtnewhorizons.angelica.glsm.shader.ShaderCacheIO;
|
||||
import com.gtnewhorizons.angelica.glsm.shader.ShaderDiskCache;
|
||||
import com.gtnewhorizons.angelica.glsm.shader.SpirvCompiler;
|
||||
@@ -28,6 +29,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
@@ -215,6 +217,38 @@ class MslCrossCompileTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static final String CPP_KEYWORD_LOCAL_GLSL = """
|
||||
#version 460 core
|
||||
layout(location = 0) in vec4 v_Color;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
vec4 trace(vec4 c) {
|
||||
vec4 try = c * 0.5;
|
||||
if (try.a > -0.5) return try;
|
||||
return c;
|
||||
}
|
||||
void main() { fragColor = trace(v_Color); }
|
||||
""";
|
||||
|
||||
@Test
|
||||
void cppKeywordLocalIsRenamedBeforeMsl() {
|
||||
final GlslVulkanPreprocess.Result pre = GlslVulkanPreprocess.run(CPP_KEYWORD_LOCAL_GLSL, GL20.GL_FRAGMENT_SHADER, "test", true);
|
||||
assertNotNull(pre);
|
||||
final ByteBuffer spirv = compile(pre.rewrittenSource(), Shaderc.shaderc_fragment_shader);
|
||||
try {
|
||||
ShaderManager.remapSpirvForSDLGPU(spirv, GL20.GL_FRAGMENT_SHADER);
|
||||
final MslCrossCompile.Output out = MslCrossCompile.compile(spirv, GL20.GL_FRAGMENT_SHADER);
|
||||
try {
|
||||
final String msl = decode(out.code());
|
||||
assertTrue(msl.contains("angelica_renamed_try"), "the local must keep a renamed identifier:\n" + msl);
|
||||
assertFalse(Pattern.compile("\\btry\\b").matcher(msl).find(), "try is reserved in MSL:\n" + msl);
|
||||
} finally {
|
||||
MemoryUtil.memFree(out.code());
|
||||
}
|
||||
} finally {
|
||||
MemoryUtil.memFree(spirv);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void crossCompileFreesNativeMemory() {
|
||||
for (int i = 0; i < 200; i++) {
|
||||
|
||||
@@ -559,14 +559,13 @@ public class ShaderTransformer {
|
||||
artifactsOut.put(shaderType, new StageArtifact(treeHolder[0], formattedShader.length() - printedBody.length()));
|
||||
}
|
||||
}
|
||||
maybeExtractRwImageStores(result, patchType);
|
||||
if (BackendManager.RENDER_BACKEND.isSDLGPU()) extractRwImageStores(result, patchType, artifactsOut);
|
||||
watch.stop();
|
||||
Iris.logger.info("[Load #{}] Transformed shader for {} in {}", Iris.getShaderPackLoadId(), patchType.name(), watch);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void maybeExtractRwImageStores(EnumMap<PatchShaderType, String> result, Patch patchType) {
|
||||
if (!BackendManager.RENDER_BACKEND.isSDLGPU()) return;
|
||||
static void extractRwImageStores(EnumMap<PatchShaderType, String> result, Patch patchType, EnumMap<PatchShaderType, StageArtifact> artifactsOut) {
|
||||
if (result.containsKey(PatchShaderType.COMPUTE)) return;
|
||||
|
||||
final String vsh = result.get(PatchShaderType.VERTEX);
|
||||
@@ -580,10 +579,12 @@ public class ShaderTransformer {
|
||||
if (vshResult != null) {
|
||||
result.put(PatchShaderType.VERTEX, vshResult.strippedSource());
|
||||
result.put(PatchShaderType.COMPUTE, vshResult.computeSource());
|
||||
if (artifactsOut != null) artifactsOut.remove(PatchShaderType.VERTEX);
|
||||
Iris.logger.info("[RwImageStoreExtractor] Extracted compute pre-pass for {} (mode={}, written={})", patchType.name(), vshResult.mode(), vshResult.writtenImages());
|
||||
} else if (fshResult != null) {
|
||||
result.put(PatchShaderType.FRAGMENT, fshResult.strippedSource());
|
||||
result.put(PatchShaderType.COMPUTE, fshResult.computeSource());
|
||||
if (artifactsOut != null) artifactsOut.remove(PatchShaderType.FRAGMENT);
|
||||
Iris.logger.info("[RwImageStoreExtractor] Extracted compute pre-pass for {} (mode={}, written={})", patchType.name(), fshResult.mode(), fshResult.writtenImages());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package net.coderbot.iris.pipeline.transform;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GlslTransformUtils;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.Reflect;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.TextureStageParameters;
|
||||
import net.coderbot.iris.shaderpack.texture.TextureStage;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -11,6 +14,7 @@ import org.taumc.glsl.ShaderParser;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
@@ -219,6 +223,55 @@ class ShaderTransformerTest {
|
||||
assertTrue(out.contains("gtexture"), "the pack's own sampler name must survive off SDL-GPU\n\n" + out);
|
||||
}
|
||||
|
||||
private static final String IMAGE_STORE_FRAGMENT = String.join("\n",
|
||||
"#version 330 core",
|
||||
"layout(r16ui) writeonly uniform uimage3D voxel_img;",
|
||||
"in vec2 uv;",
|
||||
"void main(){",
|
||||
" imageStore(voxel_img, ivec3(0), uvec4(1u, 0u, 0u, 0u));",
|
||||
" gl_FragColor = vec4(uv, 0.0, 1.0);",
|
||||
"}",
|
||||
"");
|
||||
|
||||
private static final String PLAIN_VERTEX = "#version 330 core\nout vec2 uv;\nvoid main(){ uv = vec2(0.5); gl_Position = vec4(0.0); }";
|
||||
|
||||
@Test
|
||||
void extractedStageDropsItsArtifact() {
|
||||
TransformPatcher.clearCache();
|
||||
ShaderTransformer.clearCache();
|
||||
final EnumMap<PatchShaderType, ShaderTransformer.StageArtifact> artifacts = new EnumMap<>(PatchShaderType.class);
|
||||
final Map<PatchShaderType, String> out = ShaderTransformer.transform(PLAIN_VERTEX, null, null, null, IMAGE_STORE_FRAGMENT, new TextureStageParameters(Patch.COMPOSITE, TextureStage.COMPOSITE_AND_FINAL, null), artifacts);
|
||||
assertNotNull(out);
|
||||
assertTrue(artifacts.containsKey(PatchShaderType.VERTEX) && artifacts.containsKey(PatchShaderType.FRAGMENT), "fixture must start with both artifacts");
|
||||
|
||||
final EnumMap<PatchShaderType, String> result = new EnumMap<>(out);
|
||||
final String fragmentBefore = result.get(PatchShaderType.FRAGMENT);
|
||||
ShaderTransformer.extractRwImageStores(result, Patch.COMPOSITE, artifacts);
|
||||
|
||||
assertNotNull(result.get(PatchShaderType.COMPUTE), "fixture must actually exercise the extraction");
|
||||
assertFalse(fragmentBefore.equals(result.get(PatchShaderType.FRAGMENT)), "fixture must actually rewrite the fragment stage");
|
||||
assertFalse(artifacts.containsKey(PatchShaderType.FRAGMENT), "a rewritten stage must not keep the tree of its old text");
|
||||
assertTrue(artifacts.containsKey(PatchShaderType.VERTEX), "an untouched stage keeps its artifact");
|
||||
}
|
||||
|
||||
@Test
|
||||
void survivingArtifactsMatchTheirSource() {
|
||||
TransformPatcher.clearCache();
|
||||
ShaderTransformer.clearCache();
|
||||
final EnumMap<PatchShaderType, ShaderTransformer.StageArtifact> artifacts = new EnumMap<>(PatchShaderType.class);
|
||||
final Map<PatchShaderType, String> out = ShaderTransformer.transform(PLAIN_VERTEX, null, null, null, IMAGE_STORE_FRAGMENT, new TextureStageParameters(Patch.COMPOSITE, TextureStage.COMPOSITE_AND_FINAL, null), artifacts);
|
||||
assertNotNull(out);
|
||||
|
||||
final EnumMap<PatchShaderType, String> result = new EnumMap<>(out);
|
||||
ShaderTransformer.extractRwImageStores(result, Patch.COMPOSITE, artifacts);
|
||||
|
||||
assertFalse(artifacts.isEmpty(), "fixture must leave at least one artifact to check");
|
||||
for (Map.Entry<PatchShaderType, ShaderTransformer.StageArtifact> e : artifacts.entrySet()) {
|
||||
final String body = result.get(e.getKey()).substring(e.getValue().headerLen());
|
||||
assertEquals(GlslTransformUtils.getFormattedShaderRebased(e.getValue().tree(), ""), body, "artifact tree must describe the emitted " + e.getKey() + " body");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void transformIsDeterministicUnderConcurrency() throws ExecutionException, InterruptedException {
|
||||
TransformPatcher.clearCache();
|
||||
|
||||
Reference in new issue
Block a user