diff --git a/.idea/icon.png b/.idea/icon.png new file mode 100644 index 0000000000..04dbe36d4e Binary files /dev/null and b/.idea/icon.png differ diff --git a/build.gradle b/build.gradle index b9e11ac0e2..533005a4c0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,21 +1,22 @@ plugins { - id 'dev.architectury.loom' version '0.11.0-SNAPSHOT' + id 'dev.architectury.loom' version '1.5.+' id 'maven-publish' } loom { - silentMojangMappingsLicense() - + silentMojangMappingsLicense() + forge { mixinConfigs = [ "mixins.oculus.json", + "mixins.oculus.compat.dh.json", + "mixins.oculus.compat.sodium.json", "mixins.oculus.fantastic.json", "mixins.oculus.vertexformat.json", "mixins.oculus.bettermipmaps.json", "mixins.oculus.fixes.maxfpscrash.json", "mixins.oculus.optimized-stitching.json", - "oculus-batched-entity-rendering.mixins.json", - "mixins.oculus.compat.sodium.json" + "oculus-batched-entity-rendering.mixins.json" ] } } @@ -29,33 +30,38 @@ group = project.maven_group repositories { maven { - name = "Modrinth" - url = "https://api.modrinth.com/maven" - content { - includeGroup "maven.modrinth" - } - } + name = "Modrinth" + url = "https://api.modrinth.com/maven" + content { + includeGroup "maven.modrinth" + } + } + mavenCentral() } configurations { - toJar + toJar } dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings loom.officialMojangMappings() forge "net.minecraftforge:forge:${minecraft_version}-${forge_version}" - + + compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:0.3.5")) + implementation(include("io.github.llamalad7:mixinextras-forge:0.3.5")) + compileOnly files("libs/apache-ant-1.8.2.jar") - modImplementation "maven.modrinth:rubidium:0.5.4" + modImplementation files("libs/DistantHorizons-forge-2.0.2-a-dev-1.18.2.jar") + modImplementation "maven.modrinth:embeddium:0.3.10+mc1.18.2" } processResources { inputs.property "version", project.version filesMatching("META-INF/mods.toml") { - expand "version": project.version - } + expand "version": project.version + } } tasks.withType(JavaCompile).configureEach { @@ -69,7 +75,7 @@ java { jar { from { configurations.toJar.collect { it.isDirectory() ? it : zipTree(it) } } from("LICENSE") { - rename { "${it}_${project.archivesBaseName}"} + rename { "${it}_${project.archivesBaseName}" } } } diff --git a/gradle.properties b/gradle.properties index 6df89b72e0..893ab10a66 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ org.gradle.jvmargs=-Xmx3G mod_version = 1.5.2 maven_group = net.coderbot archives_base_name = oculus - - forge_version=40.1.85 - loom.platform=forge \ No newline at end of file + forge_version=40.2.17 + + loom.platform=forge diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index dc461e451a..7454180f2a 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e6e5897b5..48c0a02ca4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index c53aefaa5f..1b6c787337 100644 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # diff --git a/libs/DistantHorizons-forge-2.0.2-a-dev-1.18.2.jar b/libs/DistantHorizons-forge-2.0.2-a-dev-1.18.2.jar new file mode 100644 index 0000000000..1433c24518 Binary files /dev/null and b/libs/DistantHorizons-forge-2.0.2-a-dev-1.18.2.jar differ diff --git a/src/main/java/io/github/douira/glsl_transformer/GLSLLexer.interp b/src/main/java/io/github/douira/glsl_transformer/GLSLLexer.interp new file mode 100644 index 0000000000..55f4d2b93e --- /dev/null +++ b/src/main/java/io/github/douira/glsl_transformer/GLSLLexer.interp @@ -0,0 +1,1045 @@ +token literal names: +null +null +'uniform' +'buffer' +'in' +'out' +'inout' +'highp' +'mediump' +'lowp' +'precision' +'const' +'precise' +null +'smooth' +'flat' +'centroid' +'attribute' +'volatile' +'varying' +'shared' +'layout' +'.length()' +'noperspective' +'sample' +'patch' +'coherent' +'restrict' +'readonly' +'writeonly' +'subroutine' +'devicecoherent' +'queuefamilycoherent' +'workgroupcoherent' +'subgroupcoherent' +'nonprivate' +'rayPayloadEXT' +'rayPayloadInEXT' +'hitAttributeEXT' +'callableDataEXT' +'callableDataInEXT' +'ignoreIntersectionEXT' +'terminateRayEXT' +'accelerationStructureEXT' +'atomic_uint' +'struct' +'if' +'else' +'switch' +'case' +'default' +'while' +'do' +'for' +'continue' +'break' +'return' +'discard' +'demote' +null +null +null +null +null +null +null +null +null +null +'bool' +'bvec2' +'bvec3' +'bvec4' +'int8_t' +'i8vec2' +'i8vec3' +'i8vec4' +'uint8_t' +'u8vec2' +'u8vec3' +'u8vec4' +'int16_t' +'i16vec2' +'i16vec3' +'i16vec4' +'uint16_t' +'u16vec2' +'u16vec3' +'u16vec4' +null +null +null +null +null +null +null +null +'int64_t' +'i64vec2' +'i64vec3' +'i64vec4' +'uint64_t' +'u64vec2' +'u64vec3' +'u64vec4' +'float16_t' +'f16vec2' +'f16vec3' +'f16vec4' +null +'f16mat2x3' +'f16mat2x4' +'f16mat3x2' +null +'f16mat3x4' +'f16mat4x2' +'f16mat4x3' +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +'image1D' +'image2D' +'image3D' +'uimage1D' +'uimage2D' +'uimage3D' +'iimage1D' +'iimage2D' +'iimage3D' +'sampler1D' +'sampler2D' +'sampler3D' +'sampler2DRect' +'sampler1DShadow' +'sampler2DShadow' +'sampler2DRectShadow' +'sampler1DArray' +'sampler2DArray' +'sampler1DArrayShadow' +'sampler2DArrayShadow' +'isampler1D' +'isampler2D' +'isampler2DRect' +'isampler3D' +'isampler1DArray' +'isampler2DArray' +'usampler1D' +'usampler2D' +'usampler2DRect' +'usampler3D' +'usampler1DArray' +'usampler2DArray' +'sampler2DMS' +'isampler2DMS' +'usampler2DMS' +'sampler2DMSArray' +'isampler2DMSArray' +'usampler2DMSArray' +'image2DRect' +'image1DArray' +'image2DArray' +'image2DMS' +'image2DMSArray' +'iimage2DRect' +'iimage1DArray' +'iimage2DArray' +'iimage2DMS' +'iimage2DMSArray' +'uimage2DRect' +'uimage1DArray' +'uimage2DArray' +'uimage2DMS' +'uimage2DMSArray' +'samplerCubeShadow' +'samplerCubeArrayShadow' +'samplerCube' +'isamplerCube' +'usamplerCube' +'samplerBuffer' +'isamplerBuffer' +'usamplerBuffer' +'samplerCubeArray' +'isamplerCubeArray' +'usamplerCubeArray' +'imageCube' +'uimageCube' +'iimageCube' +'imageBuffer' +'iimageBuffer' +'uimageBuffer' +'imageCubeArray' +'iimageCubeArray' +'uimageCubeArray' +'++' +'--' +'void' +'<<' +'>>' +'<=' +'>=' +'==' +'!=' +'&&' +'^^' +'||' +'*=' +'/=' +'%=' +'+=' +'-=' +'<<=' +'>>=' +'&=' +'^=' +'|=' +null +null +'{' +'}' +';' +'[' +']' +',' +'.' +'+' +'-' +'!' +'~' +'*' +'/' +'%' +'<' +null +'&' +'|' +'^' +'?' +'=' +null +null +null +'#' +null +null +null +null +null +null +'extension' +'version' +null +'include' +'pragma' +'debug' +'optimize' +null +'on' +'off' +'all' +'require' +'enable' +'warn' +'disable' +null +null +null +'STDGL' +'core' +'compatibility' +'es' +'110' +'120' +'100' +'130' +'140' +'150' +'330' +'300' +'310' +'320' +'400' +'410' +'420' +'430' +'440' +'450' +'460' +null +null +null +null +null +null +null +null +null +null +'"' +null +null +null +null +null +null +null +null +null +null +null +null + +token symbolic names: +null +COLON +UNIFORM +BUFFER +IN +OUT +INOUT +HIGHP +MEDIUMP +LOWP +PRECISION +CONST +PRECISE +INVARIANT +SMOOTH +FLAT +CENTROID +ATTRIBUTE +VOLATILE +VARYING +SHARED +LAYOUT +DOT_LENGTH_METHOD_CALL +NOPERSPECTIVE +SAMPLE +PATCH +COHERENT +RESTRICT +READONLY +WRITEONLY +SUBROUTINE +DEVICECOHERENT +QUEUEFAMILYCOHERENT +WORKGROUPCOHERENT +SUBGROUPCOHERENT +NONPRIVATE +RAY_PAYLOAD_EXT +RAY_PAYLOAD_IN_EXT +HIT_ATTRIBUTE_EXT +CALLABLE_DATA_EXT +CALLABLE_DATA_IN_EXT +IGNORE_INTERSECTION_EXT +TERMINATE_RAY_EXT +ACCELERATION_STRUCTURE_EXT +ATOMIC_UINT +STRUCT +IF +ELSE +SWITCH +CASE +DEFAULT +WHILE +DO +FOR +CONTINUE +BREAK +RETURN +DISCARD +DEMOTE +UINT16CONSTANT +INT16CONSTANT +UINT32CONSTANT +INT32CONSTANT +UINT64CONSTANT +INT64CONSTANT +FLOAT16CONSTANT +FLOAT32CONSTANT +FLOAT64CONSTANT +BOOLCONSTANT +BOOL +BVEC2 +BVEC3 +BVEC4 +INT8 +I8VEC2 +I8VEC3 +I8VEC4 +UINT8 +U8VEC2 +U8VEC3 +U8VEC4 +INT16 +I16VEC2 +I16VEC3 +I16VEC4 +UINT16 +U16VEC2 +U16VEC3 +U16VEC4 +INT32 +I32VEC2 +I32VEC3 +I32VEC4 +UINT32 +U32VEC2 +U32VEC3 +U32VEC4 +INT64 +I64VEC2 +I64VEC3 +I64VEC4 +UINT64 +U64VEC2 +U64VEC3 +U64VEC4 +FLOAT16 +F16VEC2 +F16VEC3 +F16VEC4 +F16MAT2X2 +F16MAT2X3 +F16MAT2X4 +F16MAT3X2 +F16MAT3X3 +F16MAT3X4 +F16MAT4X2 +F16MAT4X3 +F16MAT4X4 +FLOAT32 +F32VEC2 +F32VEC3 +F32VEC4 +F32MAT2X2 +F32MAT2X3 +F32MAT2X4 +F32MAT3X2 +F32MAT3X3 +F32MAT3X4 +F32MAT4X2 +F32MAT4X3 +F32MAT4X4 +FLOAT64 +F64VEC2 +F64VEC3 +F64VEC4 +F64MAT2X2 +F64MAT2X3 +F64MAT2X4 +F64MAT3X2 +F64MAT3X3 +F64MAT3X4 +F64MAT4X2 +F64MAT4X3 +F64MAT4X4 +IMAGE1D +IMAGE2D +IMAGE3D +UIMAGE1D +UIMAGE2D +UIMAGE3D +IIMAGE1D +IIMAGE2D +IIMAGE3D +SAMPLER1D +SAMPLER2D +SAMPLER3D +SAMPLER2DRECT +SAMPLER1DSHADOW +SAMPLER2DSHADOW +SAMPLER2DRECTSHADOW +SAMPLER1DARRAY +SAMPLER2DARRAY +SAMPLER1DARRAYSHADOW +SAMPLER2DARRAYSHADOW +ISAMPLER1D +ISAMPLER2D +ISAMPLER2DRECT +ISAMPLER3D +ISAMPLER1DARRAY +ISAMPLER2DARRAY +USAMPLER1D +USAMPLER2D +USAMPLER2DRECT +USAMPLER3D +USAMPLER1DARRAY +USAMPLER2DARRAY +SAMPLER2DMS +ISAMPLER2DMS +USAMPLER2DMS +SAMPLER2DMSARRAY +ISAMPLER2DMSARRAY +USAMPLER2DMSARRAY +IMAGE2DRECT +IMAGE1DARRAY +IMAGE2DARRAY +IMAGE2DMS +IMAGE2DMSARRAY +IIMAGE2DRECT +IIMAGE1DARRAY +IIMAGE2DARRAY +IIMAGE2DMS +IIMAGE2DMSARRAY +UIMAGE2DRECT +UIMAGE1DARRAY +UIMAGE2DARRAY +UIMAGE2DMS +UIMAGE2DMSARRAY +SAMPLERCUBESHADOW +SAMPLERCUBEARRAYSHADOW +SAMPLERCUBE +ISAMPLERCUBE +USAMPLERCUBE +SAMPLERBUFFER +ISAMPLERBUFFER +USAMPLERBUFFER +SAMPLERCUBEARRAY +ISAMPLERCUBEARRAY +USAMPLERCUBEARRAY +IMAGECUBE +UIMAGECUBE +IIMAGECUBE +IMAGEBUFFER +IIMAGEBUFFER +UIMAGEBUFFER +IMAGECUBEARRAY +IIMAGECUBEARRAY +UIMAGECUBEARRAY +INC_OP +DEC_OP +VOID +LEFT_OP +RIGHT_OP +LE_OP +GE_OP +EQ_OP +NE_OP +LOGICAL_AND_OP +LOGICAL_XOR_OP +LOGICAL_OR_OP +MUL_ASSIGN +DIV_ASSIGN +MOD_ASSIGN +ADD_ASSIGN +SUB_ASSIGN +LEFT_ASSIGN +RIGHT_ASSIGN +AND_ASSIGN +XOR_ASSIGN +OR_ASSIGN +LPAREN +RPAREN +LBRACE +RBRACE +SEMICOLON +LBRACKET +RBRACKET +COMMA +DOT +PLUS_OP +MINUS_OP +LOGICAL_NOT_OP +BITWISE_NEG_OP +TIMES_OP +DIV_OP +MOD_OP +LT_OP +GT_OP +BITWISE_AND_OP +BITWISE_OR_OP +BITWISE_XOR_OP +QUERY_OP +ASSIGN_OP +PP_ENTER_MODE +PP_EMPTY +NR_LINE +NR +IDENTIFIER +LINE_CONTINUE +LINE_COMMENT +BLOCK_COMMENT +WS +EOL +NR_EXTENSION +NR_VERSION +NR_CUSTOM +NR_INCLUDE +NR_PRAGMA +NR_PRAGMA_DEBUG +NR_PRAGMA_OPTIMIZE +NR_PRAGMA_INVARIANT +NR_ON +NR_OFF +NR_ALL +NR_REQUIRE +NR_ENABLE +NR_WARN +NR_DISABLE +NR_COLON +NR_LPAREN +NR_RPAREN +NR_STDGL +NR_CORE +NR_COMPATIBILITY +NR_ES +NR_GLSL_110 +NR_GLSL_120 +NR_GLSLES_100 +NR_GLSL_130 +NR_GLSL_140 +NR_GLSL_150 +NR_GLSL_330 +NR_GLSLES_300 +NR_GLSLES_310 +NR_GLSLES_320 +NR_GLSL_400 +NR_GLSL_410 +NR_GLSL_420 +NR_GLSL_430 +NR_GLSL_440 +NR_GLSL_450 +NR_GLSL_460 +NR_STRING_START +NR_STRING_START_ANGLE +NR_INTCONSTANT +NR_IDENTIFIER +NR_LINE_CONTINUE +NR_LINE_COMMENT +NR_BLOCK_COMMENT +NR_EOL +NR_WS +S_CONTENT +S_STRING_END +S_CONTENT_ANGLE +S_STRING_END_ANGLE +C_LINE_COMMENT +C_BLOCK_COMMENT +C_EOL +C_WS +C_CONTENT +PP_LINE_CONTINUE +PP_LINE_COMMENT +PP_BLOCK_COMMENT +PP_EOL +PP_CONTENT + +rule names: +DECIMAL_DIGITS +OCTAL_DIGITS +HEX_DIGITS +DIGIT +FLOAT_DIGITS +IDENTIFIER_frag +WS_frag +NEWLINE +NO_NEWLINE +LINE_CONTINUE_frag +COLON +UNIFORM +BUFFER +IN +OUT +INOUT +HIGHP +MEDIUMP +LOWP +PRECISION +CONST +PRECISE +INVARIANT +SMOOTH +FLAT +CENTROID +ATTRIBUTE +VOLATILE +VARYING +SHARED +LAYOUT +DOT_LENGTH_METHOD_CALL +NOPERSPECTIVE +SAMPLE +PATCH +COHERENT +RESTRICT +READONLY +WRITEONLY +SUBROUTINE +DEVICECOHERENT +QUEUEFAMILYCOHERENT +WORKGROUPCOHERENT +SUBGROUPCOHERENT +NONPRIVATE +RAY_PAYLOAD_EXT +RAY_PAYLOAD_IN_EXT +HIT_ATTRIBUTE_EXT +CALLABLE_DATA_EXT +CALLABLE_DATA_IN_EXT +IGNORE_INTERSECTION_EXT +TERMINATE_RAY_EXT +ACCELERATION_STRUCTURE_EXT +ATOMIC_UINT +STRUCT +IF +ELSE +SWITCH +CASE +DEFAULT +WHILE +DO +FOR +CONTINUE +BREAK +RETURN +DISCARD +DEMOTE +INTCONSTANT_frag +FLOAT_SUFFIX +HALF_SUFFIX +DOUBLE_SUFFIX +UNSIGNED_SUFFIX +SHORT_SUFFIX +UINT16CONSTANT +INT16CONSTANT +UINT32CONSTANT +INT32CONSTANT +UINT64CONSTANT +INT64CONSTANT +FLOAT16CONSTANT +FLOAT32CONSTANT +FLOAT64CONSTANT +BOOLCONSTANT +BOOL +BVEC2 +BVEC3 +BVEC4 +INT8 +I8VEC2 +I8VEC3 +I8VEC4 +UINT8 +U8VEC2 +U8VEC3 +U8VEC4 +INT16 +I16VEC2 +I16VEC3 +I16VEC4 +UINT16 +U16VEC2 +U16VEC3 +U16VEC4 +INT32 +I32VEC2 +I32VEC3 +I32VEC4 +UINT32 +U32VEC2 +U32VEC3 +U32VEC4 +INT64 +I64VEC2 +I64VEC3 +I64VEC4 +UINT64 +U64VEC2 +U64VEC3 +U64VEC4 +FLOAT16 +F16VEC2 +F16VEC3 +F16VEC4 +F16MAT2X2 +F16MAT2X3 +F16MAT2X4 +F16MAT3X2 +F16MAT3X3 +F16MAT3X4 +F16MAT4X2 +F16MAT4X3 +F16MAT4X4 +FLOAT32 +F32VEC2 +F32VEC3 +F32VEC4 +F32MAT2X2 +F32MAT2X3 +F32MAT2X4 +F32MAT3X2 +F32MAT3X3 +F32MAT3X4 +F32MAT4X2 +F32MAT4X3 +F32MAT4X4 +FLOAT64 +F64VEC2 +F64VEC3 +F64VEC4 +F64MAT2X2 +F64MAT2X3 +F64MAT2X4 +F64MAT3X2 +F64MAT3X3 +F64MAT3X4 +F64MAT4X2 +F64MAT4X3 +F64MAT4X4 +IMAGE1D +IMAGE2D +IMAGE3D +UIMAGE1D +UIMAGE2D +UIMAGE3D +IIMAGE1D +IIMAGE2D +IIMAGE3D +SAMPLER1D +SAMPLER2D +SAMPLER3D +SAMPLER2DRECT +SAMPLER1DSHADOW +SAMPLER2DSHADOW +SAMPLER2DRECTSHADOW +SAMPLER1DARRAY +SAMPLER2DARRAY +SAMPLER1DARRAYSHADOW +SAMPLER2DARRAYSHADOW +ISAMPLER1D +ISAMPLER2D +ISAMPLER2DRECT +ISAMPLER3D +ISAMPLER1DARRAY +ISAMPLER2DARRAY +USAMPLER1D +USAMPLER2D +USAMPLER2DRECT +USAMPLER3D +USAMPLER1DARRAY +USAMPLER2DARRAY +SAMPLER2DMS +ISAMPLER2DMS +USAMPLER2DMS +SAMPLER2DMSARRAY +ISAMPLER2DMSARRAY +USAMPLER2DMSARRAY +IMAGE2DRECT +IMAGE1DARRAY +IMAGE2DARRAY +IMAGE2DMS +IMAGE2DMSARRAY +IIMAGE2DRECT +IIMAGE1DARRAY +IIMAGE2DARRAY +IIMAGE2DMS +IIMAGE2DMSARRAY +UIMAGE2DRECT +UIMAGE1DARRAY +UIMAGE2DARRAY +UIMAGE2DMS +UIMAGE2DMSARRAY +SAMPLERCUBESHADOW +SAMPLERCUBEARRAYSHADOW +SAMPLERCUBE +ISAMPLERCUBE +USAMPLERCUBE +SAMPLERBUFFER +ISAMPLERBUFFER +USAMPLERBUFFER +SAMPLERCUBEARRAY +ISAMPLERCUBEARRAY +USAMPLERCUBEARRAY +IMAGECUBE +UIMAGECUBE +IIMAGECUBE +IMAGEBUFFER +IIMAGEBUFFER +UIMAGEBUFFER +IMAGECUBEARRAY +IIMAGECUBEARRAY +UIMAGECUBEARRAY +INC_OP +DEC_OP +VOID +LEFT_OP +RIGHT_OP +LE_OP +GE_OP +EQ_OP +NE_OP +LOGICAL_AND_OP +LOGICAL_XOR_OP +LOGICAL_OR_OP +MUL_ASSIGN +DIV_ASSIGN +MOD_ASSIGN +ADD_ASSIGN +SUB_ASSIGN +LEFT_ASSIGN +RIGHT_ASSIGN +AND_ASSIGN +XOR_ASSIGN +OR_ASSIGN +LPAREN +RPAREN +LBRACE +RBRACE +SEMICOLON +LBRACKET +RBRACKET +COMMA +DOT +PLUS_OP +MINUS_OP +LOGICAL_NOT_OP +BITWISE_NEG_OP +TIMES_OP +DIV_OP +MOD_OP +LT_OP +GT_OP +BITWISE_AND_OP +BITWISE_OR_OP +BITWISE_XOR_OP +QUERY_OP +ASSIGN_OP +NR_PP_PREFIX +PP_ENTER_MODE +PP_EMPTY +NR_LINE +NR +IDENTIFIER +LINE_COMMENT_frag +BLOCK_COMMENT_frag +LINE_CONTINUE +LINE_COMMENT +BLOCK_COMMENT +WS +EOL +NR_EXTENSION +NR_VERSION +NR_CUSTOM +NR_INCLUDE +NR_PRAGMA +NR_PRAGMA_DEBUG +NR_PRAGMA_OPTIMIZE +NR_PRAGMA_INVARIANT +NR_ON +NR_OFF +NR_ALL +NR_REQUIRE +NR_ENABLE +NR_WARN +NR_DISABLE +NR_COLON +NR_LPAREN +NR_RPAREN +NR_STDGL +NR_CORE +NR_COMPATIBILITY +NR_ES +NR_GLSL_110 +NR_GLSL_120 +NR_GLSLES_100 +NR_GLSL_130 +NR_GLSL_140 +NR_GLSL_150 +NR_GLSL_330 +NR_GLSLES_300 +NR_GLSLES_310 +NR_GLSLES_320 +NR_GLSL_400 +NR_GLSL_410 +NR_GLSL_420 +NR_GLSL_430 +NR_GLSL_440 +NR_GLSL_450 +NR_GLSL_460 +NR_STRING_START +NR_STRING_START_ANGLE +NR_INTCONSTANT +NR_IDENTIFIER +NR_LINE_CONTINUE +NR_LINE_COMMENT +NR_BLOCK_COMMENT +NR_EOL +NR_WS +S_CONTENT +S_STRING_END +S_CONTENT_ANGLE +S_STRING_END_ANGLE +C_LINE_COMMENT +C_BLOCK_COMMENT +C_EOL +C_WS +C_CONTENT +PP_LINE_CONTINUE +PP_LINE_COMMENT +PP_BLOCK_COMMENT +PP_EOL +PP_CONTENT + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN +null +null +WHITESPACE +COMMENTS +PREPROCESSOR + +mode names: +DEFAULT_MODE +NR_Mode +String +StringAngle +CustomDirective +Preprocessor + +atn: +[4, 0, 333, 3994, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, 188, 7, 188, 2, 189, 7, 189, 2, 190, 7, 190, 2, 191, 7, 191, 2, 192, 7, 192, 2, 193, 7, 193, 2, 194, 7, 194, 2, 195, 7, 195, 2, 196, 7, 196, 2, 197, 7, 197, 2, 198, 7, 198, 2, 199, 7, 199, 2, 200, 7, 200, 2, 201, 7, 201, 2, 202, 7, 202, 2, 203, 7, 203, 2, 204, 7, 204, 2, 205, 7, 205, 2, 206, 7, 206, 2, 207, 7, 207, 2, 208, 7, 208, 2, 209, 7, 209, 2, 210, 7, 210, 2, 211, 7, 211, 2, 212, 7, 212, 2, 213, 7, 213, 2, 214, 7, 214, 2, 215, 7, 215, 2, 216, 7, 216, 2, 217, 7, 217, 2, 218, 7, 218, 2, 219, 7, 219, 2, 220, 7, 220, 2, 221, 7, 221, 2, 222, 7, 222, 2, 223, 7, 223, 2, 224, 7, 224, 2, 225, 7, 225, 2, 226, 7, 226, 2, 227, 7, 227, 2, 228, 7, 228, 2, 229, 7, 229, 2, 230, 7, 230, 2, 231, 7, 231, 2, 232, 7, 232, 2, 233, 7, 233, 2, 234, 7, 234, 2, 235, 7, 235, 2, 236, 7, 236, 2, 237, 7, 237, 2, 238, 7, 238, 2, 239, 7, 239, 2, 240, 7, 240, 2, 241, 7, 241, 2, 242, 7, 242, 2, 243, 7, 243, 2, 244, 7, 244, 2, 245, 7, 245, 2, 246, 7, 246, 2, 247, 7, 247, 2, 248, 7, 248, 2, 249, 7, 249, 2, 250, 7, 250, 2, 251, 7, 251, 2, 252, 7, 252, 2, 253, 7, 253, 2, 254, 7, 254, 2, 255, 7, 255, 2, 256, 7, 256, 2, 257, 7, 257, 2, 258, 7, 258, 2, 259, 7, 259, 2, 260, 7, 260, 2, 261, 7, 261, 2, 262, 7, 262, 2, 263, 7, 263, 2, 264, 7, 264, 2, 265, 7, 265, 2, 266, 7, 266, 2, 267, 7, 267, 2, 268, 7, 268, 2, 269, 7, 269, 2, 270, 7, 270, 2, 271, 7, 271, 2, 272, 7, 272, 2, 273, 7, 273, 2, 274, 7, 274, 2, 275, 7, 275, 2, 276, 7, 276, 2, 277, 7, 277, 2, 278, 7, 278, 2, 279, 7, 279, 2, 280, 7, 280, 2, 281, 7, 281, 2, 282, 7, 282, 2, 283, 7, 283, 2, 284, 7, 284, 2, 285, 7, 285, 2, 286, 7, 286, 2, 287, 7, 287, 2, 288, 7, 288, 2, 289, 7, 289, 2, 290, 7, 290, 2, 291, 7, 291, 2, 292, 7, 292, 2, 293, 7, 293, 2, 294, 7, 294, 2, 295, 7, 295, 2, 296, 7, 296, 2, 297, 7, 297, 2, 298, 7, 298, 2, 299, 7, 299, 2, 300, 7, 300, 2, 301, 7, 301, 2, 302, 7, 302, 2, 303, 7, 303, 2, 304, 7, 304, 2, 305, 7, 305, 2, 306, 7, 306, 2, 307, 7, 307, 2, 308, 7, 308, 2, 309, 7, 309, 2, 310, 7, 310, 2, 311, 7, 311, 2, 312, 7, 312, 2, 313, 7, 313, 2, 314, 7, 314, 2, 315, 7, 315, 2, 316, 7, 316, 2, 317, 7, 317, 2, 318, 7, 318, 2, 319, 7, 319, 2, 320, 7, 320, 2, 321, 7, 321, 2, 322, 7, 322, 2, 323, 7, 323, 2, 324, 7, 324, 2, 325, 7, 325, 2, 326, 7, 326, 2, 327, 7, 327, 2, 328, 7, 328, 2, 329, 7, 329, 2, 330, 7, 330, 2, 331, 7, 331, 2, 332, 7, 332, 2, 333, 7, 333, 2, 334, 7, 334, 2, 335, 7, 335, 2, 336, 7, 336, 2, 337, 7, 337, 2, 338, 7, 338, 2, 339, 7, 339, 2, 340, 7, 340, 2, 341, 7, 341, 2, 342, 7, 342, 2, 343, 7, 343, 2, 344, 7, 344, 2, 345, 7, 345, 2, 346, 7, 346, 2, 347, 7, 347, 2, 348, 7, 348, 2, 349, 7, 349, 2, 350, 7, 350, 2, 351, 7, 351, 1, 0, 1, 0, 1, 0, 5, 0, 714, 8, 0, 10, 0, 12, 0, 717, 9, 0, 3, 0, 719, 8, 0, 1, 1, 1, 1, 4, 1, 723, 8, 1, 11, 1, 12, 1, 724, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 4, 2, 732, 8, 2, 11, 2, 12, 2, 733, 1, 3, 1, 3, 1, 4, 4, 4, 739, 8, 4, 11, 4, 12, 4, 740, 1, 4, 1, 4, 5, 4, 745, 8, 4, 10, 4, 12, 4, 748, 9, 4, 3, 4, 750, 8, 4, 1, 4, 1, 4, 4, 4, 754, 8, 4, 11, 4, 12, 4, 755, 3, 4, 758, 8, 4, 1, 4, 1, 4, 3, 4, 762, 8, 4, 1, 4, 5, 4, 765, 8, 4, 10, 4, 12, 4, 768, 9, 4, 3, 4, 770, 8, 4, 1, 5, 1, 5, 1, 5, 5, 5, 775, 8, 5, 10, 5, 12, 5, 778, 9, 5, 1, 6, 4, 6, 781, 8, 6, 11, 6, 12, 6, 782, 1, 7, 3, 7, 786, 8, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 3, 68, 1377, 8, 68, 1, 69, 1, 69, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 3, 81, 1414, 8, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 3, 83, 1429, 8, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, 1, 89, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 3, 104, 1586, 8, 104, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 3, 105, 1600, 8, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 3, 106, 1614, 8, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 3, 107, 1628, 8, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 3, 108, 1642, 8, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 3, 109, 1656, 8, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 3, 110, 1670, 8, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 3, 111, 1684, 8, 111, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 3, 124, 1801, 8, 124, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 3, 128, 1849, 8, 128, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 3, 132, 1897, 8, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 3, 133, 1913, 8, 133, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 3, 134, 1926, 8, 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 3, 135, 1939, 8, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 3, 136, 1952, 8, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 3, 137, 1980, 8, 137, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 3, 138, 1997, 8, 138, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 3, 139, 2014, 8, 139, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 3, 140, 2031, 8, 140, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 3, 141, 2059, 8, 141, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 3, 142, 2076, 8, 142, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 3, 143, 2093, 8, 143, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 3, 144, 2110, 8, 144, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 3, 145, 2138, 8, 145, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 3, 146, 2155, 8, 146, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 3, 147, 2169, 8, 147, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 3, 148, 2183, 8, 148, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 3, 149, 2197, 8, 149, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 3, 150, 2227, 8, 150, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 3, 151, 2245, 8, 151, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 3, 152, 2263, 8, 152, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 3, 153, 2281, 8, 153, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 3, 154, 2311, 8, 154, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 3, 155, 2329, 8, 155, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 3, 156, 2347, 8, 156, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 3, 157, 2365, 8, 157, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 3, 158, 2395, 8, 158, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 162, 1, 162, 1, 162, 1, 162, 1, 162, 1, 162, 1, 162, 1, 162, 1, 162, 1, 163, 1, 163, 1, 163, 1, 163, 1, 163, 1, 163, 1, 163, 1, 163, 1, 163, 1, 164, 1, 164, 1, 164, 1, 164, 1, 164, 1, 164, 1, 164, 1, 164, 1, 164, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 180, 1, 180, 1, 180, 1, 180, 1, 180, 1, 180, 1, 180, 1, 180, 1, 180, 1, 180, 1, 180, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 195, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 197, 1, 197, 1, 197, 1, 197, 1, 197, 1, 197, 1, 197, 1, 197, 1, 197, 1, 197, 1, 197, 1, 197, 1, 198, 1, 198, 1, 198, 1, 198, 1, 198, 1, 198, 1, 198, 1, 198, 1, 198, 1, 198, 1, 198, 1, 198, 1, 198, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 204, 1, 204, 1, 204, 1, 204, 1, 204, 1, 204, 1, 204, 1, 204, 1, 204, 1, 204, 1, 204, 1, 204, 1, 204, 1, 204, 1, 205, 1, 205, 1, 205, 1, 205, 1, 205, 1, 205, 1, 205, 1, 205, 1, 205, 1, 205, 1, 205, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 208, 1, 208, 1, 208, 1, 208, 1, 208, 1, 208, 1, 208, 1, 208, 1, 208, 1, 208, 1, 208, 1, 208, 1, 208, 1, 208, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 210, 1, 210, 1, 210, 1, 210, 1, 210, 1, 210, 1, 210, 1, 210, 1, 210, 1, 210, 1, 210, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 214, 1, 214, 1, 214, 1, 214, 1, 214, 1, 214, 1, 214, 1, 214, 1, 214, 1, 214, 1, 214, 1, 214, 1, 215, 1, 215, 1, 215, 1, 215, 1, 215, 1, 215, 1, 215, 1, 215, 1, 215, 1, 215, 1, 215, 1, 215, 1, 215, 1, 216, 1, 216, 1, 216, 1, 216, 1, 216, 1, 216, 1, 216, 1, 216, 1, 216, 1, 216, 1, 216, 1, 216, 1, 216, 1, 217, 1, 217, 1, 217, 1, 217, 1, 217, 1, 217, 1, 217, 1, 217, 1, 217, 1, 217, 1, 217, 1, 217, 1, 217, 1, 217, 1, 217, 1, 217, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 218, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 219, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 223, 1, 223, 1, 223, 1, 223, 1, 223, 1, 223, 1, 223, 1, 223, 1, 223, 1, 223, 1, 224, 1, 224, 1, 224, 1, 224, 1, 224, 1, 224, 1, 224, 1, 224, 1, 224, 1, 224, 1, 224, 1, 225, 1, 225, 1, 225, 1, 225, 1, 225, 1, 225, 1, 225, 1, 225, 1, 225, 1, 225, 1, 225, 1, 226, 1, 226, 1, 226, 1, 226, 1, 226, 1, 226, 1, 226, 1, 226, 1, 226, 1, 226, 1, 226, 1, 226, 1, 227, 1, 227, 1, 227, 1, 227, 1, 227, 1, 227, 1, 227, 1, 227, 1, 227, 1, 227, 1, 227, 1, 227, 1, 227, 1, 228, 1, 228, 1, 228, 1, 228, 1, 228, 1, 228, 1, 228, 1, 228, 1, 228, 1, 228, 1, 228, 1, 228, 1, 228, 1, 229, 1, 229, 1, 229, 1, 229, 1, 229, 1, 229, 1, 229, 1, 229, 1, 229, 1, 229, 1, 229, 1, 229, 1, 229, 1, 229, 1, 229, 1, 230, 1, 230, 1, 230, 1, 230, 1, 230, 1, 230, 1, 230, 1, 230, 1, 230, 1, 230, 1, 230, 1, 230, 1, 230, 1, 230, 1, 230, 1, 230, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 232, 1, 232, 1, 232, 1, 233, 1, 233, 1, 233, 1, 234, 1, 234, 1, 234, 1, 234, 1, 234, 1, 235, 1, 235, 1, 235, 1, 236, 1, 236, 1, 236, 1, 237, 1, 237, 1, 237, 1, 238, 1, 238, 1, 238, 1, 239, 1, 239, 1, 239, 1, 240, 1, 240, 1, 240, 1, 241, 1, 241, 1, 241, 1, 242, 1, 242, 1, 242, 1, 243, 1, 243, 1, 243, 1, 244, 1, 244, 1, 244, 1, 245, 1, 245, 1, 245, 1, 246, 1, 246, 1, 246, 1, 247, 1, 247, 1, 247, 1, 248, 1, 248, 1, 248, 1, 249, 1, 249, 1, 249, 1, 249, 1, 250, 1, 250, 1, 250, 1, 250, 1, 251, 1, 251, 1, 251, 1, 252, 1, 252, 1, 252, 1, 253, 1, 253, 1, 253, 1, 254, 1, 254, 1, 255, 1, 255, 1, 256, 1, 256, 1, 257, 1, 257, 1, 258, 1, 258, 1, 259, 1, 259, 1, 260, 1, 260, 1, 261, 1, 261, 1, 262, 1, 262, 1, 263, 1, 263, 1, 264, 1, 264, 1, 265, 1, 265, 1, 266, 1, 266, 1, 267, 1, 267, 1, 268, 1, 268, 1, 269, 1, 269, 1, 270, 1, 270, 1, 271, 1, 271, 1, 272, 1, 272, 1, 273, 1, 273, 1, 274, 1, 274, 1, 275, 1, 275, 1, 276, 1, 276, 1, 277, 1, 277, 5, 277, 3536, 8, 277, 10, 277, 12, 277, 3539, 9, 277, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 1, 278, 3, 278, 3584, 8, 278, 1, 278, 1, 278, 1, 278, 1, 279, 1, 279, 1, 279, 5, 279, 3592, 8, 279, 10, 279, 12, 279, 3595, 9, 279, 1, 279, 1, 279, 1, 279, 1, 279, 1, 280, 1, 280, 1, 280, 1, 280, 1, 280, 1, 280, 1, 280, 1, 280, 4, 280, 3609, 8, 280, 11, 280, 12, 280, 3610, 1, 280, 1, 280, 4, 280, 3615, 8, 280, 11, 280, 12, 280, 3616, 3, 280, 3619, 8, 280, 1, 280, 1, 280, 5, 280, 3623, 8, 280, 10, 280, 12, 280, 3626, 9, 280, 1, 280, 1, 280, 1, 280, 1, 280, 1, 281, 1, 281, 1, 281, 1, 281, 1, 282, 1, 282, 1, 283, 1, 283, 1, 283, 1, 283, 5, 283, 3642, 8, 283, 10, 283, 12, 283, 3645, 9, 283, 1, 284, 1, 284, 1, 284, 1, 284, 5, 284, 3651, 8, 284, 10, 284, 12, 284, 3654, 9, 284, 1, 284, 1, 284, 1, 284, 1, 285, 1, 285, 1, 285, 1, 285, 1, 286, 1, 286, 1, 286, 1, 286, 1, 286, 1, 287, 1, 287, 1, 287, 1, 287, 1, 288, 1, 288, 1, 288, 1, 288, 1, 289, 1, 289, 1, 289, 1, 289, 1, 290, 1, 290, 1, 290, 1, 290, 1, 290, 1, 290, 1, 290, 1, 290, 1, 290, 1, 290, 1, 291, 1, 291, 1, 291, 1, 291, 1, 291, 1, 291, 1, 291, 1, 291, 1, 292, 1, 292, 1, 292, 1, 292, 1, 292, 1, 292, 1, 292, 1, 292, 1, 292, 1, 292, 1, 292, 1, 293, 1, 293, 1, 293, 1, 293, 1, 293, 1, 293, 1, 293, 1, 293, 1, 293, 1, 293, 1, 294, 1, 294, 1, 294, 1, 294, 1, 294, 1, 294, 1, 294, 1, 295, 1, 295, 1, 295, 1, 295, 1, 295, 1, 295, 1, 296, 1, 296, 1, 296, 1, 296, 1, 296, 1, 296, 1, 296, 1, 296, 1, 296, 1, 297, 1, 297, 1, 297, 1, 297, 1, 297, 1, 297, 1, 297, 1, 297, 1, 297, 1, 297, 1, 298, 1, 298, 1, 298, 1, 299, 1, 299, 1, 299, 1, 299, 1, 300, 1, 300, 1, 300, 1, 300, 1, 301, 1, 301, 1, 301, 1, 301, 1, 301, 1, 301, 1, 301, 1, 301, 1, 302, 1, 302, 1, 302, 1, 302, 1, 302, 1, 302, 1, 302, 1, 303, 1, 303, 1, 303, 1, 303, 1, 303, 1, 304, 1, 304, 1, 304, 1, 304, 1, 304, 1, 304, 1, 304, 1, 304, 1, 305, 1, 305, 1, 306, 1, 306, 1, 307, 1, 307, 1, 308, 1, 308, 1, 308, 1, 308, 1, 308, 1, 308, 1, 309, 1, 309, 1, 309, 1, 309, 1, 309, 1, 310, 1, 310, 1, 310, 1, 310, 1, 310, 1, 310, 1, 310, 1, 310, 1, 310, 1, 310, 1, 310, 1, 310, 1, 310, 1, 310, 1, 311, 1, 311, 1, 311, 1, 312, 1, 312, 1, 312, 1, 312, 1, 313, 1, 313, 1, 313, 1, 313, 1, 314, 1, 314, 1, 314, 1, 314, 1, 315, 1, 315, 1, 315, 1, 315, 1, 316, 1, 316, 1, 316, 1, 316, 1, 317, 1, 317, 1, 317, 1, 317, 1, 318, 1, 318, 1, 318, 1, 318, 1, 319, 1, 319, 1, 319, 1, 319, 1, 320, 1, 320, 1, 320, 1, 320, 1, 321, 1, 321, 1, 321, 1, 321, 1, 322, 1, 322, 1, 322, 1, 322, 1, 323, 1, 323, 1, 323, 1, 323, 1, 324, 1, 324, 1, 324, 1, 324, 1, 325, 1, 325, 1, 325, 1, 325, 1, 326, 1, 326, 1, 326, 1, 326, 1, 327, 1, 327, 1, 327, 1, 327, 1, 328, 1, 328, 1, 328, 1, 328, 1, 329, 1, 329, 1, 329, 1, 329, 1, 329, 1, 330, 1, 330, 1, 330, 1, 330, 1, 330, 1, 331, 1, 331, 1, 332, 1, 332, 1, 333, 1, 333, 1, 333, 1, 333, 1, 334, 1, 334, 1, 334, 1, 334, 1, 335, 1, 335, 1, 335, 1, 335, 1, 336, 1, 336, 1, 336, 1, 336, 1, 337, 1, 337, 1, 337, 1, 337, 1, 338, 4, 338, 3927, 8, 338, 11, 338, 12, 338, 3928, 1, 339, 1, 339, 1, 339, 1, 339, 1, 340, 4, 340, 3936, 8, 340, 11, 340, 12, 340, 3937, 1, 341, 1, 341, 1, 341, 1, 341, 1, 342, 1, 342, 1, 342, 1, 342, 1, 343, 1, 343, 1, 343, 1, 343, 1, 344, 1, 344, 1, 344, 1, 344, 1, 344, 1, 345, 1, 345, 1, 345, 1, 345, 1, 346, 1, 346, 5, 346, 3963, 8, 346, 10, 346, 12, 346, 3966, 9, 346, 1, 347, 1, 347, 1, 347, 1, 347, 1, 348, 1, 348, 1, 348, 1, 348, 1, 349, 1, 349, 1, 349, 1, 349, 1, 350, 1, 350, 1, 350, 1, 350, 1, 350, 1, 351, 5, 351, 3986, 8, 351, 10, 351, 12, 351, 3989, 9, 351, 1, 351, 1, 351, 1, 351, 1, 351, 1, 3652, 0, 352, 6, 0, 8, 0, 10, 0, 12, 0, 14, 0, 16, 0, 18, 0, 20, 0, 22, 0, 24, 0, 26, 1, 28, 2, 30, 3, 32, 4, 34, 5, 36, 6, 38, 7, 40, 8, 42, 9, 44, 10, 46, 11, 48, 12, 50, 13, 52, 14, 54, 15, 56, 16, 58, 17, 60, 18, 62, 19, 64, 20, 66, 21, 68, 22, 70, 23, 72, 24, 74, 25, 76, 26, 78, 27, 80, 28, 82, 29, 84, 30, 86, 31, 88, 32, 90, 33, 92, 34, 94, 35, 96, 36, 98, 37, 100, 38, 102, 39, 104, 40, 106, 41, 108, 42, 110, 43, 112, 44, 114, 45, 116, 46, 118, 47, 120, 48, 122, 49, 124, 50, 126, 51, 128, 52, 130, 53, 132, 54, 134, 55, 136, 56, 138, 57, 140, 58, 142, 0, 144, 0, 146, 0, 148, 0, 150, 0, 152, 0, 154, 59, 156, 60, 158, 61, 160, 62, 162, 63, 164, 64, 166, 65, 168, 66, 170, 67, 172, 68, 174, 69, 176, 70, 178, 71, 180, 72, 182, 73, 184, 74, 186, 75, 188, 76, 190, 77, 192, 78, 194, 79, 196, 80, 198, 81, 200, 82, 202, 83, 204, 84, 206, 85, 208, 86, 210, 87, 212, 88, 214, 89, 216, 90, 218, 91, 220, 92, 222, 93, 224, 94, 226, 95, 228, 96, 230, 97, 232, 98, 234, 99, 236, 100, 238, 101, 240, 102, 242, 103, 244, 104, 246, 105, 248, 106, 250, 107, 252, 108, 254, 109, 256, 110, 258, 111, 260, 112, 262, 113, 264, 114, 266, 115, 268, 116, 270, 117, 272, 118, 274, 119, 276, 120, 278, 121, 280, 122, 282, 123, 284, 124, 286, 125, 288, 126, 290, 127, 292, 128, 294, 129, 296, 130, 298, 131, 300, 132, 302, 133, 304, 134, 306, 135, 308, 136, 310, 137, 312, 138, 314, 139, 316, 140, 318, 141, 320, 142, 322, 143, 324, 144, 326, 145, 328, 146, 330, 147, 332, 148, 334, 149, 336, 150, 338, 151, 340, 152, 342, 153, 344, 154, 346, 155, 348, 156, 350, 157, 352, 158, 354, 159, 356, 160, 358, 161, 360, 162, 362, 163, 364, 164, 366, 165, 368, 166, 370, 167, 372, 168, 374, 169, 376, 170, 378, 171, 380, 172, 382, 173, 384, 174, 386, 175, 388, 176, 390, 177, 392, 178, 394, 179, 396, 180, 398, 181, 400, 182, 402, 183, 404, 184, 406, 185, 408, 186, 410, 187, 412, 188, 414, 189, 416, 190, 418, 191, 420, 192, 422, 193, 424, 194, 426, 195, 428, 196, 430, 197, 432, 198, 434, 199, 436, 200, 438, 201, 440, 202, 442, 203, 444, 204, 446, 205, 448, 206, 450, 207, 452, 208, 454, 209, 456, 210, 458, 211, 460, 212, 462, 213, 464, 214, 466, 215, 468, 216, 470, 217, 472, 218, 474, 219, 476, 220, 478, 221, 480, 222, 482, 223, 484, 224, 486, 225, 488, 226, 490, 227, 492, 228, 494, 229, 496, 230, 498, 231, 500, 232, 502, 233, 504, 234, 506, 235, 508, 236, 510, 237, 512, 238, 514, 239, 516, 240, 518, 241, 520, 242, 522, 243, 524, 244, 526, 245, 528, 246, 530, 247, 532, 248, 534, 249, 536, 250, 538, 251, 540, 252, 542, 253, 544, 254, 546, 255, 548, 256, 550, 257, 552, 258, 554, 259, 556, 260, 558, 261, 560, 0, 562, 262, 564, 263, 566, 264, 568, 265, 570, 266, 572, 0, 574, 0, 576, 267, 578, 268, 580, 269, 582, 270, 584, 271, 586, 272, 588, 273, 590, 274, 592, 275, 594, 276, 596, 277, 598, 278, 600, 279, 602, 280, 604, 281, 606, 282, 608, 283, 610, 284, 612, 285, 614, 286, 616, 287, 618, 288, 620, 289, 622, 290, 624, 291, 626, 292, 628, 293, 630, 294, 632, 295, 634, 296, 636, 297, 638, 298, 640, 299, 642, 300, 644, 301, 646, 302, 648, 303, 650, 304, 652, 305, 654, 306, 656, 307, 658, 308, 660, 309, 662, 310, 664, 311, 666, 312, 668, 313, 670, 314, 672, 315, 674, 316, 676, 317, 678, 318, 680, 319, 682, 320, 684, 321, 686, 322, 688, 323, 690, 324, 692, 325, 694, 326, 696, 327, 698, 328, 700, 329, 702, 330, 704, 331, 706, 332, 708, 333, 6, 0, 1, 2, 3, 4, 5, 16, 2, 0, 65, 70, 97, 102, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 3, 0, 65, 90, 95, 95, 97, 122, 3, 0, 9, 9, 12, 13, 32, 32, 2, 0, 10, 10, 13, 13, 2, 0, 70, 70, 102, 102, 2, 0, 72, 72, 104, 104, 2, 0, 76, 76, 108, 108, 2, 0, 85, 85, 117, 117, 2, 0, 83, 83, 115, 115, 2, 0, 9, 9, 32, 32, 3, 0, 10, 10, 13, 13, 34, 34, 3, 0, 10, 10, 13, 13, 62, 62, 3, 0, 9, 10, 12, 13, 32, 32, 3, 0, 10, 10, 13, 13, 92, 92, 4061, 0, 26, 1, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 30, 1, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 0, 40, 1, 0, 0, 0, 0, 42, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 46, 1, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 50, 1, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 54, 1, 0, 0, 0, 0, 56, 1, 0, 0, 0, 0, 58, 1, 0, 0, 0, 0, 60, 1, 0, 0, 0, 0, 62, 1, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 66, 1, 0, 0, 0, 0, 68, 1, 0, 0, 0, 0, 70, 1, 0, 0, 0, 0, 72, 1, 0, 0, 0, 0, 74, 1, 0, 0, 0, 0, 76, 1, 0, 0, 0, 0, 78, 1, 0, 0, 0, 0, 80, 1, 0, 0, 0, 0, 82, 1, 0, 0, 0, 0, 84, 1, 0, 0, 0, 0, 86, 1, 0, 0, 0, 0, 88, 1, 0, 0, 0, 0, 90, 1, 0, 0, 0, 0, 92, 1, 0, 0, 0, 0, 94, 1, 0, 0, 0, 0, 96, 1, 0, 0, 0, 0, 98, 1, 0, 0, 0, 0, 100, 1, 0, 0, 0, 0, 102, 1, 0, 0, 0, 0, 104, 1, 0, 0, 0, 0, 106, 1, 0, 0, 0, 0, 108, 1, 0, 0, 0, 0, 110, 1, 0, 0, 0, 0, 112, 1, 0, 0, 0, 0, 114, 1, 0, 0, 0, 0, 116, 1, 0, 0, 0, 0, 118, 1, 0, 0, 0, 0, 120, 1, 0, 0, 0, 0, 122, 1, 0, 0, 0, 0, 124, 1, 0, 0, 0, 0, 126, 1, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 130, 1, 0, 0, 0, 0, 132, 1, 0, 0, 0, 0, 134, 1, 0, 0, 0, 0, 136, 1, 0, 0, 0, 0, 138, 1, 0, 0, 0, 0, 140, 1, 0, 0, 0, 0, 154, 1, 0, 0, 0, 0, 156, 1, 0, 0, 0, 0, 158, 1, 0, 0, 0, 0, 160, 1, 0, 0, 0, 0, 162, 1, 0, 0, 0, 0, 164, 1, 0, 0, 0, 0, 166, 1, 0, 0, 0, 0, 168, 1, 0, 0, 0, 0, 170, 1, 0, 0, 0, 0, 172, 1, 0, 0, 0, 0, 174, 1, 0, 0, 0, 0, 176, 1, 0, 0, 0, 0, 178, 1, 0, 0, 0, 0, 180, 1, 0, 0, 0, 0, 182, 1, 0, 0, 0, 0, 184, 1, 0, 0, 0, 0, 186, 1, 0, 0, 0, 0, 188, 1, 0, 0, 0, 0, 190, 1, 0, 0, 0, 0, 192, 1, 0, 0, 0, 0, 194, 1, 0, 0, 0, 0, 196, 1, 0, 0, 0, 0, 198, 1, 0, 0, 0, 0, 200, 1, 0, 0, 0, 0, 202, 1, 0, 0, 0, 0, 204, 1, 0, 0, 0, 0, 206, 1, 0, 0, 0, 0, 208, 1, 0, 0, 0, 0, 210, 1, 0, 0, 0, 0, 212, 1, 0, 0, 0, 0, 214, 1, 0, 0, 0, 0, 216, 1, 0, 0, 0, 0, 218, 1, 0, 0, 0, 0, 220, 1, 0, 0, 0, 0, 222, 1, 0, 0, 0, 0, 224, 1, 0, 0, 0, 0, 226, 1, 0, 0, 0, 0, 228, 1, 0, 0, 0, 0, 230, 1, 0, 0, 0, 0, 232, 1, 0, 0, 0, 0, 234, 1, 0, 0, 0, 0, 236, 1, 0, 0, 0, 0, 238, 1, 0, 0, 0, 0, 240, 1, 0, 0, 0, 0, 242, 1, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 246, 1, 0, 0, 0, 0, 248, 1, 0, 0, 0, 0, 250, 1, 0, 0, 0, 0, 252, 1, 0, 0, 0, 0, 254, 1, 0, 0, 0, 0, 256, 1, 0, 0, 0, 0, 258, 1, 0, 0, 0, 0, 260, 1, 0, 0, 0, 0, 262, 1, 0, 0, 0, 0, 264, 1, 0, 0, 0, 0, 266, 1, 0, 0, 0, 0, 268, 1, 0, 0, 0, 0, 270, 1, 0, 0, 0, 0, 272, 1, 0, 0, 0, 0, 274, 1, 0, 0, 0, 0, 276, 1, 0, 0, 0, 0, 278, 1, 0, 0, 0, 0, 280, 1, 0, 0, 0, 0, 282, 1, 0, 0, 0, 0, 284, 1, 0, 0, 0, 0, 286, 1, 0, 0, 0, 0, 288, 1, 0, 0, 0, 0, 290, 1, 0, 0, 0, 0, 292, 1, 0, 0, 0, 0, 294, 1, 0, 0, 0, 0, 296, 1, 0, 0, 0, 0, 298, 1, 0, 0, 0, 0, 300, 1, 0, 0, 0, 0, 302, 1, 0, 0, 0, 0, 304, 1, 0, 0, 0, 0, 306, 1, 0, 0, 0, 0, 308, 1, 0, 0, 0, 0, 310, 1, 0, 0, 0, 0, 312, 1, 0, 0, 0, 0, 314, 1, 0, 0, 0, 0, 316, 1, 0, 0, 0, 0, 318, 1, 0, 0, 0, 0, 320, 1, 0, 0, 0, 0, 322, 1, 0, 0, 0, 0, 324, 1, 0, 0, 0, 0, 326, 1, 0, 0, 0, 0, 328, 1, 0, 0, 0, 0, 330, 1, 0, 0, 0, 0, 332, 1, 0, 0, 0, 0, 334, 1, 0, 0, 0, 0, 336, 1, 0, 0, 0, 0, 338, 1, 0, 0, 0, 0, 340, 1, 0, 0, 0, 0, 342, 1, 0, 0, 0, 0, 344, 1, 0, 0, 0, 0, 346, 1, 0, 0, 0, 0, 348, 1, 0, 0, 0, 0, 350, 1, 0, 0, 0, 0, 352, 1, 0, 0, 0, 0, 354, 1, 0, 0, 0, 0, 356, 1, 0, 0, 0, 0, 358, 1, 0, 0, 0, 0, 360, 1, 0, 0, 0, 0, 362, 1, 0, 0, 0, 0, 364, 1, 0, 0, 0, 0, 366, 1, 0, 0, 0, 0, 368, 1, 0, 0, 0, 0, 370, 1, 0, 0, 0, 0, 372, 1, 0, 0, 0, 0, 374, 1, 0, 0, 0, 0, 376, 1, 0, 0, 0, 0, 378, 1, 0, 0, 0, 0, 380, 1, 0, 0, 0, 0, 382, 1, 0, 0, 0, 0, 384, 1, 0, 0, 0, 0, 386, 1, 0, 0, 0, 0, 388, 1, 0, 0, 0, 0, 390, 1, 0, 0, 0, 0, 392, 1, 0, 0, 0, 0, 394, 1, 0, 0, 0, 0, 396, 1, 0, 0, 0, 0, 398, 1, 0, 0, 0, 0, 400, 1, 0, 0, 0, 0, 402, 1, 0, 0, 0, 0, 404, 1, 0, 0, 0, 0, 406, 1, 0, 0, 0, 0, 408, 1, 0, 0, 0, 0, 410, 1, 0, 0, 0, 0, 412, 1, 0, 0, 0, 0, 414, 1, 0, 0, 0, 0, 416, 1, 0, 0, 0, 0, 418, 1, 0, 0, 0, 0, 420, 1, 0, 0, 0, 0, 422, 1, 0, 0, 0, 0, 424, 1, 0, 0, 0, 0, 426, 1, 0, 0, 0, 0, 428, 1, 0, 0, 0, 0, 430, 1, 0, 0, 0, 0, 432, 1, 0, 0, 0, 0, 434, 1, 0, 0, 0, 0, 436, 1, 0, 0, 0, 0, 438, 1, 0, 0, 0, 0, 440, 1, 0, 0, 0, 0, 442, 1, 0, 0, 0, 0, 444, 1, 0, 0, 0, 0, 446, 1, 0, 0, 0, 0, 448, 1, 0, 0, 0, 0, 450, 1, 0, 0, 0, 0, 452, 1, 0, 0, 0, 0, 454, 1, 0, 0, 0, 0, 456, 1, 0, 0, 0, 0, 458, 1, 0, 0, 0, 0, 460, 1, 0, 0, 0, 0, 462, 1, 0, 0, 0, 0, 464, 1, 0, 0, 0, 0, 466, 1, 0, 0, 0, 0, 468, 1, 0, 0, 0, 0, 470, 1, 0, 0, 0, 0, 472, 1, 0, 0, 0, 0, 474, 1, 0, 0, 0, 0, 476, 1, 0, 0, 0, 0, 478, 1, 0, 0, 0, 0, 480, 1, 0, 0, 0, 0, 482, 1, 0, 0, 0, 0, 484, 1, 0, 0, 0, 0, 486, 1, 0, 0, 0, 0, 488, 1, 0, 0, 0, 0, 490, 1, 0, 0, 0, 0, 492, 1, 0, 0, 0, 0, 494, 1, 0, 0, 0, 0, 496, 1, 0, 0, 0, 0, 498, 1, 0, 0, 0, 0, 500, 1, 0, 0, 0, 0, 502, 1, 0, 0, 0, 0, 504, 1, 0, 0, 0, 0, 506, 1, 0, 0, 0, 0, 508, 1, 0, 0, 0, 0, 510, 1, 0, 0, 0, 0, 512, 1, 0, 0, 0, 0, 514, 1, 0, 0, 0, 0, 516, 1, 0, 0, 0, 0, 518, 1, 0, 0, 0, 0, 520, 1, 0, 0, 0, 0, 522, 1, 0, 0, 0, 0, 524, 1, 0, 0, 0, 0, 526, 1, 0, 0, 0, 0, 528, 1, 0, 0, 0, 0, 530, 1, 0, 0, 0, 0, 532, 1, 0, 0, 0, 0, 534, 1, 0, 0, 0, 0, 536, 1, 0, 0, 0, 0, 538, 1, 0, 0, 0, 0, 540, 1, 0, 0, 0, 0, 542, 1, 0, 0, 0, 0, 544, 1, 0, 0, 0, 0, 546, 1, 0, 0, 0, 0, 548, 1, 0, 0, 0, 0, 550, 1, 0, 0, 0, 0, 552, 1, 0, 0, 0, 0, 554, 1, 0, 0, 0, 0, 556, 1, 0, 0, 0, 0, 558, 1, 0, 0, 0, 0, 562, 1, 0, 0, 0, 0, 564, 1, 0, 0, 0, 0, 566, 1, 0, 0, 0, 0, 568, 1, 0, 0, 0, 0, 570, 1, 0, 0, 0, 0, 576, 1, 0, 0, 0, 0, 578, 1, 0, 0, 0, 0, 580, 1, 0, 0, 0, 0, 582, 1, 0, 0, 0, 0, 584, 1, 0, 0, 0, 1, 586, 1, 0, 0, 0, 1, 588, 1, 0, 0, 0, 1, 590, 1, 0, 0, 0, 1, 592, 1, 0, 0, 0, 1, 594, 1, 0, 0, 0, 1, 596, 1, 0, 0, 0, 1, 598, 1, 0, 0, 0, 1, 600, 1, 0, 0, 0, 1, 602, 1, 0, 0, 0, 1, 604, 1, 0, 0, 0, 1, 606, 1, 0, 0, 0, 1, 608, 1, 0, 0, 0, 1, 610, 1, 0, 0, 0, 1, 612, 1, 0, 0, 0, 1, 614, 1, 0, 0, 0, 1, 616, 1, 0, 0, 0, 1, 618, 1, 0, 0, 0, 1, 620, 1, 0, 0, 0, 1, 622, 1, 0, 0, 0, 1, 624, 1, 0, 0, 0, 1, 626, 1, 0, 0, 0, 1, 628, 1, 0, 0, 0, 1, 630, 1, 0, 0, 0, 1, 632, 1, 0, 0, 0, 1, 634, 1, 0, 0, 0, 1, 636, 1, 0, 0, 0, 1, 638, 1, 0, 0, 0, 1, 640, 1, 0, 0, 0, 1, 642, 1, 0, 0, 0, 1, 644, 1, 0, 0, 0, 1, 646, 1, 0, 0, 0, 1, 648, 1, 0, 0, 0, 1, 650, 1, 0, 0, 0, 1, 652, 1, 0, 0, 0, 1, 654, 1, 0, 0, 0, 1, 656, 1, 0, 0, 0, 1, 658, 1, 0, 0, 0, 1, 660, 1, 0, 0, 0, 1, 662, 1, 0, 0, 0, 1, 664, 1, 0, 0, 0, 1, 666, 1, 0, 0, 0, 1, 668, 1, 0, 0, 0, 1, 670, 1, 0, 0, 0, 1, 672, 1, 0, 0, 0, 1, 674, 1, 0, 0, 0, 1, 676, 1, 0, 0, 0, 1, 678, 1, 0, 0, 0, 1, 680, 1, 0, 0, 0, 2, 682, 1, 0, 0, 0, 2, 684, 1, 0, 0, 0, 3, 686, 1, 0, 0, 0, 3, 688, 1, 0, 0, 0, 4, 690, 1, 0, 0, 0, 4, 692, 1, 0, 0, 0, 4, 694, 1, 0, 0, 0, 4, 696, 1, 0, 0, 0, 4, 698, 1, 0, 0, 0, 5, 700, 1, 0, 0, 0, 5, 702, 1, 0, 0, 0, 5, 704, 1, 0, 0, 0, 5, 706, 1, 0, 0, 0, 5, 708, 1, 0, 0, 0, 6, 718, 1, 0, 0, 0, 8, 720, 1, 0, 0, 0, 10, 726, 1, 0, 0, 0, 12, 735, 1, 0, 0, 0, 14, 757, 1, 0, 0, 0, 16, 771, 1, 0, 0, 0, 18, 780, 1, 0, 0, 0, 20, 785, 1, 0, 0, 0, 22, 789, 1, 0, 0, 0, 24, 791, 1, 0, 0, 0, 26, 794, 1, 0, 0, 0, 28, 796, 1, 0, 0, 0, 30, 804, 1, 0, 0, 0, 32, 811, 1, 0, 0, 0, 34, 814, 1, 0, 0, 0, 36, 818, 1, 0, 0, 0, 38, 824, 1, 0, 0, 0, 40, 830, 1, 0, 0, 0, 42, 838, 1, 0, 0, 0, 44, 843, 1, 0, 0, 0, 46, 853, 1, 0, 0, 0, 48, 859, 1, 0, 0, 0, 50, 867, 1, 0, 0, 0, 52, 877, 1, 0, 0, 0, 54, 884, 1, 0, 0, 0, 56, 889, 1, 0, 0, 0, 58, 898, 1, 0, 0, 0, 60, 908, 1, 0, 0, 0, 62, 917, 1, 0, 0, 0, 64, 925, 1, 0, 0, 0, 66, 932, 1, 0, 0, 0, 68, 939, 1, 0, 0, 0, 70, 949, 1, 0, 0, 0, 72, 965, 1, 0, 0, 0, 74, 974, 1, 0, 0, 0, 76, 982, 1, 0, 0, 0, 78, 993, 1, 0, 0, 0, 80, 1004, 1, 0, 0, 0, 82, 1015, 1, 0, 0, 0, 84, 1027, 1, 0, 0, 0, 86, 1040, 1, 0, 0, 0, 88, 1057, 1, 0, 0, 0, 90, 1079, 1, 0, 0, 0, 92, 1099, 1, 0, 0, 0, 94, 1118, 1, 0, 0, 0, 96, 1131, 1, 0, 0, 0, 98, 1145, 1, 0, 0, 0, 100, 1161, 1, 0, 0, 0, 102, 1177, 1, 0, 0, 0, 104, 1193, 1, 0, 0, 0, 106, 1211, 1, 0, 0, 0, 108, 1233, 1, 0, 0, 0, 110, 1249, 1, 0, 0, 0, 112, 1274, 1, 0, 0, 0, 114, 1288, 1, 0, 0, 0, 116, 1295, 1, 0, 0, 0, 118, 1298, 1, 0, 0, 0, 120, 1303, 1, 0, 0, 0, 122, 1310, 1, 0, 0, 0, 124, 1315, 1, 0, 0, 0, 126, 1323, 1, 0, 0, 0, 128, 1329, 1, 0, 0, 0, 130, 1332, 1, 0, 0, 0, 132, 1336, 1, 0, 0, 0, 134, 1345, 1, 0, 0, 0, 136, 1351, 1, 0, 0, 0, 138, 1358, 1, 0, 0, 0, 140, 1366, 1, 0, 0, 0, 142, 1376, 1, 0, 0, 0, 144, 1378, 1, 0, 0, 0, 146, 1380, 1, 0, 0, 0, 148, 1382, 1, 0, 0, 0, 150, 1384, 1, 0, 0, 0, 152, 1386, 1, 0, 0, 0, 154, 1388, 1, 0, 0, 0, 156, 1392, 1, 0, 0, 0, 158, 1395, 1, 0, 0, 0, 160, 1398, 1, 0, 0, 0, 162, 1400, 1, 0, 0, 0, 164, 1404, 1, 0, 0, 0, 166, 1407, 1, 0, 0, 0, 168, 1411, 1, 0, 0, 0, 170, 1415, 1, 0, 0, 0, 172, 1428, 1, 0, 0, 0, 174, 1430, 1, 0, 0, 0, 176, 1435, 1, 0, 0, 0, 178, 1441, 1, 0, 0, 0, 180, 1447, 1, 0, 0, 0, 182, 1453, 1, 0, 0, 0, 184, 1460, 1, 0, 0, 0, 186, 1467, 1, 0, 0, 0, 188, 1474, 1, 0, 0, 0, 190, 1481, 1, 0, 0, 0, 192, 1489, 1, 0, 0, 0, 194, 1496, 1, 0, 0, 0, 196, 1503, 1, 0, 0, 0, 198, 1510, 1, 0, 0, 0, 200, 1518, 1, 0, 0, 0, 202, 1526, 1, 0, 0, 0, 204, 1534, 1, 0, 0, 0, 206, 1542, 1, 0, 0, 0, 208, 1551, 1, 0, 0, 0, 210, 1559, 1, 0, 0, 0, 212, 1567, 1, 0, 0, 0, 214, 1585, 1, 0, 0, 0, 216, 1599, 1, 0, 0, 0, 218, 1613, 1, 0, 0, 0, 220, 1627, 1, 0, 0, 0, 222, 1641, 1, 0, 0, 0, 224, 1655, 1, 0, 0, 0, 226, 1669, 1, 0, 0, 0, 228, 1683, 1, 0, 0, 0, 230, 1685, 1, 0, 0, 0, 232, 1693, 1, 0, 0, 0, 234, 1701, 1, 0, 0, 0, 236, 1709, 1, 0, 0, 0, 238, 1717, 1, 0, 0, 0, 240, 1726, 1, 0, 0, 0, 242, 1734, 1, 0, 0, 0, 244, 1742, 1, 0, 0, 0, 246, 1750, 1, 0, 0, 0, 248, 1760, 1, 0, 0, 0, 250, 1768, 1, 0, 0, 0, 252, 1776, 1, 0, 0, 0, 254, 1800, 1, 0, 0, 0, 256, 1802, 1, 0, 0, 0, 258, 1812, 1, 0, 0, 0, 260, 1822, 1, 0, 0, 0, 262, 1848, 1, 0, 0, 0, 264, 1850, 1, 0, 0, 0, 266, 1860, 1, 0, 0, 0, 268, 1870, 1, 0, 0, 0, 270, 1896, 1, 0, 0, 0, 272, 1912, 1, 0, 0, 0, 274, 1925, 1, 0, 0, 0, 276, 1938, 1, 0, 0, 0, 278, 1951, 1, 0, 0, 0, 280, 1979, 1, 0, 0, 0, 282, 1996, 1, 0, 0, 0, 284, 2013, 1, 0, 0, 0, 286, 2030, 1, 0, 0, 0, 288, 2058, 1, 0, 0, 0, 290, 2075, 1, 0, 0, 0, 292, 2092, 1, 0, 0, 0, 294, 2109, 1, 0, 0, 0, 296, 2137, 1, 0, 0, 0, 298, 2154, 1, 0, 0, 0, 300, 2168, 1, 0, 0, 0, 302, 2182, 1, 0, 0, 0, 304, 2196, 1, 0, 0, 0, 306, 2226, 1, 0, 0, 0, 308, 2244, 1, 0, 0, 0, 310, 2262, 1, 0, 0, 0, 312, 2280, 1, 0, 0, 0, 314, 2310, 1, 0, 0, 0, 316, 2328, 1, 0, 0, 0, 318, 2346, 1, 0, 0, 0, 320, 2364, 1, 0, 0, 0, 322, 2394, 1, 0, 0, 0, 324, 2396, 1, 0, 0, 0, 326, 2404, 1, 0, 0, 0, 328, 2412, 1, 0, 0, 0, 330, 2420, 1, 0, 0, 0, 332, 2429, 1, 0, 0, 0, 334, 2438, 1, 0, 0, 0, 336, 2447, 1, 0, 0, 0, 338, 2456, 1, 0, 0, 0, 340, 2465, 1, 0, 0, 0, 342, 2474, 1, 0, 0, 0, 344, 2484, 1, 0, 0, 0, 346, 2494, 1, 0, 0, 0, 348, 2504, 1, 0, 0, 0, 350, 2518, 1, 0, 0, 0, 352, 2534, 1, 0, 0, 0, 354, 2550, 1, 0, 0, 0, 356, 2570, 1, 0, 0, 0, 358, 2585, 1, 0, 0, 0, 360, 2600, 1, 0, 0, 0, 362, 2623, 1, 0, 0, 0, 364, 2644, 1, 0, 0, 0, 366, 2657, 1, 0, 0, 0, 368, 2668, 1, 0, 0, 0, 370, 2685, 1, 0, 0, 0, 372, 2696, 1, 0, 0, 0, 374, 2714, 1, 0, 0, 0, 376, 2730, 1, 0, 0, 0, 378, 2743, 1, 0, 0, 0, 380, 2754, 1, 0, 0, 0, 382, 2771, 1, 0, 0, 0, 384, 2782, 1, 0, 0, 0, 386, 2800, 1, 0, 0, 0, 388, 2816, 1, 0, 0, 0, 390, 2830, 1, 0, 0, 0, 392, 2845, 1, 0, 0, 0, 394, 2860, 1, 0, 0, 0, 396, 2879, 1, 0, 0, 0, 398, 2899, 1, 0, 0, 0, 400, 2919, 1, 0, 0, 0, 402, 2931, 1, 0, 0, 0, 404, 2944, 1, 0, 0, 0, 406, 2957, 1, 0, 0, 0, 408, 2967, 1, 0, 0, 0, 410, 2982, 1, 0, 0, 0, 412, 2995, 1, 0, 0, 0, 414, 3009, 1, 0, 0, 0, 416, 3023, 1, 0, 0, 0, 418, 3034, 1, 0, 0, 0, 420, 3050, 1, 0, 0, 0, 422, 3063, 1, 0, 0, 0, 424, 3077, 1, 0, 0, 0, 426, 3091, 1, 0, 0, 0, 428, 3102, 1, 0, 0, 0, 430, 3118, 1, 0, 0, 0, 432, 3136, 1, 0, 0, 0, 434, 3159, 1, 0, 0, 0, 436, 3171, 1, 0, 0, 0, 438, 3184, 1, 0, 0, 0, 440, 3197, 1, 0, 0, 0, 442, 3213, 1, 0, 0, 0, 444, 3230, 1, 0, 0, 0, 446, 3247, 1, 0, 0, 0, 448, 3264, 1, 0, 0, 0, 450, 3282, 1, 0, 0, 0, 452, 3300, 1, 0, 0, 0, 454, 3310, 1, 0, 0, 0, 456, 3321, 1, 0, 0, 0, 458, 3332, 1, 0, 0, 0, 460, 3344, 1, 0, 0, 0, 462, 3357, 1, 0, 0, 0, 464, 3370, 1, 0, 0, 0, 466, 3385, 1, 0, 0, 0, 468, 3401, 1, 0, 0, 0, 470, 3417, 1, 0, 0, 0, 472, 3420, 1, 0, 0, 0, 474, 3423, 1, 0, 0, 0, 476, 3428, 1, 0, 0, 0, 478, 3431, 1, 0, 0, 0, 480, 3434, 1, 0, 0, 0, 482, 3437, 1, 0, 0, 0, 484, 3440, 1, 0, 0, 0, 486, 3443, 1, 0, 0, 0, 488, 3446, 1, 0, 0, 0, 490, 3449, 1, 0, 0, 0, 492, 3452, 1, 0, 0, 0, 494, 3455, 1, 0, 0, 0, 496, 3458, 1, 0, 0, 0, 498, 3461, 1, 0, 0, 0, 500, 3464, 1, 0, 0, 0, 502, 3467, 1, 0, 0, 0, 504, 3470, 1, 0, 0, 0, 506, 3474, 1, 0, 0, 0, 508, 3478, 1, 0, 0, 0, 510, 3481, 1, 0, 0, 0, 512, 3484, 1, 0, 0, 0, 514, 3487, 1, 0, 0, 0, 516, 3489, 1, 0, 0, 0, 518, 3491, 1, 0, 0, 0, 520, 3493, 1, 0, 0, 0, 522, 3495, 1, 0, 0, 0, 524, 3497, 1, 0, 0, 0, 526, 3499, 1, 0, 0, 0, 528, 3501, 1, 0, 0, 0, 530, 3503, 1, 0, 0, 0, 532, 3505, 1, 0, 0, 0, 534, 3507, 1, 0, 0, 0, 536, 3509, 1, 0, 0, 0, 538, 3511, 1, 0, 0, 0, 540, 3513, 1, 0, 0, 0, 542, 3515, 1, 0, 0, 0, 544, 3517, 1, 0, 0, 0, 546, 3519, 1, 0, 0, 0, 548, 3521, 1, 0, 0, 0, 550, 3523, 1, 0, 0, 0, 552, 3525, 1, 0, 0, 0, 554, 3527, 1, 0, 0, 0, 556, 3529, 1, 0, 0, 0, 558, 3531, 1, 0, 0, 0, 560, 3533, 1, 0, 0, 0, 562, 3540, 1, 0, 0, 0, 564, 3588, 1, 0, 0, 0, 566, 3600, 1, 0, 0, 0, 568, 3631, 1, 0, 0, 0, 570, 3635, 1, 0, 0, 0, 572, 3637, 1, 0, 0, 0, 574, 3646, 1, 0, 0, 0, 576, 3658, 1, 0, 0, 0, 578, 3662, 1, 0, 0, 0, 580, 3667, 1, 0, 0, 0, 582, 3671, 1, 0, 0, 0, 584, 3675, 1, 0, 0, 0, 586, 3679, 1, 0, 0, 0, 588, 3689, 1, 0, 0, 0, 590, 3697, 1, 0, 0, 0, 592, 3708, 1, 0, 0, 0, 594, 3718, 1, 0, 0, 0, 596, 3725, 1, 0, 0, 0, 598, 3731, 1, 0, 0, 0, 600, 3740, 1, 0, 0, 0, 602, 3750, 1, 0, 0, 0, 604, 3753, 1, 0, 0, 0, 606, 3757, 1, 0, 0, 0, 608, 3761, 1, 0, 0, 0, 610, 3769, 1, 0, 0, 0, 612, 3776, 1, 0, 0, 0, 614, 3781, 1, 0, 0, 0, 616, 3789, 1, 0, 0, 0, 618, 3791, 1, 0, 0, 0, 620, 3793, 1, 0, 0, 0, 622, 3795, 1, 0, 0, 0, 624, 3801, 1, 0, 0, 0, 626, 3806, 1, 0, 0, 0, 628, 3820, 1, 0, 0, 0, 630, 3823, 1, 0, 0, 0, 632, 3827, 1, 0, 0, 0, 634, 3831, 1, 0, 0, 0, 636, 3835, 1, 0, 0, 0, 638, 3839, 1, 0, 0, 0, 640, 3843, 1, 0, 0, 0, 642, 3847, 1, 0, 0, 0, 644, 3851, 1, 0, 0, 0, 646, 3855, 1, 0, 0, 0, 648, 3859, 1, 0, 0, 0, 650, 3863, 1, 0, 0, 0, 652, 3867, 1, 0, 0, 0, 654, 3871, 1, 0, 0, 0, 656, 3875, 1, 0, 0, 0, 658, 3879, 1, 0, 0, 0, 660, 3883, 1, 0, 0, 0, 662, 3887, 1, 0, 0, 0, 664, 3891, 1, 0, 0, 0, 666, 3896, 1, 0, 0, 0, 668, 3901, 1, 0, 0, 0, 670, 3903, 1, 0, 0, 0, 672, 3905, 1, 0, 0, 0, 674, 3909, 1, 0, 0, 0, 676, 3913, 1, 0, 0, 0, 678, 3917, 1, 0, 0, 0, 680, 3921, 1, 0, 0, 0, 682, 3926, 1, 0, 0, 0, 684, 3930, 1, 0, 0, 0, 686, 3935, 1, 0, 0, 0, 688, 3939, 1, 0, 0, 0, 690, 3943, 1, 0, 0, 0, 692, 3947, 1, 0, 0, 0, 694, 3951, 1, 0, 0, 0, 696, 3956, 1, 0, 0, 0, 698, 3960, 1, 0, 0, 0, 700, 3967, 1, 0, 0, 0, 702, 3971, 1, 0, 0, 0, 704, 3975, 1, 0, 0, 0, 706, 3979, 1, 0, 0, 0, 708, 3987, 1, 0, 0, 0, 710, 719, 5, 48, 0, 0, 711, 715, 2, 49, 57, 0, 712, 714, 3, 12, 3, 0, 713, 712, 1, 0, 0, 0, 714, 717, 1, 0, 0, 0, 715, 713, 1, 0, 0, 0, 715, 716, 1, 0, 0, 0, 716, 719, 1, 0, 0, 0, 717, 715, 1, 0, 0, 0, 718, 710, 1, 0, 0, 0, 718, 711, 1, 0, 0, 0, 719, 7, 1, 0, 0, 0, 720, 722, 5, 48, 0, 0, 721, 723, 2, 48, 55, 0, 722, 721, 1, 0, 0, 0, 723, 724, 1, 0, 0, 0, 724, 722, 1, 0, 0, 0, 724, 725, 1, 0, 0, 0, 725, 9, 1, 0, 0, 0, 726, 727, 5, 48, 0, 0, 727, 728, 5, 120, 0, 0, 728, 731, 1, 0, 0, 0, 729, 732, 3, 12, 3, 0, 730, 732, 7, 0, 0, 0, 731, 729, 1, 0, 0, 0, 731, 730, 1, 0, 0, 0, 732, 733, 1, 0, 0, 0, 733, 731, 1, 0, 0, 0, 733, 734, 1, 0, 0, 0, 734, 11, 1, 0, 0, 0, 735, 736, 2, 48, 57, 0, 736, 13, 1, 0, 0, 0, 737, 739, 3, 12, 3, 0, 738, 737, 1, 0, 0, 0, 739, 740, 1, 0, 0, 0, 740, 738, 1, 0, 0, 0, 740, 741, 1, 0, 0, 0, 741, 749, 1, 0, 0, 0, 742, 746, 5, 46, 0, 0, 743, 745, 3, 12, 3, 0, 744, 743, 1, 0, 0, 0, 745, 748, 1, 0, 0, 0, 746, 744, 1, 0, 0, 0, 746, 747, 1, 0, 0, 0, 747, 750, 1, 0, 0, 0, 748, 746, 1, 0, 0, 0, 749, 742, 1, 0, 0, 0, 749, 750, 1, 0, 0, 0, 750, 758, 1, 0, 0, 0, 751, 753, 5, 46, 0, 0, 752, 754, 3, 12, 3, 0, 753, 752, 1, 0, 0, 0, 754, 755, 1, 0, 0, 0, 755, 753, 1, 0, 0, 0, 755, 756, 1, 0, 0, 0, 756, 758, 1, 0, 0, 0, 757, 738, 1, 0, 0, 0, 757, 751, 1, 0, 0, 0, 758, 769, 1, 0, 0, 0, 759, 761, 7, 1, 0, 0, 760, 762, 7, 2, 0, 0, 761, 760, 1, 0, 0, 0, 761, 762, 1, 0, 0, 0, 762, 766, 1, 0, 0, 0, 763, 765, 3, 12, 3, 0, 764, 763, 1, 0, 0, 0, 765, 768, 1, 0, 0, 0, 766, 764, 1, 0, 0, 0, 766, 767, 1, 0, 0, 0, 767, 770, 1, 0, 0, 0, 768, 766, 1, 0, 0, 0, 769, 759, 1, 0, 0, 0, 769, 770, 1, 0, 0, 0, 770, 15, 1, 0, 0, 0, 771, 776, 7, 3, 0, 0, 772, 775, 3, 12, 3, 0, 773, 775, 7, 3, 0, 0, 774, 772, 1, 0, 0, 0, 774, 773, 1, 0, 0, 0, 775, 778, 1, 0, 0, 0, 776, 774, 1, 0, 0, 0, 776, 777, 1, 0, 0, 0, 777, 17, 1, 0, 0, 0, 778, 776, 1, 0, 0, 0, 779, 781, 7, 4, 0, 0, 780, 779, 1, 0, 0, 0, 781, 782, 1, 0, 0, 0, 782, 780, 1, 0, 0, 0, 782, 783, 1, 0, 0, 0, 783, 19, 1, 0, 0, 0, 784, 786, 5, 13, 0, 0, 785, 784, 1, 0, 0, 0, 785, 786, 1, 0, 0, 0, 786, 787, 1, 0, 0, 0, 787, 788, 5, 10, 0, 0, 788, 21, 1, 0, 0, 0, 789, 790, 8, 5, 0, 0, 790, 23, 1, 0, 0, 0, 791, 792, 5, 92, 0, 0, 792, 793, 3, 20, 7, 0, 793, 25, 1, 0, 0, 0, 794, 795, 5, 58, 0, 0, 795, 27, 1, 0, 0, 0, 796, 797, 5, 117, 0, 0, 797, 798, 5, 110, 0, 0, 798, 799, 5, 105, 0, 0, 799, 800, 5, 102, 0, 0, 800, 801, 5, 111, 0, 0, 801, 802, 5, 114, 0, 0, 802, 803, 5, 109, 0, 0, 803, 29, 1, 0, 0, 0, 804, 805, 5, 98, 0, 0, 805, 806, 5, 117, 0, 0, 806, 807, 5, 102, 0, 0, 807, 808, 5, 102, 0, 0, 808, 809, 5, 101, 0, 0, 809, 810, 5, 114, 0, 0, 810, 31, 1, 0, 0, 0, 811, 812, 5, 105, 0, 0, 812, 813, 5, 110, 0, 0, 813, 33, 1, 0, 0, 0, 814, 815, 5, 111, 0, 0, 815, 816, 5, 117, 0, 0, 816, 817, 5, 116, 0, 0, 817, 35, 1, 0, 0, 0, 818, 819, 5, 105, 0, 0, 819, 820, 5, 110, 0, 0, 820, 821, 5, 111, 0, 0, 821, 822, 5, 117, 0, 0, 822, 823, 5, 116, 0, 0, 823, 37, 1, 0, 0, 0, 824, 825, 5, 104, 0, 0, 825, 826, 5, 105, 0, 0, 826, 827, 5, 103, 0, 0, 827, 828, 5, 104, 0, 0, 828, 829, 5, 112, 0, 0, 829, 39, 1, 0, 0, 0, 830, 831, 5, 109, 0, 0, 831, 832, 5, 101, 0, 0, 832, 833, 5, 100, 0, 0, 833, 834, 5, 105, 0, 0, 834, 835, 5, 117, 0, 0, 835, 836, 5, 109, 0, 0, 836, 837, 5, 112, 0, 0, 837, 41, 1, 0, 0, 0, 838, 839, 5, 108, 0, 0, 839, 840, 5, 111, 0, 0, 840, 841, 5, 119, 0, 0, 841, 842, 5, 112, 0, 0, 842, 43, 1, 0, 0, 0, 843, 844, 5, 112, 0, 0, 844, 845, 5, 114, 0, 0, 845, 846, 5, 101, 0, 0, 846, 847, 5, 99, 0, 0, 847, 848, 5, 105, 0, 0, 848, 849, 5, 115, 0, 0, 849, 850, 5, 105, 0, 0, 850, 851, 5, 111, 0, 0, 851, 852, 5, 110, 0, 0, 852, 45, 1, 0, 0, 0, 853, 854, 5, 99, 0, 0, 854, 855, 5, 111, 0, 0, 855, 856, 5, 110, 0, 0, 856, 857, 5, 115, 0, 0, 857, 858, 5, 116, 0, 0, 858, 47, 1, 0, 0, 0, 859, 860, 5, 112, 0, 0, 860, 861, 5, 114, 0, 0, 861, 862, 5, 101, 0, 0, 862, 863, 5, 99, 0, 0, 863, 864, 5, 105, 0, 0, 864, 865, 5, 115, 0, 0, 865, 866, 5, 101, 0, 0, 866, 49, 1, 0, 0, 0, 867, 868, 5, 105, 0, 0, 868, 869, 5, 110, 0, 0, 869, 870, 5, 118, 0, 0, 870, 871, 5, 97, 0, 0, 871, 872, 5, 114, 0, 0, 872, 873, 5, 105, 0, 0, 873, 874, 5, 97, 0, 0, 874, 875, 5, 110, 0, 0, 875, 876, 5, 116, 0, 0, 876, 51, 1, 0, 0, 0, 877, 878, 5, 115, 0, 0, 878, 879, 5, 109, 0, 0, 879, 880, 5, 111, 0, 0, 880, 881, 5, 111, 0, 0, 881, 882, 5, 116, 0, 0, 882, 883, 5, 104, 0, 0, 883, 53, 1, 0, 0, 0, 884, 885, 5, 102, 0, 0, 885, 886, 5, 108, 0, 0, 886, 887, 5, 97, 0, 0, 887, 888, 5, 116, 0, 0, 888, 55, 1, 0, 0, 0, 889, 890, 5, 99, 0, 0, 890, 891, 5, 101, 0, 0, 891, 892, 5, 110, 0, 0, 892, 893, 5, 116, 0, 0, 893, 894, 5, 114, 0, 0, 894, 895, 5, 111, 0, 0, 895, 896, 5, 105, 0, 0, 896, 897, 5, 100, 0, 0, 897, 57, 1, 0, 0, 0, 898, 899, 5, 97, 0, 0, 899, 900, 5, 116, 0, 0, 900, 901, 5, 116, 0, 0, 901, 902, 5, 114, 0, 0, 902, 903, 5, 105, 0, 0, 903, 904, 5, 98, 0, 0, 904, 905, 5, 117, 0, 0, 905, 906, 5, 116, 0, 0, 906, 907, 5, 101, 0, 0, 907, 59, 1, 0, 0, 0, 908, 909, 5, 118, 0, 0, 909, 910, 5, 111, 0, 0, 910, 911, 5, 108, 0, 0, 911, 912, 5, 97, 0, 0, 912, 913, 5, 116, 0, 0, 913, 914, 5, 105, 0, 0, 914, 915, 5, 108, 0, 0, 915, 916, 5, 101, 0, 0, 916, 61, 1, 0, 0, 0, 917, 918, 5, 118, 0, 0, 918, 919, 5, 97, 0, 0, 919, 920, 5, 114, 0, 0, 920, 921, 5, 121, 0, 0, 921, 922, 5, 105, 0, 0, 922, 923, 5, 110, 0, 0, 923, 924, 5, 103, 0, 0, 924, 63, 1, 0, 0, 0, 925, 926, 5, 115, 0, 0, 926, 927, 5, 104, 0, 0, 927, 928, 5, 97, 0, 0, 928, 929, 5, 114, 0, 0, 929, 930, 5, 101, 0, 0, 930, 931, 5, 100, 0, 0, 931, 65, 1, 0, 0, 0, 932, 933, 5, 108, 0, 0, 933, 934, 5, 97, 0, 0, 934, 935, 5, 121, 0, 0, 935, 936, 5, 111, 0, 0, 936, 937, 5, 117, 0, 0, 937, 938, 5, 116, 0, 0, 938, 67, 1, 0, 0, 0, 939, 940, 5, 46, 0, 0, 940, 941, 5, 108, 0, 0, 941, 942, 5, 101, 0, 0, 942, 943, 5, 110, 0, 0, 943, 944, 5, 103, 0, 0, 944, 945, 5, 116, 0, 0, 945, 946, 5, 104, 0, 0, 946, 947, 5, 40, 0, 0, 947, 948, 5, 41, 0, 0, 948, 69, 1, 0, 0, 0, 949, 950, 5, 110, 0, 0, 950, 951, 5, 111, 0, 0, 951, 952, 5, 112, 0, 0, 952, 953, 5, 101, 0, 0, 953, 954, 5, 114, 0, 0, 954, 955, 5, 115, 0, 0, 955, 956, 5, 112, 0, 0, 956, 957, 5, 101, 0, 0, 957, 958, 5, 99, 0, 0, 958, 959, 5, 116, 0, 0, 959, 960, 5, 105, 0, 0, 960, 961, 5, 118, 0, 0, 961, 962, 5, 101, 0, 0, 962, 963, 1, 0, 0, 0, 963, 964, 4, 32, 0, 0, 964, 71, 1, 0, 0, 0, 965, 966, 5, 115, 0, 0, 966, 967, 5, 97, 0, 0, 967, 968, 5, 109, 0, 0, 968, 969, 5, 112, 0, 0, 969, 970, 5, 108, 0, 0, 970, 971, 5, 101, 0, 0, 971, 972, 1, 0, 0, 0, 972, 973, 4, 33, 1, 0, 973, 73, 1, 0, 0, 0, 974, 975, 5, 112, 0, 0, 975, 976, 5, 97, 0, 0, 976, 977, 5, 116, 0, 0, 977, 978, 5, 99, 0, 0, 978, 979, 5, 104, 0, 0, 979, 980, 1, 0, 0, 0, 980, 981, 4, 34, 2, 0, 981, 75, 1, 0, 0, 0, 982, 983, 5, 99, 0, 0, 983, 984, 5, 111, 0, 0, 984, 985, 5, 104, 0, 0, 985, 986, 5, 101, 0, 0, 986, 987, 5, 114, 0, 0, 987, 988, 5, 101, 0, 0, 988, 989, 5, 110, 0, 0, 989, 990, 5, 116, 0, 0, 990, 991, 1, 0, 0, 0, 991, 992, 4, 35, 3, 0, 992, 77, 1, 0, 0, 0, 993, 994, 5, 114, 0, 0, 994, 995, 5, 101, 0, 0, 995, 996, 5, 115, 0, 0, 996, 997, 5, 116, 0, 0, 997, 998, 5, 114, 0, 0, 998, 999, 5, 105, 0, 0, 999, 1000, 5, 99, 0, 0, 1000, 1001, 5, 116, 0, 0, 1001, 1002, 1, 0, 0, 0, 1002, 1003, 4, 36, 4, 0, 1003, 79, 1, 0, 0, 0, 1004, 1005, 5, 114, 0, 0, 1005, 1006, 5, 101, 0, 0, 1006, 1007, 5, 97, 0, 0, 1007, 1008, 5, 100, 0, 0, 1008, 1009, 5, 111, 0, 0, 1009, 1010, 5, 110, 0, 0, 1010, 1011, 5, 108, 0, 0, 1011, 1012, 5, 121, 0, 0, 1012, 1013, 1, 0, 0, 0, 1013, 1014, 4, 37, 5, 0, 1014, 81, 1, 0, 0, 0, 1015, 1016, 5, 119, 0, 0, 1016, 1017, 5, 114, 0, 0, 1017, 1018, 5, 105, 0, 0, 1018, 1019, 5, 116, 0, 0, 1019, 1020, 5, 101, 0, 0, 1020, 1021, 5, 111, 0, 0, 1021, 1022, 5, 110, 0, 0, 1022, 1023, 5, 108, 0, 0, 1023, 1024, 5, 121, 0, 0, 1024, 1025, 1, 0, 0, 0, 1025, 1026, 4, 38, 6, 0, 1026, 83, 1, 0, 0, 0, 1027, 1028, 5, 115, 0, 0, 1028, 1029, 5, 117, 0, 0, 1029, 1030, 5, 98, 0, 0, 1030, 1031, 5, 114, 0, 0, 1031, 1032, 5, 111, 0, 0, 1032, 1033, 5, 117, 0, 0, 1033, 1034, 5, 116, 0, 0, 1034, 1035, 5, 105, 0, 0, 1035, 1036, 5, 110, 0, 0, 1036, 1037, 5, 101, 0, 0, 1037, 1038, 1, 0, 0, 0, 1038, 1039, 4, 39, 7, 0, 1039, 85, 1, 0, 0, 0, 1040, 1041, 5, 100, 0, 0, 1041, 1042, 5, 101, 0, 0, 1042, 1043, 5, 118, 0, 0, 1043, 1044, 5, 105, 0, 0, 1044, 1045, 5, 99, 0, 0, 1045, 1046, 5, 101, 0, 0, 1046, 1047, 5, 99, 0, 0, 1047, 1048, 5, 111, 0, 0, 1048, 1049, 5, 104, 0, 0, 1049, 1050, 5, 101, 0, 0, 1050, 1051, 5, 114, 0, 0, 1051, 1052, 5, 101, 0, 0, 1052, 1053, 5, 110, 0, 0, 1053, 1054, 5, 116, 0, 0, 1054, 1055, 1, 0, 0, 0, 1055, 1056, 4, 40, 8, 0, 1056, 87, 1, 0, 0, 0, 1057, 1058, 5, 113, 0, 0, 1058, 1059, 5, 117, 0, 0, 1059, 1060, 5, 101, 0, 0, 1060, 1061, 5, 117, 0, 0, 1061, 1062, 5, 101, 0, 0, 1062, 1063, 5, 102, 0, 0, 1063, 1064, 5, 97, 0, 0, 1064, 1065, 5, 109, 0, 0, 1065, 1066, 5, 105, 0, 0, 1066, 1067, 5, 108, 0, 0, 1067, 1068, 5, 121, 0, 0, 1068, 1069, 5, 99, 0, 0, 1069, 1070, 5, 111, 0, 0, 1070, 1071, 5, 104, 0, 0, 1071, 1072, 5, 101, 0, 0, 1072, 1073, 5, 114, 0, 0, 1073, 1074, 5, 101, 0, 0, 1074, 1075, 5, 110, 0, 0, 1075, 1076, 5, 116, 0, 0, 1076, 1077, 1, 0, 0, 0, 1077, 1078, 4, 41, 9, 0, 1078, 89, 1, 0, 0, 0, 1079, 1080, 5, 119, 0, 0, 1080, 1081, 5, 111, 0, 0, 1081, 1082, 5, 114, 0, 0, 1082, 1083, 5, 107, 0, 0, 1083, 1084, 5, 103, 0, 0, 1084, 1085, 5, 114, 0, 0, 1085, 1086, 5, 111, 0, 0, 1086, 1087, 5, 117, 0, 0, 1087, 1088, 5, 112, 0, 0, 1088, 1089, 5, 99, 0, 0, 1089, 1090, 5, 111, 0, 0, 1090, 1091, 5, 104, 0, 0, 1091, 1092, 5, 101, 0, 0, 1092, 1093, 5, 114, 0, 0, 1093, 1094, 5, 101, 0, 0, 1094, 1095, 5, 110, 0, 0, 1095, 1096, 5, 116, 0, 0, 1096, 1097, 1, 0, 0, 0, 1097, 1098, 4, 42, 10, 0, 1098, 91, 1, 0, 0, 0, 1099, 1100, 5, 115, 0, 0, 1100, 1101, 5, 117, 0, 0, 1101, 1102, 5, 98, 0, 0, 1102, 1103, 5, 103, 0, 0, 1103, 1104, 5, 114, 0, 0, 1104, 1105, 5, 111, 0, 0, 1105, 1106, 5, 117, 0, 0, 1106, 1107, 5, 112, 0, 0, 1107, 1108, 5, 99, 0, 0, 1108, 1109, 5, 111, 0, 0, 1109, 1110, 5, 104, 0, 0, 1110, 1111, 5, 101, 0, 0, 1111, 1112, 5, 114, 0, 0, 1112, 1113, 5, 101, 0, 0, 1113, 1114, 5, 110, 0, 0, 1114, 1115, 5, 116, 0, 0, 1115, 1116, 1, 0, 0, 0, 1116, 1117, 4, 43, 11, 0, 1117, 93, 1, 0, 0, 0, 1118, 1119, 5, 110, 0, 0, 1119, 1120, 5, 111, 0, 0, 1120, 1121, 5, 110, 0, 0, 1121, 1122, 5, 112, 0, 0, 1122, 1123, 5, 114, 0, 0, 1123, 1124, 5, 105, 0, 0, 1124, 1125, 5, 118, 0, 0, 1125, 1126, 5, 97, 0, 0, 1126, 1127, 5, 116, 0, 0, 1127, 1128, 5, 101, 0, 0, 1128, 1129, 1, 0, 0, 0, 1129, 1130, 4, 44, 12, 0, 1130, 95, 1, 0, 0, 0, 1131, 1132, 5, 114, 0, 0, 1132, 1133, 5, 97, 0, 0, 1133, 1134, 5, 121, 0, 0, 1134, 1135, 5, 80, 0, 0, 1135, 1136, 5, 97, 0, 0, 1136, 1137, 5, 121, 0, 0, 1137, 1138, 5, 108, 0, 0, 1138, 1139, 5, 111, 0, 0, 1139, 1140, 5, 97, 0, 0, 1140, 1141, 5, 100, 0, 0, 1141, 1142, 5, 69, 0, 0, 1142, 1143, 5, 88, 0, 0, 1143, 1144, 5, 84, 0, 0, 1144, 97, 1, 0, 0, 0, 1145, 1146, 5, 114, 0, 0, 1146, 1147, 5, 97, 0, 0, 1147, 1148, 5, 121, 0, 0, 1148, 1149, 5, 80, 0, 0, 1149, 1150, 5, 97, 0, 0, 1150, 1151, 5, 121, 0, 0, 1151, 1152, 5, 108, 0, 0, 1152, 1153, 5, 111, 0, 0, 1153, 1154, 5, 97, 0, 0, 1154, 1155, 5, 100, 0, 0, 1155, 1156, 5, 73, 0, 0, 1156, 1157, 5, 110, 0, 0, 1157, 1158, 5, 69, 0, 0, 1158, 1159, 5, 88, 0, 0, 1159, 1160, 5, 84, 0, 0, 1160, 99, 1, 0, 0, 0, 1161, 1162, 5, 104, 0, 0, 1162, 1163, 5, 105, 0, 0, 1163, 1164, 5, 116, 0, 0, 1164, 1165, 5, 65, 0, 0, 1165, 1166, 5, 116, 0, 0, 1166, 1167, 5, 116, 0, 0, 1167, 1168, 5, 114, 0, 0, 1168, 1169, 5, 105, 0, 0, 1169, 1170, 5, 98, 0, 0, 1170, 1171, 5, 117, 0, 0, 1171, 1172, 5, 116, 0, 0, 1172, 1173, 5, 101, 0, 0, 1173, 1174, 5, 69, 0, 0, 1174, 1175, 5, 88, 0, 0, 1175, 1176, 5, 84, 0, 0, 1176, 101, 1, 0, 0, 0, 1177, 1178, 5, 99, 0, 0, 1178, 1179, 5, 97, 0, 0, 1179, 1180, 5, 108, 0, 0, 1180, 1181, 5, 108, 0, 0, 1181, 1182, 5, 97, 0, 0, 1182, 1183, 5, 98, 0, 0, 1183, 1184, 5, 108, 0, 0, 1184, 1185, 5, 101, 0, 0, 1185, 1186, 5, 68, 0, 0, 1186, 1187, 5, 97, 0, 0, 1187, 1188, 5, 116, 0, 0, 1188, 1189, 5, 97, 0, 0, 1189, 1190, 5, 69, 0, 0, 1190, 1191, 5, 88, 0, 0, 1191, 1192, 5, 84, 0, 0, 1192, 103, 1, 0, 0, 0, 1193, 1194, 5, 99, 0, 0, 1194, 1195, 5, 97, 0, 0, 1195, 1196, 5, 108, 0, 0, 1196, 1197, 5, 108, 0, 0, 1197, 1198, 5, 97, 0, 0, 1198, 1199, 5, 98, 0, 0, 1199, 1200, 5, 108, 0, 0, 1200, 1201, 5, 101, 0, 0, 1201, 1202, 5, 68, 0, 0, 1202, 1203, 5, 97, 0, 0, 1203, 1204, 5, 116, 0, 0, 1204, 1205, 5, 97, 0, 0, 1205, 1206, 5, 73, 0, 0, 1206, 1207, 5, 110, 0, 0, 1207, 1208, 5, 69, 0, 0, 1208, 1209, 5, 88, 0, 0, 1209, 1210, 5, 84, 0, 0, 1210, 105, 1, 0, 0, 0, 1211, 1212, 5, 105, 0, 0, 1212, 1213, 5, 103, 0, 0, 1213, 1214, 5, 110, 0, 0, 1214, 1215, 5, 111, 0, 0, 1215, 1216, 5, 114, 0, 0, 1216, 1217, 5, 101, 0, 0, 1217, 1218, 5, 73, 0, 0, 1218, 1219, 5, 110, 0, 0, 1219, 1220, 5, 116, 0, 0, 1220, 1221, 5, 101, 0, 0, 1221, 1222, 5, 114, 0, 0, 1222, 1223, 5, 115, 0, 0, 1223, 1224, 5, 101, 0, 0, 1224, 1225, 5, 99, 0, 0, 1225, 1226, 5, 116, 0, 0, 1226, 1227, 5, 105, 0, 0, 1227, 1228, 5, 111, 0, 0, 1228, 1229, 5, 110, 0, 0, 1229, 1230, 5, 69, 0, 0, 1230, 1231, 5, 88, 0, 0, 1231, 1232, 5, 84, 0, 0, 1232, 107, 1, 0, 0, 0, 1233, 1234, 5, 116, 0, 0, 1234, 1235, 5, 101, 0, 0, 1235, 1236, 5, 114, 0, 0, 1236, 1237, 5, 109, 0, 0, 1237, 1238, 5, 105, 0, 0, 1238, 1239, 5, 110, 0, 0, 1239, 1240, 5, 97, 0, 0, 1240, 1241, 5, 116, 0, 0, 1241, 1242, 5, 101, 0, 0, 1242, 1243, 5, 82, 0, 0, 1243, 1244, 5, 97, 0, 0, 1244, 1245, 5, 121, 0, 0, 1245, 1246, 5, 69, 0, 0, 1246, 1247, 5, 88, 0, 0, 1247, 1248, 5, 84, 0, 0, 1248, 109, 1, 0, 0, 0, 1249, 1250, 5, 97, 0, 0, 1250, 1251, 5, 99, 0, 0, 1251, 1252, 5, 99, 0, 0, 1252, 1253, 5, 101, 0, 0, 1253, 1254, 5, 108, 0, 0, 1254, 1255, 5, 101, 0, 0, 1255, 1256, 5, 114, 0, 0, 1256, 1257, 5, 97, 0, 0, 1257, 1258, 5, 116, 0, 0, 1258, 1259, 5, 105, 0, 0, 1259, 1260, 5, 111, 0, 0, 1260, 1261, 5, 110, 0, 0, 1261, 1262, 5, 83, 0, 0, 1262, 1263, 5, 116, 0, 0, 1263, 1264, 5, 114, 0, 0, 1264, 1265, 5, 117, 0, 0, 1265, 1266, 5, 99, 0, 0, 1266, 1267, 5, 116, 0, 0, 1267, 1268, 5, 117, 0, 0, 1268, 1269, 5, 114, 0, 0, 1269, 1270, 5, 101, 0, 0, 1270, 1271, 5, 69, 0, 0, 1271, 1272, 5, 88, 0, 0, 1272, 1273, 5, 84, 0, 0, 1273, 111, 1, 0, 0, 0, 1274, 1275, 5, 97, 0, 0, 1275, 1276, 5, 116, 0, 0, 1276, 1277, 5, 111, 0, 0, 1277, 1278, 5, 109, 0, 0, 1278, 1279, 5, 105, 0, 0, 1279, 1280, 5, 99, 0, 0, 1280, 1281, 5, 95, 0, 0, 1281, 1282, 5, 117, 0, 0, 1282, 1283, 5, 105, 0, 0, 1283, 1284, 5, 110, 0, 0, 1284, 1285, 5, 116, 0, 0, 1285, 1286, 1, 0, 0, 0, 1286, 1287, 4, 53, 13, 0, 1287, 113, 1, 0, 0, 0, 1288, 1289, 5, 115, 0, 0, 1289, 1290, 5, 116, 0, 0, 1290, 1291, 5, 114, 0, 0, 1291, 1292, 5, 117, 0, 0, 1292, 1293, 5, 99, 0, 0, 1293, 1294, 5, 116, 0, 0, 1294, 115, 1, 0, 0, 0, 1295, 1296, 5, 105, 0, 0, 1296, 1297, 5, 102, 0, 0, 1297, 117, 1, 0, 0, 0, 1298, 1299, 5, 101, 0, 0, 1299, 1300, 5, 108, 0, 0, 1300, 1301, 5, 115, 0, 0, 1301, 1302, 5, 101, 0, 0, 1302, 119, 1, 0, 0, 0, 1303, 1304, 5, 115, 0, 0, 1304, 1305, 5, 119, 0, 0, 1305, 1306, 5, 105, 0, 0, 1306, 1307, 5, 116, 0, 0, 1307, 1308, 5, 99, 0, 0, 1308, 1309, 5, 104, 0, 0, 1309, 121, 1, 0, 0, 0, 1310, 1311, 5, 99, 0, 0, 1311, 1312, 5, 97, 0, 0, 1312, 1313, 5, 115, 0, 0, 1313, 1314, 5, 101, 0, 0, 1314, 123, 1, 0, 0, 0, 1315, 1316, 5, 100, 0, 0, 1316, 1317, 5, 101, 0, 0, 1317, 1318, 5, 102, 0, 0, 1318, 1319, 5, 97, 0, 0, 1319, 1320, 5, 117, 0, 0, 1320, 1321, 5, 108, 0, 0, 1321, 1322, 5, 116, 0, 0, 1322, 125, 1, 0, 0, 0, 1323, 1324, 5, 119, 0, 0, 1324, 1325, 5, 104, 0, 0, 1325, 1326, 5, 105, 0, 0, 1326, 1327, 5, 108, 0, 0, 1327, 1328, 5, 101, 0, 0, 1328, 127, 1, 0, 0, 0, 1329, 1330, 5, 100, 0, 0, 1330, 1331, 5, 111, 0, 0, 1331, 129, 1, 0, 0, 0, 1332, 1333, 5, 102, 0, 0, 1333, 1334, 5, 111, 0, 0, 1334, 1335, 5, 114, 0, 0, 1335, 131, 1, 0, 0, 0, 1336, 1337, 5, 99, 0, 0, 1337, 1338, 5, 111, 0, 0, 1338, 1339, 5, 110, 0, 0, 1339, 1340, 5, 116, 0, 0, 1340, 1341, 5, 105, 0, 0, 1341, 1342, 5, 110, 0, 0, 1342, 1343, 5, 117, 0, 0, 1343, 1344, 5, 101, 0, 0, 1344, 133, 1, 0, 0, 0, 1345, 1346, 5, 98, 0, 0, 1346, 1347, 5, 114, 0, 0, 1347, 1348, 5, 101, 0, 0, 1348, 1349, 5, 97, 0, 0, 1349, 1350, 5, 107, 0, 0, 1350, 135, 1, 0, 0, 0, 1351, 1352, 5, 114, 0, 0, 1352, 1353, 5, 101, 0, 0, 1353, 1354, 5, 116, 0, 0, 1354, 1355, 5, 117, 0, 0, 1355, 1356, 5, 114, 0, 0, 1356, 1357, 5, 110, 0, 0, 1357, 137, 1, 0, 0, 0, 1358, 1359, 5, 100, 0, 0, 1359, 1360, 5, 105, 0, 0, 1360, 1361, 5, 115, 0, 0, 1361, 1362, 5, 99, 0, 0, 1362, 1363, 5, 97, 0, 0, 1363, 1364, 5, 114, 0, 0, 1364, 1365, 5, 100, 0, 0, 1365, 139, 1, 0, 0, 0, 1366, 1367, 5, 100, 0, 0, 1367, 1368, 5, 101, 0, 0, 1368, 1369, 5, 109, 0, 0, 1369, 1370, 5, 111, 0, 0, 1370, 1371, 5, 116, 0, 0, 1371, 1372, 5, 101, 0, 0, 1372, 141, 1, 0, 0, 0, 1373, 1377, 3, 6, 0, 0, 1374, 1377, 3, 8, 1, 0, 1375, 1377, 3, 10, 2, 0, 1376, 1373, 1, 0, 0, 0, 1376, 1374, 1, 0, 0, 0, 1376, 1375, 1, 0, 0, 0, 1377, 143, 1, 0, 0, 0, 1378, 1379, 7, 6, 0, 0, 1379, 145, 1, 0, 0, 0, 1380, 1381, 7, 7, 0, 0, 1381, 147, 1, 0, 0, 0, 1382, 1383, 7, 8, 0, 0, 1383, 149, 1, 0, 0, 0, 1384, 1385, 7, 9, 0, 0, 1385, 151, 1, 0, 0, 0, 1386, 1387, 7, 10, 0, 0, 1387, 153, 1, 0, 0, 0, 1388, 1389, 3, 142, 68, 0, 1389, 1390, 3, 150, 72, 0, 1390, 1391, 3, 152, 73, 0, 1391, 155, 1, 0, 0, 0, 1392, 1393, 3, 142, 68, 0, 1393, 1394, 3, 152, 73, 0, 1394, 157, 1, 0, 0, 0, 1395, 1396, 3, 142, 68, 0, 1396, 1397, 3, 150, 72, 0, 1397, 159, 1, 0, 0, 0, 1398, 1399, 3, 142, 68, 0, 1399, 161, 1, 0, 0, 0, 1400, 1401, 3, 142, 68, 0, 1401, 1402, 3, 150, 72, 0, 1402, 1403, 3, 148, 71, 0, 1403, 163, 1, 0, 0, 0, 1404, 1405, 3, 142, 68, 0, 1405, 1406, 3, 148, 71, 0, 1406, 165, 1, 0, 0, 0, 1407, 1408, 3, 14, 4, 0, 1408, 1409, 3, 146, 70, 0, 1409, 1410, 3, 144, 69, 0, 1410, 167, 1, 0, 0, 0, 1411, 1413, 3, 14, 4, 0, 1412, 1414, 3, 144, 69, 0, 1413, 1412, 1, 0, 0, 0, 1413, 1414, 1, 0, 0, 0, 1414, 169, 1, 0, 0, 0, 1415, 1416, 3, 14, 4, 0, 1416, 1417, 3, 148, 71, 0, 1417, 1418, 3, 144, 69, 0, 1418, 171, 1, 0, 0, 0, 1419, 1420, 5, 116, 0, 0, 1420, 1421, 5, 114, 0, 0, 1421, 1422, 5, 117, 0, 0, 1422, 1429, 5, 101, 0, 0, 1423, 1424, 5, 102, 0, 0, 1424, 1425, 5, 97, 0, 0, 1425, 1426, 5, 108, 0, 0, 1426, 1427, 5, 115, 0, 0, 1427, 1429, 5, 101, 0, 0, 1428, 1419, 1, 0, 0, 0, 1428, 1423, 1, 0, 0, 0, 1429, 173, 1, 0, 0, 0, 1430, 1431, 5, 98, 0, 0, 1431, 1432, 5, 111, 0, 0, 1432, 1433, 5, 111, 0, 0, 1433, 1434, 5, 108, 0, 0, 1434, 175, 1, 0, 0, 0, 1435, 1436, 5, 98, 0, 0, 1436, 1437, 5, 118, 0, 0, 1437, 1438, 5, 101, 0, 0, 1438, 1439, 5, 99, 0, 0, 1439, 1440, 5, 50, 0, 0, 1440, 177, 1, 0, 0, 0, 1441, 1442, 5, 98, 0, 0, 1442, 1443, 5, 118, 0, 0, 1443, 1444, 5, 101, 0, 0, 1444, 1445, 5, 99, 0, 0, 1445, 1446, 5, 51, 0, 0, 1446, 179, 1, 0, 0, 0, 1447, 1448, 5, 98, 0, 0, 1448, 1449, 5, 118, 0, 0, 1449, 1450, 5, 101, 0, 0, 1450, 1451, 5, 99, 0, 0, 1451, 1452, 5, 52, 0, 0, 1452, 181, 1, 0, 0, 0, 1453, 1454, 5, 105, 0, 0, 1454, 1455, 5, 110, 0, 0, 1455, 1456, 5, 116, 0, 0, 1456, 1457, 5, 56, 0, 0, 1457, 1458, 5, 95, 0, 0, 1458, 1459, 5, 116, 0, 0, 1459, 183, 1, 0, 0, 0, 1460, 1461, 5, 105, 0, 0, 1461, 1462, 5, 56, 0, 0, 1462, 1463, 5, 118, 0, 0, 1463, 1464, 5, 101, 0, 0, 1464, 1465, 5, 99, 0, 0, 1465, 1466, 5, 50, 0, 0, 1466, 185, 1, 0, 0, 0, 1467, 1468, 5, 105, 0, 0, 1468, 1469, 5, 56, 0, 0, 1469, 1470, 5, 118, 0, 0, 1470, 1471, 5, 101, 0, 0, 1471, 1472, 5, 99, 0, 0, 1472, 1473, 5, 51, 0, 0, 1473, 187, 1, 0, 0, 0, 1474, 1475, 5, 105, 0, 0, 1475, 1476, 5, 56, 0, 0, 1476, 1477, 5, 118, 0, 0, 1477, 1478, 5, 101, 0, 0, 1478, 1479, 5, 99, 0, 0, 1479, 1480, 5, 52, 0, 0, 1480, 189, 1, 0, 0, 0, 1481, 1482, 5, 117, 0, 0, 1482, 1483, 5, 105, 0, 0, 1483, 1484, 5, 110, 0, 0, 1484, 1485, 5, 116, 0, 0, 1485, 1486, 5, 56, 0, 0, 1486, 1487, 5, 95, 0, 0, 1487, 1488, 5, 116, 0, 0, 1488, 191, 1, 0, 0, 0, 1489, 1490, 5, 117, 0, 0, 1490, 1491, 5, 56, 0, 0, 1491, 1492, 5, 118, 0, 0, 1492, 1493, 5, 101, 0, 0, 1493, 1494, 5, 99, 0, 0, 1494, 1495, 5, 50, 0, 0, 1495, 193, 1, 0, 0, 0, 1496, 1497, 5, 117, 0, 0, 1497, 1498, 5, 56, 0, 0, 1498, 1499, 5, 118, 0, 0, 1499, 1500, 5, 101, 0, 0, 1500, 1501, 5, 99, 0, 0, 1501, 1502, 5, 51, 0, 0, 1502, 195, 1, 0, 0, 0, 1503, 1504, 5, 117, 0, 0, 1504, 1505, 5, 56, 0, 0, 1505, 1506, 5, 118, 0, 0, 1506, 1507, 5, 101, 0, 0, 1507, 1508, 5, 99, 0, 0, 1508, 1509, 5, 52, 0, 0, 1509, 197, 1, 0, 0, 0, 1510, 1511, 5, 105, 0, 0, 1511, 1512, 5, 110, 0, 0, 1512, 1513, 5, 116, 0, 0, 1513, 1514, 5, 49, 0, 0, 1514, 1515, 5, 54, 0, 0, 1515, 1516, 5, 95, 0, 0, 1516, 1517, 5, 116, 0, 0, 1517, 199, 1, 0, 0, 0, 1518, 1519, 5, 105, 0, 0, 1519, 1520, 5, 49, 0, 0, 1520, 1521, 5, 54, 0, 0, 1521, 1522, 5, 118, 0, 0, 1522, 1523, 5, 101, 0, 0, 1523, 1524, 5, 99, 0, 0, 1524, 1525, 5, 50, 0, 0, 1525, 201, 1, 0, 0, 0, 1526, 1527, 5, 105, 0, 0, 1527, 1528, 5, 49, 0, 0, 1528, 1529, 5, 54, 0, 0, 1529, 1530, 5, 118, 0, 0, 1530, 1531, 5, 101, 0, 0, 1531, 1532, 5, 99, 0, 0, 1532, 1533, 5, 51, 0, 0, 1533, 203, 1, 0, 0, 0, 1534, 1535, 5, 105, 0, 0, 1535, 1536, 5, 49, 0, 0, 1536, 1537, 5, 54, 0, 0, 1537, 1538, 5, 118, 0, 0, 1538, 1539, 5, 101, 0, 0, 1539, 1540, 5, 99, 0, 0, 1540, 1541, 5, 52, 0, 0, 1541, 205, 1, 0, 0, 0, 1542, 1543, 5, 117, 0, 0, 1543, 1544, 5, 105, 0, 0, 1544, 1545, 5, 110, 0, 0, 1545, 1546, 5, 116, 0, 0, 1546, 1547, 5, 49, 0, 0, 1547, 1548, 5, 54, 0, 0, 1548, 1549, 5, 95, 0, 0, 1549, 1550, 5, 116, 0, 0, 1550, 207, 1, 0, 0, 0, 1551, 1552, 5, 117, 0, 0, 1552, 1553, 5, 49, 0, 0, 1553, 1554, 5, 54, 0, 0, 1554, 1555, 5, 118, 0, 0, 1555, 1556, 5, 101, 0, 0, 1556, 1557, 5, 99, 0, 0, 1557, 1558, 5, 50, 0, 0, 1558, 209, 1, 0, 0, 0, 1559, 1560, 5, 117, 0, 0, 1560, 1561, 5, 49, 0, 0, 1561, 1562, 5, 54, 0, 0, 1562, 1563, 5, 118, 0, 0, 1563, 1564, 5, 101, 0, 0, 1564, 1565, 5, 99, 0, 0, 1565, 1566, 5, 51, 0, 0, 1566, 211, 1, 0, 0, 0, 1567, 1568, 5, 117, 0, 0, 1568, 1569, 5, 49, 0, 0, 1569, 1570, 5, 54, 0, 0, 1570, 1571, 5, 118, 0, 0, 1571, 1572, 5, 101, 0, 0, 1572, 1573, 5, 99, 0, 0, 1573, 1574, 5, 52, 0, 0, 1574, 213, 1, 0, 0, 0, 1575, 1576, 5, 105, 0, 0, 1576, 1577, 5, 110, 0, 0, 1577, 1578, 5, 116, 0, 0, 1578, 1579, 5, 51, 0, 0, 1579, 1580, 5, 50, 0, 0, 1580, 1581, 5, 95, 0, 0, 1581, 1586, 5, 116, 0, 0, 1582, 1583, 5, 105, 0, 0, 1583, 1584, 5, 110, 0, 0, 1584, 1586, 5, 116, 0, 0, 1585, 1575, 1, 0, 0, 0, 1585, 1582, 1, 0, 0, 0, 1586, 215, 1, 0, 0, 0, 1587, 1588, 5, 105, 0, 0, 1588, 1589, 5, 51, 0, 0, 1589, 1590, 5, 50, 0, 0, 1590, 1591, 5, 118, 0, 0, 1591, 1592, 5, 101, 0, 0, 1592, 1593, 5, 99, 0, 0, 1593, 1600, 5, 50, 0, 0, 1594, 1595, 5, 105, 0, 0, 1595, 1596, 5, 118, 0, 0, 1596, 1597, 5, 101, 0, 0, 1597, 1598, 5, 99, 0, 0, 1598, 1600, 5, 50, 0, 0, 1599, 1587, 1, 0, 0, 0, 1599, 1594, 1, 0, 0, 0, 1600, 217, 1, 0, 0, 0, 1601, 1602, 5, 105, 0, 0, 1602, 1603, 5, 51, 0, 0, 1603, 1604, 5, 50, 0, 0, 1604, 1605, 5, 118, 0, 0, 1605, 1606, 5, 101, 0, 0, 1606, 1607, 5, 99, 0, 0, 1607, 1614, 5, 51, 0, 0, 1608, 1609, 5, 105, 0, 0, 1609, 1610, 5, 118, 0, 0, 1610, 1611, 5, 101, 0, 0, 1611, 1612, 5, 99, 0, 0, 1612, 1614, 5, 51, 0, 0, 1613, 1601, 1, 0, 0, 0, 1613, 1608, 1, 0, 0, 0, 1614, 219, 1, 0, 0, 0, 1615, 1616, 5, 105, 0, 0, 1616, 1617, 5, 51, 0, 0, 1617, 1618, 5, 50, 0, 0, 1618, 1619, 5, 118, 0, 0, 1619, 1620, 5, 101, 0, 0, 1620, 1621, 5, 99, 0, 0, 1621, 1628, 5, 52, 0, 0, 1622, 1623, 5, 105, 0, 0, 1623, 1624, 5, 118, 0, 0, 1624, 1625, 5, 101, 0, 0, 1625, 1626, 5, 99, 0, 0, 1626, 1628, 5, 52, 0, 0, 1627, 1615, 1, 0, 0, 0, 1627, 1622, 1, 0, 0, 0, 1628, 221, 1, 0, 0, 0, 1629, 1630, 5, 117, 0, 0, 1630, 1631, 5, 105, 0, 0, 1631, 1632, 5, 110, 0, 0, 1632, 1633, 5, 116, 0, 0, 1633, 1634, 5, 51, 0, 0, 1634, 1635, 5, 50, 0, 0, 1635, 1636, 5, 95, 0, 0, 1636, 1642, 5, 116, 0, 0, 1637, 1638, 5, 117, 0, 0, 1638, 1639, 5, 105, 0, 0, 1639, 1640, 5, 110, 0, 0, 1640, 1642, 5, 116, 0, 0, 1641, 1629, 1, 0, 0, 0, 1641, 1637, 1, 0, 0, 0, 1642, 223, 1, 0, 0, 0, 1643, 1644, 5, 117, 0, 0, 1644, 1645, 5, 51, 0, 0, 1645, 1646, 5, 50, 0, 0, 1646, 1647, 5, 118, 0, 0, 1647, 1648, 5, 101, 0, 0, 1648, 1649, 5, 99, 0, 0, 1649, 1656, 5, 50, 0, 0, 1650, 1651, 5, 117, 0, 0, 1651, 1652, 5, 118, 0, 0, 1652, 1653, 5, 101, 0, 0, 1653, 1654, 5, 99, 0, 0, 1654, 1656, 5, 50, 0, 0, 1655, 1643, 1, 0, 0, 0, 1655, 1650, 1, 0, 0, 0, 1656, 225, 1, 0, 0, 0, 1657, 1658, 5, 117, 0, 0, 1658, 1659, 5, 51, 0, 0, 1659, 1660, 5, 50, 0, 0, 1660, 1661, 5, 118, 0, 0, 1661, 1662, 5, 101, 0, 0, 1662, 1663, 5, 99, 0, 0, 1663, 1670, 5, 51, 0, 0, 1664, 1665, 5, 117, 0, 0, 1665, 1666, 5, 118, 0, 0, 1666, 1667, 5, 101, 0, 0, 1667, 1668, 5, 99, 0, 0, 1668, 1670, 5, 51, 0, 0, 1669, 1657, 1, 0, 0, 0, 1669, 1664, 1, 0, 0, 0, 1670, 227, 1, 0, 0, 0, 1671, 1672, 5, 117, 0, 0, 1672, 1673, 5, 51, 0, 0, 1673, 1674, 5, 50, 0, 0, 1674, 1675, 5, 118, 0, 0, 1675, 1676, 5, 101, 0, 0, 1676, 1677, 5, 99, 0, 0, 1677, 1684, 5, 52, 0, 0, 1678, 1679, 5, 117, 0, 0, 1679, 1680, 5, 118, 0, 0, 1680, 1681, 5, 101, 0, 0, 1681, 1682, 5, 99, 0, 0, 1682, 1684, 5, 52, 0, 0, 1683, 1671, 1, 0, 0, 0, 1683, 1678, 1, 0, 0, 0, 1684, 229, 1, 0, 0, 0, 1685, 1686, 5, 105, 0, 0, 1686, 1687, 5, 110, 0, 0, 1687, 1688, 5, 116, 0, 0, 1688, 1689, 5, 54, 0, 0, 1689, 1690, 5, 52, 0, 0, 1690, 1691, 5, 95, 0, 0, 1691, 1692, 5, 116, 0, 0, 1692, 231, 1, 0, 0, 0, 1693, 1694, 5, 105, 0, 0, 1694, 1695, 5, 54, 0, 0, 1695, 1696, 5, 52, 0, 0, 1696, 1697, 5, 118, 0, 0, 1697, 1698, 5, 101, 0, 0, 1698, 1699, 5, 99, 0, 0, 1699, 1700, 5, 50, 0, 0, 1700, 233, 1, 0, 0, 0, 1701, 1702, 5, 105, 0, 0, 1702, 1703, 5, 54, 0, 0, 1703, 1704, 5, 52, 0, 0, 1704, 1705, 5, 118, 0, 0, 1705, 1706, 5, 101, 0, 0, 1706, 1707, 5, 99, 0, 0, 1707, 1708, 5, 51, 0, 0, 1708, 235, 1, 0, 0, 0, 1709, 1710, 5, 105, 0, 0, 1710, 1711, 5, 54, 0, 0, 1711, 1712, 5, 52, 0, 0, 1712, 1713, 5, 118, 0, 0, 1713, 1714, 5, 101, 0, 0, 1714, 1715, 5, 99, 0, 0, 1715, 1716, 5, 52, 0, 0, 1716, 237, 1, 0, 0, 0, 1717, 1718, 5, 117, 0, 0, 1718, 1719, 5, 105, 0, 0, 1719, 1720, 5, 110, 0, 0, 1720, 1721, 5, 116, 0, 0, 1721, 1722, 5, 54, 0, 0, 1722, 1723, 5, 52, 0, 0, 1723, 1724, 5, 95, 0, 0, 1724, 1725, 5, 116, 0, 0, 1725, 239, 1, 0, 0, 0, 1726, 1727, 5, 117, 0, 0, 1727, 1728, 5, 54, 0, 0, 1728, 1729, 5, 52, 0, 0, 1729, 1730, 5, 118, 0, 0, 1730, 1731, 5, 101, 0, 0, 1731, 1732, 5, 99, 0, 0, 1732, 1733, 5, 50, 0, 0, 1733, 241, 1, 0, 0, 0, 1734, 1735, 5, 117, 0, 0, 1735, 1736, 5, 54, 0, 0, 1736, 1737, 5, 52, 0, 0, 1737, 1738, 5, 118, 0, 0, 1738, 1739, 5, 101, 0, 0, 1739, 1740, 5, 99, 0, 0, 1740, 1741, 5, 51, 0, 0, 1741, 243, 1, 0, 0, 0, 1742, 1743, 5, 117, 0, 0, 1743, 1744, 5, 54, 0, 0, 1744, 1745, 5, 52, 0, 0, 1745, 1746, 5, 118, 0, 0, 1746, 1747, 5, 101, 0, 0, 1747, 1748, 5, 99, 0, 0, 1748, 1749, 5, 52, 0, 0, 1749, 245, 1, 0, 0, 0, 1750, 1751, 5, 102, 0, 0, 1751, 1752, 5, 108, 0, 0, 1752, 1753, 5, 111, 0, 0, 1753, 1754, 5, 97, 0, 0, 1754, 1755, 5, 116, 0, 0, 1755, 1756, 5, 49, 0, 0, 1756, 1757, 5, 54, 0, 0, 1757, 1758, 5, 95, 0, 0, 1758, 1759, 5, 116, 0, 0, 1759, 247, 1, 0, 0, 0, 1760, 1761, 5, 102, 0, 0, 1761, 1762, 5, 49, 0, 0, 1762, 1763, 5, 54, 0, 0, 1763, 1764, 5, 118, 0, 0, 1764, 1765, 5, 101, 0, 0, 1765, 1766, 5, 99, 0, 0, 1766, 1767, 5, 50, 0, 0, 1767, 249, 1, 0, 0, 0, 1768, 1769, 5, 102, 0, 0, 1769, 1770, 5, 49, 0, 0, 1770, 1771, 5, 54, 0, 0, 1771, 1772, 5, 118, 0, 0, 1772, 1773, 5, 101, 0, 0, 1773, 1774, 5, 99, 0, 0, 1774, 1775, 5, 51, 0, 0, 1775, 251, 1, 0, 0, 0, 1776, 1777, 5, 102, 0, 0, 1777, 1778, 5, 49, 0, 0, 1778, 1779, 5, 54, 0, 0, 1779, 1780, 5, 118, 0, 0, 1780, 1781, 5, 101, 0, 0, 1781, 1782, 5, 99, 0, 0, 1782, 1783, 5, 52, 0, 0, 1783, 253, 1, 0, 0, 0, 1784, 1785, 5, 102, 0, 0, 1785, 1786, 5, 49, 0, 0, 1786, 1787, 5, 54, 0, 0, 1787, 1788, 5, 109, 0, 0, 1788, 1789, 5, 97, 0, 0, 1789, 1790, 5, 116, 0, 0, 1790, 1791, 5, 50, 0, 0, 1791, 1792, 5, 120, 0, 0, 1792, 1801, 5, 50, 0, 0, 1793, 1794, 5, 102, 0, 0, 1794, 1795, 5, 49, 0, 0, 1795, 1796, 5, 54, 0, 0, 1796, 1797, 5, 109, 0, 0, 1797, 1798, 5, 97, 0, 0, 1798, 1799, 5, 116, 0, 0, 1799, 1801, 5, 50, 0, 0, 1800, 1784, 1, 0, 0, 0, 1800, 1793, 1, 0, 0, 0, 1801, 255, 1, 0, 0, 0, 1802, 1803, 5, 102, 0, 0, 1803, 1804, 5, 49, 0, 0, 1804, 1805, 5, 54, 0, 0, 1805, 1806, 5, 109, 0, 0, 1806, 1807, 5, 97, 0, 0, 1807, 1808, 5, 116, 0, 0, 1808, 1809, 5, 50, 0, 0, 1809, 1810, 5, 120, 0, 0, 1810, 1811, 5, 51, 0, 0, 1811, 257, 1, 0, 0, 0, 1812, 1813, 5, 102, 0, 0, 1813, 1814, 5, 49, 0, 0, 1814, 1815, 5, 54, 0, 0, 1815, 1816, 5, 109, 0, 0, 1816, 1817, 5, 97, 0, 0, 1817, 1818, 5, 116, 0, 0, 1818, 1819, 5, 50, 0, 0, 1819, 1820, 5, 120, 0, 0, 1820, 1821, 5, 52, 0, 0, 1821, 259, 1, 0, 0, 0, 1822, 1823, 5, 102, 0, 0, 1823, 1824, 5, 49, 0, 0, 1824, 1825, 5, 54, 0, 0, 1825, 1826, 5, 109, 0, 0, 1826, 1827, 5, 97, 0, 0, 1827, 1828, 5, 116, 0, 0, 1828, 1829, 5, 51, 0, 0, 1829, 1830, 5, 120, 0, 0, 1830, 1831, 5, 50, 0, 0, 1831, 261, 1, 0, 0, 0, 1832, 1833, 5, 102, 0, 0, 1833, 1834, 5, 49, 0, 0, 1834, 1835, 5, 54, 0, 0, 1835, 1836, 5, 109, 0, 0, 1836, 1837, 5, 97, 0, 0, 1837, 1838, 5, 116, 0, 0, 1838, 1839, 5, 51, 0, 0, 1839, 1840, 5, 120, 0, 0, 1840, 1849, 5, 51, 0, 0, 1841, 1842, 5, 102, 0, 0, 1842, 1843, 5, 49, 0, 0, 1843, 1844, 5, 54, 0, 0, 1844, 1845, 5, 109, 0, 0, 1845, 1846, 5, 97, 0, 0, 1846, 1847, 5, 116, 0, 0, 1847, 1849, 5, 51, 0, 0, 1848, 1832, 1, 0, 0, 0, 1848, 1841, 1, 0, 0, 0, 1849, 263, 1, 0, 0, 0, 1850, 1851, 5, 102, 0, 0, 1851, 1852, 5, 49, 0, 0, 1852, 1853, 5, 54, 0, 0, 1853, 1854, 5, 109, 0, 0, 1854, 1855, 5, 97, 0, 0, 1855, 1856, 5, 116, 0, 0, 1856, 1857, 5, 51, 0, 0, 1857, 1858, 5, 120, 0, 0, 1858, 1859, 5, 52, 0, 0, 1859, 265, 1, 0, 0, 0, 1860, 1861, 5, 102, 0, 0, 1861, 1862, 5, 49, 0, 0, 1862, 1863, 5, 54, 0, 0, 1863, 1864, 5, 109, 0, 0, 1864, 1865, 5, 97, 0, 0, 1865, 1866, 5, 116, 0, 0, 1866, 1867, 5, 52, 0, 0, 1867, 1868, 5, 120, 0, 0, 1868, 1869, 5, 50, 0, 0, 1869, 267, 1, 0, 0, 0, 1870, 1871, 5, 102, 0, 0, 1871, 1872, 5, 49, 0, 0, 1872, 1873, 5, 54, 0, 0, 1873, 1874, 5, 109, 0, 0, 1874, 1875, 5, 97, 0, 0, 1875, 1876, 5, 116, 0, 0, 1876, 1877, 5, 52, 0, 0, 1877, 1878, 5, 120, 0, 0, 1878, 1879, 5, 51, 0, 0, 1879, 269, 1, 0, 0, 0, 1880, 1881, 5, 102, 0, 0, 1881, 1882, 5, 49, 0, 0, 1882, 1883, 5, 54, 0, 0, 1883, 1884, 5, 109, 0, 0, 1884, 1885, 5, 97, 0, 0, 1885, 1886, 5, 116, 0, 0, 1886, 1887, 5, 52, 0, 0, 1887, 1888, 5, 120, 0, 0, 1888, 1897, 5, 52, 0, 0, 1889, 1890, 5, 102, 0, 0, 1890, 1891, 5, 49, 0, 0, 1891, 1892, 5, 54, 0, 0, 1892, 1893, 5, 109, 0, 0, 1893, 1894, 5, 97, 0, 0, 1894, 1895, 5, 116, 0, 0, 1895, 1897, 5, 52, 0, 0, 1896, 1880, 1, 0, 0, 0, 1896, 1889, 1, 0, 0, 0, 1897, 271, 1, 0, 0, 0, 1898, 1899, 5, 102, 0, 0, 1899, 1900, 5, 108, 0, 0, 1900, 1901, 5, 111, 0, 0, 1901, 1902, 5, 97, 0, 0, 1902, 1903, 5, 116, 0, 0, 1903, 1904, 5, 51, 0, 0, 1904, 1905, 5, 50, 0, 0, 1905, 1906, 5, 95, 0, 0, 1906, 1913, 5, 116, 0, 0, 1907, 1908, 5, 102, 0, 0, 1908, 1909, 5, 108, 0, 0, 1909, 1910, 5, 111, 0, 0, 1910, 1911, 5, 97, 0, 0, 1911, 1913, 5, 116, 0, 0, 1912, 1898, 1, 0, 0, 0, 1912, 1907, 1, 0, 0, 0, 1913, 273, 1, 0, 0, 0, 1914, 1915, 5, 102, 0, 0, 1915, 1916, 5, 51, 0, 0, 1916, 1917, 5, 50, 0, 0, 1917, 1918, 5, 118, 0, 0, 1918, 1919, 5, 101, 0, 0, 1919, 1920, 5, 99, 0, 0, 1920, 1926, 5, 50, 0, 0, 1921, 1922, 5, 118, 0, 0, 1922, 1923, 5, 101, 0, 0, 1923, 1924, 5, 99, 0, 0, 1924, 1926, 5, 50, 0, 0, 1925, 1914, 1, 0, 0, 0, 1925, 1921, 1, 0, 0, 0, 1926, 275, 1, 0, 0, 0, 1927, 1928, 5, 102, 0, 0, 1928, 1929, 5, 51, 0, 0, 1929, 1930, 5, 50, 0, 0, 1930, 1931, 5, 118, 0, 0, 1931, 1932, 5, 101, 0, 0, 1932, 1933, 5, 99, 0, 0, 1933, 1939, 5, 51, 0, 0, 1934, 1935, 5, 118, 0, 0, 1935, 1936, 5, 101, 0, 0, 1936, 1937, 5, 99, 0, 0, 1937, 1939, 5, 51, 0, 0, 1938, 1927, 1, 0, 0, 0, 1938, 1934, 1, 0, 0, 0, 1939, 277, 1, 0, 0, 0, 1940, 1941, 5, 102, 0, 0, 1941, 1942, 5, 51, 0, 0, 1942, 1943, 5, 50, 0, 0, 1943, 1944, 5, 118, 0, 0, 1944, 1945, 5, 101, 0, 0, 1945, 1946, 5, 99, 0, 0, 1946, 1952, 5, 52, 0, 0, 1947, 1948, 5, 118, 0, 0, 1948, 1949, 5, 101, 0, 0, 1949, 1950, 5, 99, 0, 0, 1950, 1952, 5, 52, 0, 0, 1951, 1940, 1, 0, 0, 0, 1951, 1947, 1, 0, 0, 0, 1952, 279, 1, 0, 0, 0, 1953, 1954, 5, 102, 0, 0, 1954, 1955, 5, 51, 0, 0, 1955, 1956, 5, 50, 0, 0, 1956, 1957, 5, 109, 0, 0, 1957, 1958, 5, 97, 0, 0, 1958, 1959, 5, 116, 0, 0, 1959, 1960, 5, 50, 0, 0, 1960, 1961, 5, 120, 0, 0, 1961, 1980, 5, 50, 0, 0, 1962, 1963, 5, 102, 0, 0, 1963, 1964, 5, 51, 0, 0, 1964, 1965, 5, 50, 0, 0, 1965, 1966, 5, 109, 0, 0, 1966, 1967, 5, 97, 0, 0, 1967, 1968, 5, 116, 0, 0, 1968, 1980, 5, 50, 0, 0, 1969, 1970, 5, 109, 0, 0, 1970, 1971, 5, 97, 0, 0, 1971, 1972, 5, 116, 0, 0, 1972, 1980, 5, 50, 0, 0, 1973, 1974, 5, 109, 0, 0, 1974, 1975, 5, 97, 0, 0, 1975, 1976, 5, 116, 0, 0, 1976, 1977, 5, 50, 0, 0, 1977, 1978, 5, 120, 0, 0, 1978, 1980, 5, 50, 0, 0, 1979, 1953, 1, 0, 0, 0, 1979, 1962, 1, 0, 0, 0, 1979, 1969, 1, 0, 0, 0, 1979, 1973, 1, 0, 0, 0, 1980, 281, 1, 0, 0, 0, 1981, 1982, 5, 102, 0, 0, 1982, 1983, 5, 51, 0, 0, 1983, 1984, 5, 50, 0, 0, 1984, 1985, 5, 109, 0, 0, 1985, 1986, 5, 97, 0, 0, 1986, 1987, 5, 116, 0, 0, 1987, 1988, 5, 50, 0, 0, 1988, 1989, 5, 120, 0, 0, 1989, 1997, 5, 51, 0, 0, 1990, 1991, 5, 109, 0, 0, 1991, 1992, 5, 97, 0, 0, 1992, 1993, 5, 116, 0, 0, 1993, 1994, 5, 50, 0, 0, 1994, 1995, 5, 120, 0, 0, 1995, 1997, 5, 51, 0, 0, 1996, 1981, 1, 0, 0, 0, 1996, 1990, 1, 0, 0, 0, 1997, 283, 1, 0, 0, 0, 1998, 1999, 5, 102, 0, 0, 1999, 2000, 5, 51, 0, 0, 2000, 2001, 5, 50, 0, 0, 2001, 2002, 5, 109, 0, 0, 2002, 2003, 5, 97, 0, 0, 2003, 2004, 5, 116, 0, 0, 2004, 2005, 5, 50, 0, 0, 2005, 2006, 5, 120, 0, 0, 2006, 2014, 5, 52, 0, 0, 2007, 2008, 5, 109, 0, 0, 2008, 2009, 5, 97, 0, 0, 2009, 2010, 5, 116, 0, 0, 2010, 2011, 5, 50, 0, 0, 2011, 2012, 5, 120, 0, 0, 2012, 2014, 5, 52, 0, 0, 2013, 1998, 1, 0, 0, 0, 2013, 2007, 1, 0, 0, 0, 2014, 285, 1, 0, 0, 0, 2015, 2016, 5, 102, 0, 0, 2016, 2017, 5, 51, 0, 0, 2017, 2018, 5, 50, 0, 0, 2018, 2019, 5, 109, 0, 0, 2019, 2020, 5, 97, 0, 0, 2020, 2021, 5, 116, 0, 0, 2021, 2022, 5, 51, 0, 0, 2022, 2023, 5, 120, 0, 0, 2023, 2031, 5, 50, 0, 0, 2024, 2025, 5, 109, 0, 0, 2025, 2026, 5, 97, 0, 0, 2026, 2027, 5, 116, 0, 0, 2027, 2028, 5, 51, 0, 0, 2028, 2029, 5, 120, 0, 0, 2029, 2031, 5, 50, 0, 0, 2030, 2015, 1, 0, 0, 0, 2030, 2024, 1, 0, 0, 0, 2031, 287, 1, 0, 0, 0, 2032, 2033, 5, 102, 0, 0, 2033, 2034, 5, 51, 0, 0, 2034, 2035, 5, 50, 0, 0, 2035, 2036, 5, 109, 0, 0, 2036, 2037, 5, 97, 0, 0, 2037, 2038, 5, 116, 0, 0, 2038, 2039, 5, 51, 0, 0, 2039, 2040, 5, 120, 0, 0, 2040, 2059, 5, 51, 0, 0, 2041, 2042, 5, 102, 0, 0, 2042, 2043, 5, 51, 0, 0, 2043, 2044, 5, 50, 0, 0, 2044, 2045, 5, 109, 0, 0, 2045, 2046, 5, 97, 0, 0, 2046, 2047, 5, 116, 0, 0, 2047, 2059, 5, 51, 0, 0, 2048, 2049, 5, 109, 0, 0, 2049, 2050, 5, 97, 0, 0, 2050, 2051, 5, 116, 0, 0, 2051, 2059, 5, 51, 0, 0, 2052, 2053, 5, 109, 0, 0, 2053, 2054, 5, 97, 0, 0, 2054, 2055, 5, 116, 0, 0, 2055, 2056, 5, 51, 0, 0, 2056, 2057, 5, 120, 0, 0, 2057, 2059, 5, 51, 0, 0, 2058, 2032, 1, 0, 0, 0, 2058, 2041, 1, 0, 0, 0, 2058, 2048, 1, 0, 0, 0, 2058, 2052, 1, 0, 0, 0, 2059, 289, 1, 0, 0, 0, 2060, 2061, 5, 102, 0, 0, 2061, 2062, 5, 51, 0, 0, 2062, 2063, 5, 50, 0, 0, 2063, 2064, 5, 109, 0, 0, 2064, 2065, 5, 97, 0, 0, 2065, 2066, 5, 116, 0, 0, 2066, 2067, 5, 51, 0, 0, 2067, 2068, 5, 120, 0, 0, 2068, 2076, 5, 52, 0, 0, 2069, 2070, 5, 109, 0, 0, 2070, 2071, 5, 97, 0, 0, 2071, 2072, 5, 116, 0, 0, 2072, 2073, 5, 51, 0, 0, 2073, 2074, 5, 120, 0, 0, 2074, 2076, 5, 52, 0, 0, 2075, 2060, 1, 0, 0, 0, 2075, 2069, 1, 0, 0, 0, 2076, 291, 1, 0, 0, 0, 2077, 2078, 5, 102, 0, 0, 2078, 2079, 5, 51, 0, 0, 2079, 2080, 5, 50, 0, 0, 2080, 2081, 5, 109, 0, 0, 2081, 2082, 5, 97, 0, 0, 2082, 2083, 5, 116, 0, 0, 2083, 2084, 5, 52, 0, 0, 2084, 2085, 5, 120, 0, 0, 2085, 2093, 5, 50, 0, 0, 2086, 2087, 5, 109, 0, 0, 2087, 2088, 5, 97, 0, 0, 2088, 2089, 5, 116, 0, 0, 2089, 2090, 5, 52, 0, 0, 2090, 2091, 5, 120, 0, 0, 2091, 2093, 5, 50, 0, 0, 2092, 2077, 1, 0, 0, 0, 2092, 2086, 1, 0, 0, 0, 2093, 293, 1, 0, 0, 0, 2094, 2095, 5, 102, 0, 0, 2095, 2096, 5, 51, 0, 0, 2096, 2097, 5, 50, 0, 0, 2097, 2098, 5, 109, 0, 0, 2098, 2099, 5, 97, 0, 0, 2099, 2100, 5, 116, 0, 0, 2100, 2101, 5, 52, 0, 0, 2101, 2102, 5, 120, 0, 0, 2102, 2110, 5, 51, 0, 0, 2103, 2104, 5, 109, 0, 0, 2104, 2105, 5, 97, 0, 0, 2105, 2106, 5, 116, 0, 0, 2106, 2107, 5, 52, 0, 0, 2107, 2108, 5, 120, 0, 0, 2108, 2110, 5, 51, 0, 0, 2109, 2094, 1, 0, 0, 0, 2109, 2103, 1, 0, 0, 0, 2110, 295, 1, 0, 0, 0, 2111, 2112, 5, 102, 0, 0, 2112, 2113, 5, 51, 0, 0, 2113, 2114, 5, 50, 0, 0, 2114, 2115, 5, 109, 0, 0, 2115, 2116, 5, 97, 0, 0, 2116, 2117, 5, 116, 0, 0, 2117, 2118, 5, 52, 0, 0, 2118, 2119, 5, 120, 0, 0, 2119, 2138, 5, 52, 0, 0, 2120, 2121, 5, 102, 0, 0, 2121, 2122, 5, 51, 0, 0, 2122, 2123, 5, 50, 0, 0, 2123, 2124, 5, 109, 0, 0, 2124, 2125, 5, 97, 0, 0, 2125, 2126, 5, 116, 0, 0, 2126, 2138, 5, 52, 0, 0, 2127, 2128, 5, 109, 0, 0, 2128, 2129, 5, 97, 0, 0, 2129, 2130, 5, 116, 0, 0, 2130, 2138, 5, 52, 0, 0, 2131, 2132, 5, 109, 0, 0, 2132, 2133, 5, 97, 0, 0, 2133, 2134, 5, 116, 0, 0, 2134, 2135, 5, 52, 0, 0, 2135, 2136, 5, 120, 0, 0, 2136, 2138, 5, 52, 0, 0, 2137, 2111, 1, 0, 0, 0, 2137, 2120, 1, 0, 0, 0, 2137, 2127, 1, 0, 0, 0, 2137, 2131, 1, 0, 0, 0, 2138, 297, 1, 0, 0, 0, 2139, 2140, 5, 102, 0, 0, 2140, 2141, 5, 108, 0, 0, 2141, 2142, 5, 111, 0, 0, 2142, 2143, 5, 97, 0, 0, 2143, 2144, 5, 116, 0, 0, 2144, 2145, 5, 54, 0, 0, 2145, 2146, 5, 52, 0, 0, 2146, 2147, 5, 95, 0, 0, 2147, 2155, 5, 116, 0, 0, 2148, 2149, 5, 100, 0, 0, 2149, 2150, 5, 111, 0, 0, 2150, 2151, 5, 117, 0, 0, 2151, 2152, 5, 98, 0, 0, 2152, 2153, 5, 108, 0, 0, 2153, 2155, 5, 101, 0, 0, 2154, 2139, 1, 0, 0, 0, 2154, 2148, 1, 0, 0, 0, 2155, 299, 1, 0, 0, 0, 2156, 2157, 5, 102, 0, 0, 2157, 2158, 5, 54, 0, 0, 2158, 2159, 5, 52, 0, 0, 2159, 2160, 5, 118, 0, 0, 2160, 2161, 5, 101, 0, 0, 2161, 2162, 5, 99, 0, 0, 2162, 2169, 5, 50, 0, 0, 2163, 2164, 5, 100, 0, 0, 2164, 2165, 5, 118, 0, 0, 2165, 2166, 5, 101, 0, 0, 2166, 2167, 5, 99, 0, 0, 2167, 2169, 5, 50, 0, 0, 2168, 2156, 1, 0, 0, 0, 2168, 2163, 1, 0, 0, 0, 2169, 301, 1, 0, 0, 0, 2170, 2171, 5, 102, 0, 0, 2171, 2172, 5, 54, 0, 0, 2172, 2173, 5, 52, 0, 0, 2173, 2174, 5, 118, 0, 0, 2174, 2175, 5, 101, 0, 0, 2175, 2176, 5, 99, 0, 0, 2176, 2183, 5, 51, 0, 0, 2177, 2178, 5, 100, 0, 0, 2178, 2179, 5, 118, 0, 0, 2179, 2180, 5, 101, 0, 0, 2180, 2181, 5, 99, 0, 0, 2181, 2183, 5, 51, 0, 0, 2182, 2170, 1, 0, 0, 0, 2182, 2177, 1, 0, 0, 0, 2183, 303, 1, 0, 0, 0, 2184, 2185, 5, 102, 0, 0, 2185, 2186, 5, 54, 0, 0, 2186, 2187, 5, 52, 0, 0, 2187, 2188, 5, 118, 0, 0, 2188, 2189, 5, 101, 0, 0, 2189, 2190, 5, 99, 0, 0, 2190, 2197, 5, 52, 0, 0, 2191, 2192, 5, 100, 0, 0, 2192, 2193, 5, 118, 0, 0, 2193, 2194, 5, 101, 0, 0, 2194, 2195, 5, 99, 0, 0, 2195, 2197, 5, 52, 0, 0, 2196, 2184, 1, 0, 0, 0, 2196, 2191, 1, 0, 0, 0, 2197, 305, 1, 0, 0, 0, 2198, 2199, 5, 102, 0, 0, 2199, 2200, 5, 54, 0, 0, 2200, 2201, 5, 52, 0, 0, 2201, 2202, 5, 109, 0, 0, 2202, 2203, 5, 97, 0, 0, 2203, 2204, 5, 116, 0, 0, 2204, 2205, 5, 50, 0, 0, 2205, 2206, 5, 120, 0, 0, 2206, 2227, 5, 50, 0, 0, 2207, 2208, 5, 102, 0, 0, 2208, 2209, 5, 54, 0, 0, 2209, 2210, 5, 52, 0, 0, 2210, 2211, 5, 109, 0, 0, 2211, 2212, 5, 97, 0, 0, 2212, 2213, 5, 116, 0, 0, 2213, 2227, 5, 50, 0, 0, 2214, 2215, 5, 100, 0, 0, 2215, 2216, 5, 109, 0, 0, 2216, 2217, 5, 97, 0, 0, 2217, 2218, 5, 116, 0, 0, 2218, 2227, 5, 50, 0, 0, 2219, 2220, 5, 100, 0, 0, 2220, 2221, 5, 109, 0, 0, 2221, 2222, 5, 97, 0, 0, 2222, 2223, 5, 116, 0, 0, 2223, 2224, 5, 50, 0, 0, 2224, 2225, 5, 120, 0, 0, 2225, 2227, 5, 50, 0, 0, 2226, 2198, 1, 0, 0, 0, 2226, 2207, 1, 0, 0, 0, 2226, 2214, 1, 0, 0, 0, 2226, 2219, 1, 0, 0, 0, 2227, 307, 1, 0, 0, 0, 2228, 2229, 5, 102, 0, 0, 2229, 2230, 5, 54, 0, 0, 2230, 2231, 5, 52, 0, 0, 2231, 2232, 5, 109, 0, 0, 2232, 2233, 5, 97, 0, 0, 2233, 2234, 5, 116, 0, 0, 2234, 2235, 5, 50, 0, 0, 2235, 2236, 5, 120, 0, 0, 2236, 2245, 5, 51, 0, 0, 2237, 2238, 5, 100, 0, 0, 2238, 2239, 5, 109, 0, 0, 2239, 2240, 5, 97, 0, 0, 2240, 2241, 5, 116, 0, 0, 2241, 2242, 5, 50, 0, 0, 2242, 2243, 5, 120, 0, 0, 2243, 2245, 5, 51, 0, 0, 2244, 2228, 1, 0, 0, 0, 2244, 2237, 1, 0, 0, 0, 2245, 309, 1, 0, 0, 0, 2246, 2247, 5, 102, 0, 0, 2247, 2248, 5, 54, 0, 0, 2248, 2249, 5, 52, 0, 0, 2249, 2250, 5, 109, 0, 0, 2250, 2251, 5, 97, 0, 0, 2251, 2252, 5, 116, 0, 0, 2252, 2253, 5, 50, 0, 0, 2253, 2254, 5, 120, 0, 0, 2254, 2263, 5, 52, 0, 0, 2255, 2256, 5, 100, 0, 0, 2256, 2257, 5, 109, 0, 0, 2257, 2258, 5, 97, 0, 0, 2258, 2259, 5, 116, 0, 0, 2259, 2260, 5, 50, 0, 0, 2260, 2261, 5, 120, 0, 0, 2261, 2263, 5, 52, 0, 0, 2262, 2246, 1, 0, 0, 0, 2262, 2255, 1, 0, 0, 0, 2263, 311, 1, 0, 0, 0, 2264, 2265, 5, 102, 0, 0, 2265, 2266, 5, 54, 0, 0, 2266, 2267, 5, 52, 0, 0, 2267, 2268, 5, 109, 0, 0, 2268, 2269, 5, 97, 0, 0, 2269, 2270, 5, 116, 0, 0, 2270, 2271, 5, 51, 0, 0, 2271, 2272, 5, 120, 0, 0, 2272, 2281, 5, 50, 0, 0, 2273, 2274, 5, 100, 0, 0, 2274, 2275, 5, 109, 0, 0, 2275, 2276, 5, 97, 0, 0, 2276, 2277, 5, 116, 0, 0, 2277, 2278, 5, 51, 0, 0, 2278, 2279, 5, 120, 0, 0, 2279, 2281, 5, 50, 0, 0, 2280, 2264, 1, 0, 0, 0, 2280, 2273, 1, 0, 0, 0, 2281, 313, 1, 0, 0, 0, 2282, 2283, 5, 102, 0, 0, 2283, 2284, 5, 54, 0, 0, 2284, 2285, 5, 52, 0, 0, 2285, 2286, 5, 109, 0, 0, 2286, 2287, 5, 97, 0, 0, 2287, 2288, 5, 116, 0, 0, 2288, 2289, 5, 51, 0, 0, 2289, 2290, 5, 120, 0, 0, 2290, 2311, 5, 51, 0, 0, 2291, 2292, 5, 102, 0, 0, 2292, 2293, 5, 54, 0, 0, 2293, 2294, 5, 52, 0, 0, 2294, 2295, 5, 109, 0, 0, 2295, 2296, 5, 97, 0, 0, 2296, 2297, 5, 116, 0, 0, 2297, 2311, 5, 51, 0, 0, 2298, 2299, 5, 100, 0, 0, 2299, 2300, 5, 109, 0, 0, 2300, 2301, 5, 97, 0, 0, 2301, 2302, 5, 116, 0, 0, 2302, 2311, 5, 51, 0, 0, 2303, 2304, 5, 100, 0, 0, 2304, 2305, 5, 109, 0, 0, 2305, 2306, 5, 97, 0, 0, 2306, 2307, 5, 116, 0, 0, 2307, 2308, 5, 51, 0, 0, 2308, 2309, 5, 120, 0, 0, 2309, 2311, 5, 51, 0, 0, 2310, 2282, 1, 0, 0, 0, 2310, 2291, 1, 0, 0, 0, 2310, 2298, 1, 0, 0, 0, 2310, 2303, 1, 0, 0, 0, 2311, 315, 1, 0, 0, 0, 2312, 2313, 5, 102, 0, 0, 2313, 2314, 5, 54, 0, 0, 2314, 2315, 5, 52, 0, 0, 2315, 2316, 5, 109, 0, 0, 2316, 2317, 5, 97, 0, 0, 2317, 2318, 5, 116, 0, 0, 2318, 2319, 5, 51, 0, 0, 2319, 2320, 5, 120, 0, 0, 2320, 2329, 5, 52, 0, 0, 2321, 2322, 5, 100, 0, 0, 2322, 2323, 5, 109, 0, 0, 2323, 2324, 5, 97, 0, 0, 2324, 2325, 5, 116, 0, 0, 2325, 2326, 5, 51, 0, 0, 2326, 2327, 5, 120, 0, 0, 2327, 2329, 5, 52, 0, 0, 2328, 2312, 1, 0, 0, 0, 2328, 2321, 1, 0, 0, 0, 2329, 317, 1, 0, 0, 0, 2330, 2331, 5, 102, 0, 0, 2331, 2332, 5, 54, 0, 0, 2332, 2333, 5, 52, 0, 0, 2333, 2334, 5, 109, 0, 0, 2334, 2335, 5, 97, 0, 0, 2335, 2336, 5, 116, 0, 0, 2336, 2337, 5, 52, 0, 0, 2337, 2338, 5, 120, 0, 0, 2338, 2347, 5, 50, 0, 0, 2339, 2340, 5, 100, 0, 0, 2340, 2341, 5, 109, 0, 0, 2341, 2342, 5, 97, 0, 0, 2342, 2343, 5, 116, 0, 0, 2343, 2344, 5, 52, 0, 0, 2344, 2345, 5, 120, 0, 0, 2345, 2347, 5, 50, 0, 0, 2346, 2330, 1, 0, 0, 0, 2346, 2339, 1, 0, 0, 0, 2347, 319, 1, 0, 0, 0, 2348, 2349, 5, 102, 0, 0, 2349, 2350, 5, 54, 0, 0, 2350, 2351, 5, 52, 0, 0, 2351, 2352, 5, 109, 0, 0, 2352, 2353, 5, 97, 0, 0, 2353, 2354, 5, 116, 0, 0, 2354, 2355, 5, 52, 0, 0, 2355, 2356, 5, 120, 0, 0, 2356, 2365, 5, 51, 0, 0, 2357, 2358, 5, 100, 0, 0, 2358, 2359, 5, 109, 0, 0, 2359, 2360, 5, 97, 0, 0, 2360, 2361, 5, 116, 0, 0, 2361, 2362, 5, 52, 0, 0, 2362, 2363, 5, 120, 0, 0, 2363, 2365, 5, 51, 0, 0, 2364, 2348, 1, 0, 0, 0, 2364, 2357, 1, 0, 0, 0, 2365, 321, 1, 0, 0, 0, 2366, 2367, 5, 102, 0, 0, 2367, 2368, 5, 54, 0, 0, 2368, 2369, 5, 52, 0, 0, 2369, 2370, 5, 109, 0, 0, 2370, 2371, 5, 97, 0, 0, 2371, 2372, 5, 116, 0, 0, 2372, 2373, 5, 52, 0, 0, 2373, 2374, 5, 120, 0, 0, 2374, 2395, 5, 52, 0, 0, 2375, 2376, 5, 102, 0, 0, 2376, 2377, 5, 54, 0, 0, 2377, 2378, 5, 52, 0, 0, 2378, 2379, 5, 109, 0, 0, 2379, 2380, 5, 97, 0, 0, 2380, 2381, 5, 116, 0, 0, 2381, 2395, 5, 52, 0, 0, 2382, 2383, 5, 100, 0, 0, 2383, 2384, 5, 109, 0, 0, 2384, 2385, 5, 97, 0, 0, 2385, 2386, 5, 116, 0, 0, 2386, 2395, 5, 52, 0, 0, 2387, 2388, 5, 100, 0, 0, 2388, 2389, 5, 109, 0, 0, 2389, 2390, 5, 97, 0, 0, 2390, 2391, 5, 116, 0, 0, 2391, 2392, 5, 52, 0, 0, 2392, 2393, 5, 120, 0, 0, 2393, 2395, 5, 52, 0, 0, 2394, 2366, 1, 0, 0, 0, 2394, 2375, 1, 0, 0, 0, 2394, 2382, 1, 0, 0, 0, 2394, 2387, 1, 0, 0, 0, 2395, 323, 1, 0, 0, 0, 2396, 2397, 5, 105, 0, 0, 2397, 2398, 5, 109, 0, 0, 2398, 2399, 5, 97, 0, 0, 2399, 2400, 5, 103, 0, 0, 2400, 2401, 5, 101, 0, 0, 2401, 2402, 5, 49, 0, 0, 2402, 2403, 5, 68, 0, 0, 2403, 325, 1, 0, 0, 0, 2404, 2405, 5, 105, 0, 0, 2405, 2406, 5, 109, 0, 0, 2406, 2407, 5, 97, 0, 0, 2407, 2408, 5, 103, 0, 0, 2408, 2409, 5, 101, 0, 0, 2409, 2410, 5, 50, 0, 0, 2410, 2411, 5, 68, 0, 0, 2411, 327, 1, 0, 0, 0, 2412, 2413, 5, 105, 0, 0, 2413, 2414, 5, 109, 0, 0, 2414, 2415, 5, 97, 0, 0, 2415, 2416, 5, 103, 0, 0, 2416, 2417, 5, 101, 0, 0, 2417, 2418, 5, 51, 0, 0, 2418, 2419, 5, 68, 0, 0, 2419, 329, 1, 0, 0, 0, 2420, 2421, 5, 117, 0, 0, 2421, 2422, 5, 105, 0, 0, 2422, 2423, 5, 109, 0, 0, 2423, 2424, 5, 97, 0, 0, 2424, 2425, 5, 103, 0, 0, 2425, 2426, 5, 101, 0, 0, 2426, 2427, 5, 49, 0, 0, 2427, 2428, 5, 68, 0, 0, 2428, 331, 1, 0, 0, 0, 2429, 2430, 5, 117, 0, 0, 2430, 2431, 5, 105, 0, 0, 2431, 2432, 5, 109, 0, 0, 2432, 2433, 5, 97, 0, 0, 2433, 2434, 5, 103, 0, 0, 2434, 2435, 5, 101, 0, 0, 2435, 2436, 5, 50, 0, 0, 2436, 2437, 5, 68, 0, 0, 2437, 333, 1, 0, 0, 0, 2438, 2439, 5, 117, 0, 0, 2439, 2440, 5, 105, 0, 0, 2440, 2441, 5, 109, 0, 0, 2441, 2442, 5, 97, 0, 0, 2442, 2443, 5, 103, 0, 0, 2443, 2444, 5, 101, 0, 0, 2444, 2445, 5, 51, 0, 0, 2445, 2446, 5, 68, 0, 0, 2446, 335, 1, 0, 0, 0, 2447, 2448, 5, 105, 0, 0, 2448, 2449, 5, 105, 0, 0, 2449, 2450, 5, 109, 0, 0, 2450, 2451, 5, 97, 0, 0, 2451, 2452, 5, 103, 0, 0, 2452, 2453, 5, 101, 0, 0, 2453, 2454, 5, 49, 0, 0, 2454, 2455, 5, 68, 0, 0, 2455, 337, 1, 0, 0, 0, 2456, 2457, 5, 105, 0, 0, 2457, 2458, 5, 105, 0, 0, 2458, 2459, 5, 109, 0, 0, 2459, 2460, 5, 97, 0, 0, 2460, 2461, 5, 103, 0, 0, 2461, 2462, 5, 101, 0, 0, 2462, 2463, 5, 50, 0, 0, 2463, 2464, 5, 68, 0, 0, 2464, 339, 1, 0, 0, 0, 2465, 2466, 5, 105, 0, 0, 2466, 2467, 5, 105, 0, 0, 2467, 2468, 5, 109, 0, 0, 2468, 2469, 5, 97, 0, 0, 2469, 2470, 5, 103, 0, 0, 2470, 2471, 5, 101, 0, 0, 2471, 2472, 5, 51, 0, 0, 2472, 2473, 5, 68, 0, 0, 2473, 341, 1, 0, 0, 0, 2474, 2475, 5, 115, 0, 0, 2475, 2476, 5, 97, 0, 0, 2476, 2477, 5, 109, 0, 0, 2477, 2478, 5, 112, 0, 0, 2478, 2479, 5, 108, 0, 0, 2479, 2480, 5, 101, 0, 0, 2480, 2481, 5, 114, 0, 0, 2481, 2482, 5, 49, 0, 0, 2482, 2483, 5, 68, 0, 0, 2483, 343, 1, 0, 0, 0, 2484, 2485, 5, 115, 0, 0, 2485, 2486, 5, 97, 0, 0, 2486, 2487, 5, 109, 0, 0, 2487, 2488, 5, 112, 0, 0, 2488, 2489, 5, 108, 0, 0, 2489, 2490, 5, 101, 0, 0, 2490, 2491, 5, 114, 0, 0, 2491, 2492, 5, 50, 0, 0, 2492, 2493, 5, 68, 0, 0, 2493, 345, 1, 0, 0, 0, 2494, 2495, 5, 115, 0, 0, 2495, 2496, 5, 97, 0, 0, 2496, 2497, 5, 109, 0, 0, 2497, 2498, 5, 112, 0, 0, 2498, 2499, 5, 108, 0, 0, 2499, 2500, 5, 101, 0, 0, 2500, 2501, 5, 114, 0, 0, 2501, 2502, 5, 51, 0, 0, 2502, 2503, 5, 68, 0, 0, 2503, 347, 1, 0, 0, 0, 2504, 2505, 5, 115, 0, 0, 2505, 2506, 5, 97, 0, 0, 2506, 2507, 5, 109, 0, 0, 2507, 2508, 5, 112, 0, 0, 2508, 2509, 5, 108, 0, 0, 2509, 2510, 5, 101, 0, 0, 2510, 2511, 5, 114, 0, 0, 2511, 2512, 5, 50, 0, 0, 2512, 2513, 5, 68, 0, 0, 2513, 2514, 5, 82, 0, 0, 2514, 2515, 5, 101, 0, 0, 2515, 2516, 5, 99, 0, 0, 2516, 2517, 5, 116, 0, 0, 2517, 349, 1, 0, 0, 0, 2518, 2519, 5, 115, 0, 0, 2519, 2520, 5, 97, 0, 0, 2520, 2521, 5, 109, 0, 0, 2521, 2522, 5, 112, 0, 0, 2522, 2523, 5, 108, 0, 0, 2523, 2524, 5, 101, 0, 0, 2524, 2525, 5, 114, 0, 0, 2525, 2526, 5, 49, 0, 0, 2526, 2527, 5, 68, 0, 0, 2527, 2528, 5, 83, 0, 0, 2528, 2529, 5, 104, 0, 0, 2529, 2530, 5, 97, 0, 0, 2530, 2531, 5, 100, 0, 0, 2531, 2532, 5, 111, 0, 0, 2532, 2533, 5, 119, 0, 0, 2533, 351, 1, 0, 0, 0, 2534, 2535, 5, 115, 0, 0, 2535, 2536, 5, 97, 0, 0, 2536, 2537, 5, 109, 0, 0, 2537, 2538, 5, 112, 0, 0, 2538, 2539, 5, 108, 0, 0, 2539, 2540, 5, 101, 0, 0, 2540, 2541, 5, 114, 0, 0, 2541, 2542, 5, 50, 0, 0, 2542, 2543, 5, 68, 0, 0, 2543, 2544, 5, 83, 0, 0, 2544, 2545, 5, 104, 0, 0, 2545, 2546, 5, 97, 0, 0, 2546, 2547, 5, 100, 0, 0, 2547, 2548, 5, 111, 0, 0, 2548, 2549, 5, 119, 0, 0, 2549, 353, 1, 0, 0, 0, 2550, 2551, 5, 115, 0, 0, 2551, 2552, 5, 97, 0, 0, 2552, 2553, 5, 109, 0, 0, 2553, 2554, 5, 112, 0, 0, 2554, 2555, 5, 108, 0, 0, 2555, 2556, 5, 101, 0, 0, 2556, 2557, 5, 114, 0, 0, 2557, 2558, 5, 50, 0, 0, 2558, 2559, 5, 68, 0, 0, 2559, 2560, 5, 82, 0, 0, 2560, 2561, 5, 101, 0, 0, 2561, 2562, 5, 99, 0, 0, 2562, 2563, 5, 116, 0, 0, 2563, 2564, 5, 83, 0, 0, 2564, 2565, 5, 104, 0, 0, 2565, 2566, 5, 97, 0, 0, 2566, 2567, 5, 100, 0, 0, 2567, 2568, 5, 111, 0, 0, 2568, 2569, 5, 119, 0, 0, 2569, 355, 1, 0, 0, 0, 2570, 2571, 5, 115, 0, 0, 2571, 2572, 5, 97, 0, 0, 2572, 2573, 5, 109, 0, 0, 2573, 2574, 5, 112, 0, 0, 2574, 2575, 5, 108, 0, 0, 2575, 2576, 5, 101, 0, 0, 2576, 2577, 5, 114, 0, 0, 2577, 2578, 5, 49, 0, 0, 2578, 2579, 5, 68, 0, 0, 2579, 2580, 5, 65, 0, 0, 2580, 2581, 5, 114, 0, 0, 2581, 2582, 5, 114, 0, 0, 2582, 2583, 5, 97, 0, 0, 2583, 2584, 5, 121, 0, 0, 2584, 357, 1, 0, 0, 0, 2585, 2586, 5, 115, 0, 0, 2586, 2587, 5, 97, 0, 0, 2587, 2588, 5, 109, 0, 0, 2588, 2589, 5, 112, 0, 0, 2589, 2590, 5, 108, 0, 0, 2590, 2591, 5, 101, 0, 0, 2591, 2592, 5, 114, 0, 0, 2592, 2593, 5, 50, 0, 0, 2593, 2594, 5, 68, 0, 0, 2594, 2595, 5, 65, 0, 0, 2595, 2596, 5, 114, 0, 0, 2596, 2597, 5, 114, 0, 0, 2597, 2598, 5, 97, 0, 0, 2598, 2599, 5, 121, 0, 0, 2599, 359, 1, 0, 0, 0, 2600, 2601, 5, 115, 0, 0, 2601, 2602, 5, 97, 0, 0, 2602, 2603, 5, 109, 0, 0, 2603, 2604, 5, 112, 0, 0, 2604, 2605, 5, 108, 0, 0, 2605, 2606, 5, 101, 0, 0, 2606, 2607, 5, 114, 0, 0, 2607, 2608, 5, 49, 0, 0, 2608, 2609, 5, 68, 0, 0, 2609, 2610, 5, 65, 0, 0, 2610, 2611, 5, 114, 0, 0, 2611, 2612, 5, 114, 0, 0, 2612, 2613, 5, 97, 0, 0, 2613, 2614, 5, 121, 0, 0, 2614, 2615, 5, 83, 0, 0, 2615, 2616, 5, 104, 0, 0, 2616, 2617, 5, 97, 0, 0, 2617, 2618, 5, 100, 0, 0, 2618, 2619, 5, 111, 0, 0, 2619, 2620, 5, 119, 0, 0, 2620, 2621, 1, 0, 0, 0, 2621, 2622, 4, 177, 14, 0, 2622, 361, 1, 0, 0, 0, 2623, 2624, 5, 115, 0, 0, 2624, 2625, 5, 97, 0, 0, 2625, 2626, 5, 109, 0, 0, 2626, 2627, 5, 112, 0, 0, 2627, 2628, 5, 108, 0, 0, 2628, 2629, 5, 101, 0, 0, 2629, 2630, 5, 114, 0, 0, 2630, 2631, 5, 50, 0, 0, 2631, 2632, 5, 68, 0, 0, 2632, 2633, 5, 65, 0, 0, 2633, 2634, 5, 114, 0, 0, 2634, 2635, 5, 114, 0, 0, 2635, 2636, 5, 97, 0, 0, 2636, 2637, 5, 121, 0, 0, 2637, 2638, 5, 83, 0, 0, 2638, 2639, 5, 104, 0, 0, 2639, 2640, 5, 97, 0, 0, 2640, 2641, 5, 100, 0, 0, 2641, 2642, 5, 111, 0, 0, 2642, 2643, 5, 119, 0, 0, 2643, 363, 1, 0, 0, 0, 2644, 2645, 5, 105, 0, 0, 2645, 2646, 5, 115, 0, 0, 2646, 2647, 5, 97, 0, 0, 2647, 2648, 5, 109, 0, 0, 2648, 2649, 5, 112, 0, 0, 2649, 2650, 5, 108, 0, 0, 2650, 2651, 5, 101, 0, 0, 2651, 2652, 5, 114, 0, 0, 2652, 2653, 5, 49, 0, 0, 2653, 2654, 5, 68, 0, 0, 2654, 2655, 1, 0, 0, 0, 2655, 2656, 4, 179, 15, 0, 2656, 365, 1, 0, 0, 0, 2657, 2658, 5, 105, 0, 0, 2658, 2659, 5, 115, 0, 0, 2659, 2660, 5, 97, 0, 0, 2660, 2661, 5, 109, 0, 0, 2661, 2662, 5, 112, 0, 0, 2662, 2663, 5, 108, 0, 0, 2663, 2664, 5, 101, 0, 0, 2664, 2665, 5, 114, 0, 0, 2665, 2666, 5, 50, 0, 0, 2666, 2667, 5, 68, 0, 0, 2667, 367, 1, 0, 0, 0, 2668, 2669, 5, 105, 0, 0, 2669, 2670, 5, 115, 0, 0, 2670, 2671, 5, 97, 0, 0, 2671, 2672, 5, 109, 0, 0, 2672, 2673, 5, 112, 0, 0, 2673, 2674, 5, 108, 0, 0, 2674, 2675, 5, 101, 0, 0, 2675, 2676, 5, 114, 0, 0, 2676, 2677, 5, 50, 0, 0, 2677, 2678, 5, 68, 0, 0, 2678, 2679, 5, 82, 0, 0, 2679, 2680, 5, 101, 0, 0, 2680, 2681, 5, 99, 0, 0, 2681, 2682, 5, 116, 0, 0, 2682, 2683, 1, 0, 0, 0, 2683, 2684, 4, 181, 16, 0, 2684, 369, 1, 0, 0, 0, 2685, 2686, 5, 105, 0, 0, 2686, 2687, 5, 115, 0, 0, 2687, 2688, 5, 97, 0, 0, 2688, 2689, 5, 109, 0, 0, 2689, 2690, 5, 112, 0, 0, 2690, 2691, 5, 108, 0, 0, 2691, 2692, 5, 101, 0, 0, 2692, 2693, 5, 114, 0, 0, 2693, 2694, 5, 51, 0, 0, 2694, 2695, 5, 68, 0, 0, 2695, 371, 1, 0, 0, 0, 2696, 2697, 5, 105, 0, 0, 2697, 2698, 5, 115, 0, 0, 2698, 2699, 5, 97, 0, 0, 2699, 2700, 5, 109, 0, 0, 2700, 2701, 5, 112, 0, 0, 2701, 2702, 5, 108, 0, 0, 2702, 2703, 5, 101, 0, 0, 2703, 2704, 5, 114, 0, 0, 2704, 2705, 5, 49, 0, 0, 2705, 2706, 5, 68, 0, 0, 2706, 2707, 5, 65, 0, 0, 2707, 2708, 5, 114, 0, 0, 2708, 2709, 5, 114, 0, 0, 2709, 2710, 5, 97, 0, 0, 2710, 2711, 5, 121, 0, 0, 2711, 2712, 1, 0, 0, 0, 2712, 2713, 4, 183, 17, 0, 2713, 373, 1, 0, 0, 0, 2714, 2715, 5, 105, 0, 0, 2715, 2716, 5, 115, 0, 0, 2716, 2717, 5, 97, 0, 0, 2717, 2718, 5, 109, 0, 0, 2718, 2719, 5, 112, 0, 0, 2719, 2720, 5, 108, 0, 0, 2720, 2721, 5, 101, 0, 0, 2721, 2722, 5, 114, 0, 0, 2722, 2723, 5, 50, 0, 0, 2723, 2724, 5, 68, 0, 0, 2724, 2725, 5, 65, 0, 0, 2725, 2726, 5, 114, 0, 0, 2726, 2727, 5, 114, 0, 0, 2727, 2728, 5, 97, 0, 0, 2728, 2729, 5, 121, 0, 0, 2729, 375, 1, 0, 0, 0, 2730, 2731, 5, 117, 0, 0, 2731, 2732, 5, 115, 0, 0, 2732, 2733, 5, 97, 0, 0, 2733, 2734, 5, 109, 0, 0, 2734, 2735, 5, 112, 0, 0, 2735, 2736, 5, 108, 0, 0, 2736, 2737, 5, 101, 0, 0, 2737, 2738, 5, 114, 0, 0, 2738, 2739, 5, 49, 0, 0, 2739, 2740, 5, 68, 0, 0, 2740, 2741, 1, 0, 0, 0, 2741, 2742, 4, 185, 18, 0, 2742, 377, 1, 0, 0, 0, 2743, 2744, 5, 117, 0, 0, 2744, 2745, 5, 115, 0, 0, 2745, 2746, 5, 97, 0, 0, 2746, 2747, 5, 109, 0, 0, 2747, 2748, 5, 112, 0, 0, 2748, 2749, 5, 108, 0, 0, 2749, 2750, 5, 101, 0, 0, 2750, 2751, 5, 114, 0, 0, 2751, 2752, 5, 50, 0, 0, 2752, 2753, 5, 68, 0, 0, 2753, 379, 1, 0, 0, 0, 2754, 2755, 5, 117, 0, 0, 2755, 2756, 5, 115, 0, 0, 2756, 2757, 5, 97, 0, 0, 2757, 2758, 5, 109, 0, 0, 2758, 2759, 5, 112, 0, 0, 2759, 2760, 5, 108, 0, 0, 2760, 2761, 5, 101, 0, 0, 2761, 2762, 5, 114, 0, 0, 2762, 2763, 5, 50, 0, 0, 2763, 2764, 5, 68, 0, 0, 2764, 2765, 5, 82, 0, 0, 2765, 2766, 5, 101, 0, 0, 2766, 2767, 5, 99, 0, 0, 2767, 2768, 5, 116, 0, 0, 2768, 2769, 1, 0, 0, 0, 2769, 2770, 4, 187, 19, 0, 2770, 381, 1, 0, 0, 0, 2771, 2772, 5, 117, 0, 0, 2772, 2773, 5, 115, 0, 0, 2773, 2774, 5, 97, 0, 0, 2774, 2775, 5, 109, 0, 0, 2775, 2776, 5, 112, 0, 0, 2776, 2777, 5, 108, 0, 0, 2777, 2778, 5, 101, 0, 0, 2778, 2779, 5, 114, 0, 0, 2779, 2780, 5, 51, 0, 0, 2780, 2781, 5, 68, 0, 0, 2781, 383, 1, 0, 0, 0, 2782, 2783, 5, 117, 0, 0, 2783, 2784, 5, 115, 0, 0, 2784, 2785, 5, 97, 0, 0, 2785, 2786, 5, 109, 0, 0, 2786, 2787, 5, 112, 0, 0, 2787, 2788, 5, 108, 0, 0, 2788, 2789, 5, 101, 0, 0, 2789, 2790, 5, 114, 0, 0, 2790, 2791, 5, 49, 0, 0, 2791, 2792, 5, 68, 0, 0, 2792, 2793, 5, 65, 0, 0, 2793, 2794, 5, 114, 0, 0, 2794, 2795, 5, 114, 0, 0, 2795, 2796, 5, 97, 0, 0, 2796, 2797, 5, 121, 0, 0, 2797, 2798, 1, 0, 0, 0, 2798, 2799, 4, 189, 20, 0, 2799, 385, 1, 0, 0, 0, 2800, 2801, 5, 117, 0, 0, 2801, 2802, 5, 115, 0, 0, 2802, 2803, 5, 97, 0, 0, 2803, 2804, 5, 109, 0, 0, 2804, 2805, 5, 112, 0, 0, 2805, 2806, 5, 108, 0, 0, 2806, 2807, 5, 101, 0, 0, 2807, 2808, 5, 114, 0, 0, 2808, 2809, 5, 50, 0, 0, 2809, 2810, 5, 68, 0, 0, 2810, 2811, 5, 65, 0, 0, 2811, 2812, 5, 114, 0, 0, 2812, 2813, 5, 114, 0, 0, 2813, 2814, 5, 97, 0, 0, 2814, 2815, 5, 121, 0, 0, 2815, 387, 1, 0, 0, 0, 2816, 2817, 5, 115, 0, 0, 2817, 2818, 5, 97, 0, 0, 2818, 2819, 5, 109, 0, 0, 2819, 2820, 5, 112, 0, 0, 2820, 2821, 5, 108, 0, 0, 2821, 2822, 5, 101, 0, 0, 2822, 2823, 5, 114, 0, 0, 2823, 2824, 5, 50, 0, 0, 2824, 2825, 5, 68, 0, 0, 2825, 2826, 5, 77, 0, 0, 2826, 2827, 5, 83, 0, 0, 2827, 2828, 1, 0, 0, 0, 2828, 2829, 4, 191, 21, 0, 2829, 389, 1, 0, 0, 0, 2830, 2831, 5, 105, 0, 0, 2831, 2832, 5, 115, 0, 0, 2832, 2833, 5, 97, 0, 0, 2833, 2834, 5, 109, 0, 0, 2834, 2835, 5, 112, 0, 0, 2835, 2836, 5, 108, 0, 0, 2836, 2837, 5, 101, 0, 0, 2837, 2838, 5, 114, 0, 0, 2838, 2839, 5, 50, 0, 0, 2839, 2840, 5, 68, 0, 0, 2840, 2841, 5, 77, 0, 0, 2841, 2842, 5, 83, 0, 0, 2842, 2843, 1, 0, 0, 0, 2843, 2844, 4, 192, 22, 0, 2844, 391, 1, 0, 0, 0, 2845, 2846, 5, 117, 0, 0, 2846, 2847, 5, 115, 0, 0, 2847, 2848, 5, 97, 0, 0, 2848, 2849, 5, 109, 0, 0, 2849, 2850, 5, 112, 0, 0, 2850, 2851, 5, 108, 0, 0, 2851, 2852, 5, 101, 0, 0, 2852, 2853, 5, 114, 0, 0, 2853, 2854, 5, 50, 0, 0, 2854, 2855, 5, 68, 0, 0, 2855, 2856, 5, 77, 0, 0, 2856, 2857, 5, 83, 0, 0, 2857, 2858, 1, 0, 0, 0, 2858, 2859, 4, 193, 23, 0, 2859, 393, 1, 0, 0, 0, 2860, 2861, 5, 115, 0, 0, 2861, 2862, 5, 97, 0, 0, 2862, 2863, 5, 109, 0, 0, 2863, 2864, 5, 112, 0, 0, 2864, 2865, 5, 108, 0, 0, 2865, 2866, 5, 101, 0, 0, 2866, 2867, 5, 114, 0, 0, 2867, 2868, 5, 50, 0, 0, 2868, 2869, 5, 68, 0, 0, 2869, 2870, 5, 77, 0, 0, 2870, 2871, 5, 83, 0, 0, 2871, 2872, 5, 65, 0, 0, 2872, 2873, 5, 114, 0, 0, 2873, 2874, 5, 114, 0, 0, 2874, 2875, 5, 97, 0, 0, 2875, 2876, 5, 121, 0, 0, 2876, 2877, 1, 0, 0, 0, 2877, 2878, 4, 194, 24, 0, 2878, 395, 1, 0, 0, 0, 2879, 2880, 5, 105, 0, 0, 2880, 2881, 5, 115, 0, 0, 2881, 2882, 5, 97, 0, 0, 2882, 2883, 5, 109, 0, 0, 2883, 2884, 5, 112, 0, 0, 2884, 2885, 5, 108, 0, 0, 2885, 2886, 5, 101, 0, 0, 2886, 2887, 5, 114, 0, 0, 2887, 2888, 5, 50, 0, 0, 2888, 2889, 5, 68, 0, 0, 2889, 2890, 5, 77, 0, 0, 2890, 2891, 5, 83, 0, 0, 2891, 2892, 5, 65, 0, 0, 2892, 2893, 5, 114, 0, 0, 2893, 2894, 5, 114, 0, 0, 2894, 2895, 5, 97, 0, 0, 2895, 2896, 5, 121, 0, 0, 2896, 2897, 1, 0, 0, 0, 2897, 2898, 4, 195, 25, 0, 2898, 397, 1, 0, 0, 0, 2899, 2900, 5, 117, 0, 0, 2900, 2901, 5, 115, 0, 0, 2901, 2902, 5, 97, 0, 0, 2902, 2903, 5, 109, 0, 0, 2903, 2904, 5, 112, 0, 0, 2904, 2905, 5, 108, 0, 0, 2905, 2906, 5, 101, 0, 0, 2906, 2907, 5, 114, 0, 0, 2907, 2908, 5, 50, 0, 0, 2908, 2909, 5, 68, 0, 0, 2909, 2910, 5, 77, 0, 0, 2910, 2911, 5, 83, 0, 0, 2911, 2912, 5, 65, 0, 0, 2912, 2913, 5, 114, 0, 0, 2913, 2914, 5, 114, 0, 0, 2914, 2915, 5, 97, 0, 0, 2915, 2916, 5, 121, 0, 0, 2916, 2917, 1, 0, 0, 0, 2917, 2918, 4, 196, 26, 0, 2918, 399, 1, 0, 0, 0, 2919, 2920, 5, 105, 0, 0, 2920, 2921, 5, 109, 0, 0, 2921, 2922, 5, 97, 0, 0, 2922, 2923, 5, 103, 0, 0, 2923, 2924, 5, 101, 0, 0, 2924, 2925, 5, 50, 0, 0, 2925, 2926, 5, 68, 0, 0, 2926, 2927, 5, 82, 0, 0, 2927, 2928, 5, 101, 0, 0, 2928, 2929, 5, 99, 0, 0, 2929, 2930, 5, 116, 0, 0, 2930, 401, 1, 0, 0, 0, 2931, 2932, 5, 105, 0, 0, 2932, 2933, 5, 109, 0, 0, 2933, 2934, 5, 97, 0, 0, 2934, 2935, 5, 103, 0, 0, 2935, 2936, 5, 101, 0, 0, 2936, 2937, 5, 49, 0, 0, 2937, 2938, 5, 68, 0, 0, 2938, 2939, 5, 65, 0, 0, 2939, 2940, 5, 114, 0, 0, 2940, 2941, 5, 114, 0, 0, 2941, 2942, 5, 97, 0, 0, 2942, 2943, 5, 121, 0, 0, 2943, 403, 1, 0, 0, 0, 2944, 2945, 5, 105, 0, 0, 2945, 2946, 5, 109, 0, 0, 2946, 2947, 5, 97, 0, 0, 2947, 2948, 5, 103, 0, 0, 2948, 2949, 5, 101, 0, 0, 2949, 2950, 5, 50, 0, 0, 2950, 2951, 5, 68, 0, 0, 2951, 2952, 5, 65, 0, 0, 2952, 2953, 5, 114, 0, 0, 2953, 2954, 5, 114, 0, 0, 2954, 2955, 5, 97, 0, 0, 2955, 2956, 5, 121, 0, 0, 2956, 405, 1, 0, 0, 0, 2957, 2958, 5, 105, 0, 0, 2958, 2959, 5, 109, 0, 0, 2959, 2960, 5, 97, 0, 0, 2960, 2961, 5, 103, 0, 0, 2961, 2962, 5, 101, 0, 0, 2962, 2963, 5, 50, 0, 0, 2963, 2964, 5, 68, 0, 0, 2964, 2965, 5, 77, 0, 0, 2965, 2966, 5, 83, 0, 0, 2966, 407, 1, 0, 0, 0, 2967, 2968, 5, 105, 0, 0, 2968, 2969, 5, 109, 0, 0, 2969, 2970, 5, 97, 0, 0, 2970, 2971, 5, 103, 0, 0, 2971, 2972, 5, 101, 0, 0, 2972, 2973, 5, 50, 0, 0, 2973, 2974, 5, 68, 0, 0, 2974, 2975, 5, 77, 0, 0, 2975, 2976, 5, 83, 0, 0, 2976, 2977, 5, 65, 0, 0, 2977, 2978, 5, 114, 0, 0, 2978, 2979, 5, 114, 0, 0, 2979, 2980, 5, 97, 0, 0, 2980, 2981, 5, 121, 0, 0, 2981, 409, 1, 0, 0, 0, 2982, 2983, 5, 105, 0, 0, 2983, 2984, 5, 105, 0, 0, 2984, 2985, 5, 109, 0, 0, 2985, 2986, 5, 97, 0, 0, 2986, 2987, 5, 103, 0, 0, 2987, 2988, 5, 101, 0, 0, 2988, 2989, 5, 50, 0, 0, 2989, 2990, 5, 68, 0, 0, 2990, 2991, 5, 82, 0, 0, 2991, 2992, 5, 101, 0, 0, 2992, 2993, 5, 99, 0, 0, 2993, 2994, 5, 116, 0, 0, 2994, 411, 1, 0, 0, 0, 2995, 2996, 5, 105, 0, 0, 2996, 2997, 5, 105, 0, 0, 2997, 2998, 5, 109, 0, 0, 2998, 2999, 5, 97, 0, 0, 2999, 3000, 5, 103, 0, 0, 3000, 3001, 5, 101, 0, 0, 3001, 3002, 5, 49, 0, 0, 3002, 3003, 5, 68, 0, 0, 3003, 3004, 5, 65, 0, 0, 3004, 3005, 5, 114, 0, 0, 3005, 3006, 5, 114, 0, 0, 3006, 3007, 5, 97, 0, 0, 3007, 3008, 5, 121, 0, 0, 3008, 413, 1, 0, 0, 0, 3009, 3010, 5, 105, 0, 0, 3010, 3011, 5, 105, 0, 0, 3011, 3012, 5, 109, 0, 0, 3012, 3013, 5, 97, 0, 0, 3013, 3014, 5, 103, 0, 0, 3014, 3015, 5, 101, 0, 0, 3015, 3016, 5, 50, 0, 0, 3016, 3017, 5, 68, 0, 0, 3017, 3018, 5, 65, 0, 0, 3018, 3019, 5, 114, 0, 0, 3019, 3020, 5, 114, 0, 0, 3020, 3021, 5, 97, 0, 0, 3021, 3022, 5, 121, 0, 0, 3022, 415, 1, 0, 0, 0, 3023, 3024, 5, 105, 0, 0, 3024, 3025, 5, 105, 0, 0, 3025, 3026, 5, 109, 0, 0, 3026, 3027, 5, 97, 0, 0, 3027, 3028, 5, 103, 0, 0, 3028, 3029, 5, 101, 0, 0, 3029, 3030, 5, 50, 0, 0, 3030, 3031, 5, 68, 0, 0, 3031, 3032, 5, 77, 0, 0, 3032, 3033, 5, 83, 0, 0, 3033, 417, 1, 0, 0, 0, 3034, 3035, 5, 105, 0, 0, 3035, 3036, 5, 105, 0, 0, 3036, 3037, 5, 109, 0, 0, 3037, 3038, 5, 97, 0, 0, 3038, 3039, 5, 103, 0, 0, 3039, 3040, 5, 101, 0, 0, 3040, 3041, 5, 50, 0, 0, 3041, 3042, 5, 68, 0, 0, 3042, 3043, 5, 77, 0, 0, 3043, 3044, 5, 83, 0, 0, 3044, 3045, 5, 65, 0, 0, 3045, 3046, 5, 114, 0, 0, 3046, 3047, 5, 114, 0, 0, 3047, 3048, 5, 97, 0, 0, 3048, 3049, 5, 121, 0, 0, 3049, 419, 1, 0, 0, 0, 3050, 3051, 5, 117, 0, 0, 3051, 3052, 5, 105, 0, 0, 3052, 3053, 5, 109, 0, 0, 3053, 3054, 5, 97, 0, 0, 3054, 3055, 5, 103, 0, 0, 3055, 3056, 5, 101, 0, 0, 3056, 3057, 5, 50, 0, 0, 3057, 3058, 5, 68, 0, 0, 3058, 3059, 5, 82, 0, 0, 3059, 3060, 5, 101, 0, 0, 3060, 3061, 5, 99, 0, 0, 3061, 3062, 5, 116, 0, 0, 3062, 421, 1, 0, 0, 0, 3063, 3064, 5, 117, 0, 0, 3064, 3065, 5, 105, 0, 0, 3065, 3066, 5, 109, 0, 0, 3066, 3067, 5, 97, 0, 0, 3067, 3068, 5, 103, 0, 0, 3068, 3069, 5, 101, 0, 0, 3069, 3070, 5, 49, 0, 0, 3070, 3071, 5, 68, 0, 0, 3071, 3072, 5, 65, 0, 0, 3072, 3073, 5, 114, 0, 0, 3073, 3074, 5, 114, 0, 0, 3074, 3075, 5, 97, 0, 0, 3075, 3076, 5, 121, 0, 0, 3076, 423, 1, 0, 0, 0, 3077, 3078, 5, 117, 0, 0, 3078, 3079, 5, 105, 0, 0, 3079, 3080, 5, 109, 0, 0, 3080, 3081, 5, 97, 0, 0, 3081, 3082, 5, 103, 0, 0, 3082, 3083, 5, 101, 0, 0, 3083, 3084, 5, 50, 0, 0, 3084, 3085, 5, 68, 0, 0, 3085, 3086, 5, 65, 0, 0, 3086, 3087, 5, 114, 0, 0, 3087, 3088, 5, 114, 0, 0, 3088, 3089, 5, 97, 0, 0, 3089, 3090, 5, 121, 0, 0, 3090, 425, 1, 0, 0, 0, 3091, 3092, 5, 117, 0, 0, 3092, 3093, 5, 105, 0, 0, 3093, 3094, 5, 109, 0, 0, 3094, 3095, 5, 97, 0, 0, 3095, 3096, 5, 103, 0, 0, 3096, 3097, 5, 101, 0, 0, 3097, 3098, 5, 50, 0, 0, 3098, 3099, 5, 68, 0, 0, 3099, 3100, 5, 77, 0, 0, 3100, 3101, 5, 83, 0, 0, 3101, 427, 1, 0, 0, 0, 3102, 3103, 5, 117, 0, 0, 3103, 3104, 5, 105, 0, 0, 3104, 3105, 5, 109, 0, 0, 3105, 3106, 5, 97, 0, 0, 3106, 3107, 5, 103, 0, 0, 3107, 3108, 5, 101, 0, 0, 3108, 3109, 5, 50, 0, 0, 3109, 3110, 5, 68, 0, 0, 3110, 3111, 5, 77, 0, 0, 3111, 3112, 5, 83, 0, 0, 3112, 3113, 5, 65, 0, 0, 3113, 3114, 5, 114, 0, 0, 3114, 3115, 5, 114, 0, 0, 3115, 3116, 5, 97, 0, 0, 3116, 3117, 5, 121, 0, 0, 3117, 429, 1, 0, 0, 0, 3118, 3119, 5, 115, 0, 0, 3119, 3120, 5, 97, 0, 0, 3120, 3121, 5, 109, 0, 0, 3121, 3122, 5, 112, 0, 0, 3122, 3123, 5, 108, 0, 0, 3123, 3124, 5, 101, 0, 0, 3124, 3125, 5, 114, 0, 0, 3125, 3126, 5, 67, 0, 0, 3126, 3127, 5, 117, 0, 0, 3127, 3128, 5, 98, 0, 0, 3128, 3129, 5, 101, 0, 0, 3129, 3130, 5, 83, 0, 0, 3130, 3131, 5, 104, 0, 0, 3131, 3132, 5, 97, 0, 0, 3132, 3133, 5, 100, 0, 0, 3133, 3134, 5, 111, 0, 0, 3134, 3135, 5, 119, 0, 0, 3135, 431, 1, 0, 0, 0, 3136, 3137, 5, 115, 0, 0, 3137, 3138, 5, 97, 0, 0, 3138, 3139, 5, 109, 0, 0, 3139, 3140, 5, 112, 0, 0, 3140, 3141, 5, 108, 0, 0, 3141, 3142, 5, 101, 0, 0, 3142, 3143, 5, 114, 0, 0, 3143, 3144, 5, 67, 0, 0, 3144, 3145, 5, 117, 0, 0, 3145, 3146, 5, 98, 0, 0, 3146, 3147, 5, 101, 0, 0, 3147, 3148, 5, 65, 0, 0, 3148, 3149, 5, 114, 0, 0, 3149, 3150, 5, 114, 0, 0, 3150, 3151, 5, 97, 0, 0, 3151, 3152, 5, 121, 0, 0, 3152, 3153, 5, 83, 0, 0, 3153, 3154, 5, 104, 0, 0, 3154, 3155, 5, 97, 0, 0, 3155, 3156, 5, 100, 0, 0, 3156, 3157, 5, 111, 0, 0, 3157, 3158, 5, 119, 0, 0, 3158, 433, 1, 0, 0, 0, 3159, 3160, 5, 115, 0, 0, 3160, 3161, 5, 97, 0, 0, 3161, 3162, 5, 109, 0, 0, 3162, 3163, 5, 112, 0, 0, 3163, 3164, 5, 108, 0, 0, 3164, 3165, 5, 101, 0, 0, 3165, 3166, 5, 114, 0, 0, 3166, 3167, 5, 67, 0, 0, 3167, 3168, 5, 117, 0, 0, 3168, 3169, 5, 98, 0, 0, 3169, 3170, 5, 101, 0, 0, 3170, 435, 1, 0, 0, 0, 3171, 3172, 5, 105, 0, 0, 3172, 3173, 5, 115, 0, 0, 3173, 3174, 5, 97, 0, 0, 3174, 3175, 5, 109, 0, 0, 3175, 3176, 5, 112, 0, 0, 3176, 3177, 5, 108, 0, 0, 3177, 3178, 5, 101, 0, 0, 3178, 3179, 5, 114, 0, 0, 3179, 3180, 5, 67, 0, 0, 3180, 3181, 5, 117, 0, 0, 3181, 3182, 5, 98, 0, 0, 3182, 3183, 5, 101, 0, 0, 3183, 437, 1, 0, 0, 0, 3184, 3185, 5, 117, 0, 0, 3185, 3186, 5, 115, 0, 0, 3186, 3187, 5, 97, 0, 0, 3187, 3188, 5, 109, 0, 0, 3188, 3189, 5, 112, 0, 0, 3189, 3190, 5, 108, 0, 0, 3190, 3191, 5, 101, 0, 0, 3191, 3192, 5, 114, 0, 0, 3192, 3193, 5, 67, 0, 0, 3193, 3194, 5, 117, 0, 0, 3194, 3195, 5, 98, 0, 0, 3195, 3196, 5, 101, 0, 0, 3196, 439, 1, 0, 0, 0, 3197, 3198, 5, 115, 0, 0, 3198, 3199, 5, 97, 0, 0, 3199, 3200, 5, 109, 0, 0, 3200, 3201, 5, 112, 0, 0, 3201, 3202, 5, 108, 0, 0, 3202, 3203, 5, 101, 0, 0, 3203, 3204, 5, 114, 0, 0, 3204, 3205, 5, 66, 0, 0, 3205, 3206, 5, 117, 0, 0, 3206, 3207, 5, 102, 0, 0, 3207, 3208, 5, 102, 0, 0, 3208, 3209, 5, 101, 0, 0, 3209, 3210, 5, 114, 0, 0, 3210, 3211, 1, 0, 0, 0, 3211, 3212, 4, 217, 27, 0, 3212, 441, 1, 0, 0, 0, 3213, 3214, 5, 105, 0, 0, 3214, 3215, 5, 115, 0, 0, 3215, 3216, 5, 97, 0, 0, 3216, 3217, 5, 109, 0, 0, 3217, 3218, 5, 112, 0, 0, 3218, 3219, 5, 108, 0, 0, 3219, 3220, 5, 101, 0, 0, 3220, 3221, 5, 114, 0, 0, 3221, 3222, 5, 66, 0, 0, 3222, 3223, 5, 117, 0, 0, 3223, 3224, 5, 102, 0, 0, 3224, 3225, 5, 102, 0, 0, 3225, 3226, 5, 101, 0, 0, 3226, 3227, 5, 114, 0, 0, 3227, 3228, 1, 0, 0, 0, 3228, 3229, 4, 218, 28, 0, 3229, 443, 1, 0, 0, 0, 3230, 3231, 5, 117, 0, 0, 3231, 3232, 5, 115, 0, 0, 3232, 3233, 5, 97, 0, 0, 3233, 3234, 5, 109, 0, 0, 3234, 3235, 5, 112, 0, 0, 3235, 3236, 5, 108, 0, 0, 3236, 3237, 5, 101, 0, 0, 3237, 3238, 5, 114, 0, 0, 3238, 3239, 5, 66, 0, 0, 3239, 3240, 5, 117, 0, 0, 3240, 3241, 5, 102, 0, 0, 3241, 3242, 5, 102, 0, 0, 3242, 3243, 5, 101, 0, 0, 3243, 3244, 5, 114, 0, 0, 3244, 3245, 1, 0, 0, 0, 3245, 3246, 4, 219, 29, 0, 3246, 445, 1, 0, 0, 0, 3247, 3248, 5, 115, 0, 0, 3248, 3249, 5, 97, 0, 0, 3249, 3250, 5, 109, 0, 0, 3250, 3251, 5, 112, 0, 0, 3251, 3252, 5, 108, 0, 0, 3252, 3253, 5, 101, 0, 0, 3253, 3254, 5, 114, 0, 0, 3254, 3255, 5, 67, 0, 0, 3255, 3256, 5, 117, 0, 0, 3256, 3257, 5, 98, 0, 0, 3257, 3258, 5, 101, 0, 0, 3258, 3259, 5, 65, 0, 0, 3259, 3260, 5, 114, 0, 0, 3260, 3261, 5, 114, 0, 0, 3261, 3262, 5, 97, 0, 0, 3262, 3263, 5, 121, 0, 0, 3263, 447, 1, 0, 0, 0, 3264, 3265, 5, 105, 0, 0, 3265, 3266, 5, 115, 0, 0, 3266, 3267, 5, 97, 0, 0, 3267, 3268, 5, 109, 0, 0, 3268, 3269, 5, 112, 0, 0, 3269, 3270, 5, 108, 0, 0, 3270, 3271, 5, 101, 0, 0, 3271, 3272, 5, 114, 0, 0, 3272, 3273, 5, 67, 0, 0, 3273, 3274, 5, 117, 0, 0, 3274, 3275, 5, 98, 0, 0, 3275, 3276, 5, 101, 0, 0, 3276, 3277, 5, 65, 0, 0, 3277, 3278, 5, 114, 0, 0, 3278, 3279, 5, 114, 0, 0, 3279, 3280, 5, 97, 0, 0, 3280, 3281, 5, 121, 0, 0, 3281, 449, 1, 0, 0, 0, 3282, 3283, 5, 117, 0, 0, 3283, 3284, 5, 115, 0, 0, 3284, 3285, 5, 97, 0, 0, 3285, 3286, 5, 109, 0, 0, 3286, 3287, 5, 112, 0, 0, 3287, 3288, 5, 108, 0, 0, 3288, 3289, 5, 101, 0, 0, 3289, 3290, 5, 114, 0, 0, 3290, 3291, 5, 67, 0, 0, 3291, 3292, 5, 117, 0, 0, 3292, 3293, 5, 98, 0, 0, 3293, 3294, 5, 101, 0, 0, 3294, 3295, 5, 65, 0, 0, 3295, 3296, 5, 114, 0, 0, 3296, 3297, 5, 114, 0, 0, 3297, 3298, 5, 97, 0, 0, 3298, 3299, 5, 121, 0, 0, 3299, 451, 1, 0, 0, 0, 3300, 3301, 5, 105, 0, 0, 3301, 3302, 5, 109, 0, 0, 3302, 3303, 5, 97, 0, 0, 3303, 3304, 5, 103, 0, 0, 3304, 3305, 5, 101, 0, 0, 3305, 3306, 5, 67, 0, 0, 3306, 3307, 5, 117, 0, 0, 3307, 3308, 5, 98, 0, 0, 3308, 3309, 5, 101, 0, 0, 3309, 453, 1, 0, 0, 0, 3310, 3311, 5, 117, 0, 0, 3311, 3312, 5, 105, 0, 0, 3312, 3313, 5, 109, 0, 0, 3313, 3314, 5, 97, 0, 0, 3314, 3315, 5, 103, 0, 0, 3315, 3316, 5, 101, 0, 0, 3316, 3317, 5, 67, 0, 0, 3317, 3318, 5, 117, 0, 0, 3318, 3319, 5, 98, 0, 0, 3319, 3320, 5, 101, 0, 0, 3320, 455, 1, 0, 0, 0, 3321, 3322, 5, 105, 0, 0, 3322, 3323, 5, 105, 0, 0, 3323, 3324, 5, 109, 0, 0, 3324, 3325, 5, 97, 0, 0, 3325, 3326, 5, 103, 0, 0, 3326, 3327, 5, 101, 0, 0, 3327, 3328, 5, 67, 0, 0, 3328, 3329, 5, 117, 0, 0, 3329, 3330, 5, 98, 0, 0, 3330, 3331, 5, 101, 0, 0, 3331, 457, 1, 0, 0, 0, 3332, 3333, 5, 105, 0, 0, 3333, 3334, 5, 109, 0, 0, 3334, 3335, 5, 97, 0, 0, 3335, 3336, 5, 103, 0, 0, 3336, 3337, 5, 101, 0, 0, 3337, 3338, 5, 66, 0, 0, 3338, 3339, 5, 117, 0, 0, 3339, 3340, 5, 102, 0, 0, 3340, 3341, 5, 102, 0, 0, 3341, 3342, 5, 101, 0, 0, 3342, 3343, 5, 114, 0, 0, 3343, 459, 1, 0, 0, 0, 3344, 3345, 5, 105, 0, 0, 3345, 3346, 5, 105, 0, 0, 3346, 3347, 5, 109, 0, 0, 3347, 3348, 5, 97, 0, 0, 3348, 3349, 5, 103, 0, 0, 3349, 3350, 5, 101, 0, 0, 3350, 3351, 5, 66, 0, 0, 3351, 3352, 5, 117, 0, 0, 3352, 3353, 5, 102, 0, 0, 3353, 3354, 5, 102, 0, 0, 3354, 3355, 5, 101, 0, 0, 3355, 3356, 5, 114, 0, 0, 3356, 461, 1, 0, 0, 0, 3357, 3358, 5, 117, 0, 0, 3358, 3359, 5, 105, 0, 0, 3359, 3360, 5, 109, 0, 0, 3360, 3361, 5, 97, 0, 0, 3361, 3362, 5, 103, 0, 0, 3362, 3363, 5, 101, 0, 0, 3363, 3364, 5, 66, 0, 0, 3364, 3365, 5, 117, 0, 0, 3365, 3366, 5, 102, 0, 0, 3366, 3367, 5, 102, 0, 0, 3367, 3368, 5, 101, 0, 0, 3368, 3369, 5, 114, 0, 0, 3369, 463, 1, 0, 0, 0, 3370, 3371, 5, 105, 0, 0, 3371, 3372, 5, 109, 0, 0, 3372, 3373, 5, 97, 0, 0, 3373, 3374, 5, 103, 0, 0, 3374, 3375, 5, 101, 0, 0, 3375, 3376, 5, 67, 0, 0, 3376, 3377, 5, 117, 0, 0, 3377, 3378, 5, 98, 0, 0, 3378, 3379, 5, 101, 0, 0, 3379, 3380, 5, 65, 0, 0, 3380, 3381, 5, 114, 0, 0, 3381, 3382, 5, 114, 0, 0, 3382, 3383, 5, 97, 0, 0, 3383, 3384, 5, 121, 0, 0, 3384, 465, 1, 0, 0, 0, 3385, 3386, 5, 105, 0, 0, 3386, 3387, 5, 105, 0, 0, 3387, 3388, 5, 109, 0, 0, 3388, 3389, 5, 97, 0, 0, 3389, 3390, 5, 103, 0, 0, 3390, 3391, 5, 101, 0, 0, 3391, 3392, 5, 67, 0, 0, 3392, 3393, 5, 117, 0, 0, 3393, 3394, 5, 98, 0, 0, 3394, 3395, 5, 101, 0, 0, 3395, 3396, 5, 65, 0, 0, 3396, 3397, 5, 114, 0, 0, 3397, 3398, 5, 114, 0, 0, 3398, 3399, 5, 97, 0, 0, 3399, 3400, 5, 121, 0, 0, 3400, 467, 1, 0, 0, 0, 3401, 3402, 5, 117, 0, 0, 3402, 3403, 5, 105, 0, 0, 3403, 3404, 5, 109, 0, 0, 3404, 3405, 5, 97, 0, 0, 3405, 3406, 5, 103, 0, 0, 3406, 3407, 5, 101, 0, 0, 3407, 3408, 5, 67, 0, 0, 3408, 3409, 5, 117, 0, 0, 3409, 3410, 5, 98, 0, 0, 3410, 3411, 5, 101, 0, 0, 3411, 3412, 5, 65, 0, 0, 3412, 3413, 5, 114, 0, 0, 3413, 3414, 5, 114, 0, 0, 3414, 3415, 5, 97, 0, 0, 3415, 3416, 5, 121, 0, 0, 3416, 469, 1, 0, 0, 0, 3417, 3418, 5, 43, 0, 0, 3418, 3419, 5, 43, 0, 0, 3419, 471, 1, 0, 0, 0, 3420, 3421, 5, 45, 0, 0, 3421, 3422, 5, 45, 0, 0, 3422, 473, 1, 0, 0, 0, 3423, 3424, 5, 118, 0, 0, 3424, 3425, 5, 111, 0, 0, 3425, 3426, 5, 105, 0, 0, 3426, 3427, 5, 100, 0, 0, 3427, 475, 1, 0, 0, 0, 3428, 3429, 5, 60, 0, 0, 3429, 3430, 5, 60, 0, 0, 3430, 477, 1, 0, 0, 0, 3431, 3432, 5, 62, 0, 0, 3432, 3433, 5, 62, 0, 0, 3433, 479, 1, 0, 0, 0, 3434, 3435, 5, 60, 0, 0, 3435, 3436, 5, 61, 0, 0, 3436, 481, 1, 0, 0, 0, 3437, 3438, 5, 62, 0, 0, 3438, 3439, 5, 61, 0, 0, 3439, 483, 1, 0, 0, 0, 3440, 3441, 5, 61, 0, 0, 3441, 3442, 5, 61, 0, 0, 3442, 485, 1, 0, 0, 0, 3443, 3444, 5, 33, 0, 0, 3444, 3445, 5, 61, 0, 0, 3445, 487, 1, 0, 0, 0, 3446, 3447, 5, 38, 0, 0, 3447, 3448, 5, 38, 0, 0, 3448, 489, 1, 0, 0, 0, 3449, 3450, 5, 94, 0, 0, 3450, 3451, 5, 94, 0, 0, 3451, 491, 1, 0, 0, 0, 3452, 3453, 5, 124, 0, 0, 3453, 3454, 5, 124, 0, 0, 3454, 493, 1, 0, 0, 0, 3455, 3456, 5, 42, 0, 0, 3456, 3457, 5, 61, 0, 0, 3457, 495, 1, 0, 0, 0, 3458, 3459, 5, 47, 0, 0, 3459, 3460, 5, 61, 0, 0, 3460, 497, 1, 0, 0, 0, 3461, 3462, 5, 37, 0, 0, 3462, 3463, 5, 61, 0, 0, 3463, 499, 1, 0, 0, 0, 3464, 3465, 5, 43, 0, 0, 3465, 3466, 5, 61, 0, 0, 3466, 501, 1, 0, 0, 0, 3467, 3468, 5, 45, 0, 0, 3468, 3469, 5, 61, 0, 0, 3469, 503, 1, 0, 0, 0, 3470, 3471, 5, 60, 0, 0, 3471, 3472, 5, 60, 0, 0, 3472, 3473, 5, 61, 0, 0, 3473, 505, 1, 0, 0, 0, 3474, 3475, 5, 62, 0, 0, 3475, 3476, 5, 62, 0, 0, 3476, 3477, 5, 61, 0, 0, 3477, 507, 1, 0, 0, 0, 3478, 3479, 5, 38, 0, 0, 3479, 3480, 5, 61, 0, 0, 3480, 509, 1, 0, 0, 0, 3481, 3482, 5, 94, 0, 0, 3482, 3483, 5, 61, 0, 0, 3483, 511, 1, 0, 0, 0, 3484, 3485, 5, 124, 0, 0, 3485, 3486, 5, 61, 0, 0, 3486, 513, 1, 0, 0, 0, 3487, 3488, 5, 40, 0, 0, 3488, 515, 1, 0, 0, 0, 3489, 3490, 5, 41, 0, 0, 3490, 517, 1, 0, 0, 0, 3491, 3492, 5, 123, 0, 0, 3492, 519, 1, 0, 0, 0, 3493, 3494, 5, 125, 0, 0, 3494, 521, 1, 0, 0, 0, 3495, 3496, 5, 59, 0, 0, 3496, 523, 1, 0, 0, 0, 3497, 3498, 5, 91, 0, 0, 3498, 525, 1, 0, 0, 0, 3499, 3500, 5, 93, 0, 0, 3500, 527, 1, 0, 0, 0, 3501, 3502, 5, 44, 0, 0, 3502, 529, 1, 0, 0, 0, 3503, 3504, 5, 46, 0, 0, 3504, 531, 1, 0, 0, 0, 3505, 3506, 5, 43, 0, 0, 3506, 533, 1, 0, 0, 0, 3507, 3508, 5, 45, 0, 0, 3508, 535, 1, 0, 0, 0, 3509, 3510, 5, 33, 0, 0, 3510, 537, 1, 0, 0, 0, 3511, 3512, 5, 126, 0, 0, 3512, 539, 1, 0, 0, 0, 3513, 3514, 5, 42, 0, 0, 3514, 541, 1, 0, 0, 0, 3515, 3516, 5, 47, 0, 0, 3516, 543, 1, 0, 0, 0, 3517, 3518, 5, 37, 0, 0, 3518, 545, 1, 0, 0, 0, 3519, 3520, 5, 60, 0, 0, 3520, 547, 1, 0, 0, 0, 3521, 3522, 5, 62, 0, 0, 3522, 549, 1, 0, 0, 0, 3523, 3524, 5, 38, 0, 0, 3524, 551, 1, 0, 0, 0, 3525, 3526, 5, 124, 0, 0, 3526, 553, 1, 0, 0, 0, 3527, 3528, 5, 94, 0, 0, 3528, 555, 1, 0, 0, 0, 3529, 3530, 5, 63, 0, 0, 3530, 557, 1, 0, 0, 0, 3531, 3532, 5, 61, 0, 0, 3532, 559, 1, 0, 0, 0, 3533, 3537, 5, 35, 0, 0, 3534, 3536, 7, 11, 0, 0, 3535, 3534, 1, 0, 0, 0, 3536, 3539, 1, 0, 0, 0, 3537, 3535, 1, 0, 0, 0, 3537, 3538, 1, 0, 0, 0, 3538, 561, 1, 0, 0, 0, 3539, 3537, 1, 0, 0, 0, 3540, 3583, 3, 560, 277, 0, 3541, 3542, 5, 100, 0, 0, 3542, 3543, 5, 101, 0, 0, 3543, 3544, 5, 102, 0, 0, 3544, 3545, 5, 105, 0, 0, 3545, 3546, 5, 110, 0, 0, 3546, 3584, 5, 101, 0, 0, 3547, 3548, 5, 117, 0, 0, 3548, 3549, 5, 110, 0, 0, 3549, 3550, 5, 100, 0, 0, 3550, 3551, 5, 101, 0, 0, 3551, 3584, 5, 102, 0, 0, 3552, 3553, 5, 105, 0, 0, 3553, 3584, 5, 102, 0, 0, 3554, 3555, 5, 105, 0, 0, 3555, 3556, 5, 102, 0, 0, 3556, 3557, 5, 100, 0, 0, 3557, 3558, 5, 101, 0, 0, 3558, 3584, 5, 102, 0, 0, 3559, 3560, 5, 105, 0, 0, 3560, 3561, 5, 102, 0, 0, 3561, 3562, 5, 110, 0, 0, 3562, 3563, 5, 100, 0, 0, 3563, 3564, 5, 101, 0, 0, 3564, 3584, 5, 102, 0, 0, 3565, 3566, 5, 101, 0, 0, 3566, 3567, 5, 108, 0, 0, 3567, 3568, 5, 115, 0, 0, 3568, 3584, 5, 101, 0, 0, 3569, 3570, 5, 101, 0, 0, 3570, 3571, 5, 108, 0, 0, 3571, 3572, 5, 105, 0, 0, 3572, 3584, 5, 102, 0, 0, 3573, 3574, 5, 101, 0, 0, 3574, 3575, 5, 110, 0, 0, 3575, 3576, 5, 100, 0, 0, 3576, 3577, 5, 105, 0, 0, 3577, 3584, 5, 102, 0, 0, 3578, 3579, 5, 101, 0, 0, 3579, 3580, 5, 114, 0, 0, 3580, 3581, 5, 114, 0, 0, 3581, 3582, 5, 111, 0, 0, 3582, 3584, 5, 114, 0, 0, 3583, 3541, 1, 0, 0, 0, 3583, 3547, 1, 0, 0, 0, 3583, 3552, 1, 0, 0, 0, 3583, 3554, 1, 0, 0, 0, 3583, 3559, 1, 0, 0, 0, 3583, 3565, 1, 0, 0, 0, 3583, 3569, 1, 0, 0, 0, 3583, 3573, 1, 0, 0, 0, 3583, 3578, 1, 0, 0, 0, 3584, 3585, 1, 0, 0, 0, 3585, 3586, 6, 278, 0, 0, 3586, 3587, 6, 278, 1, 0, 3587, 563, 1, 0, 0, 0, 3588, 3593, 3, 560, 277, 0, 3589, 3592, 3, 18, 6, 0, 3590, 3592, 3, 24, 9, 0, 3591, 3589, 1, 0, 0, 0, 3591, 3590, 1, 0, 0, 0, 3592, 3595, 1, 0, 0, 0, 3593, 3591, 1, 0, 0, 0, 3593, 3594, 1, 0, 0, 0, 3594, 3596, 1, 0, 0, 0, 3595, 3593, 1, 0, 0, 0, 3596, 3597, 3, 20, 7, 0, 3597, 3598, 1, 0, 0, 0, 3598, 3599, 6, 279, 0, 0, 3599, 565, 1, 0, 0, 0, 3600, 3601, 5, 35, 0, 0, 3601, 3602, 5, 108, 0, 0, 3602, 3603, 5, 105, 0, 0, 3603, 3604, 5, 110, 0, 0, 3604, 3605, 5, 101, 0, 0, 3605, 3606, 1, 0, 0, 0, 3606, 3608, 3, 18, 6, 0, 3607, 3609, 3, 12, 3, 0, 3608, 3607, 1, 0, 0, 0, 3609, 3610, 1, 0, 0, 0, 3610, 3608, 1, 0, 0, 0, 3610, 3611, 1, 0, 0, 0, 3611, 3618, 1, 0, 0, 0, 3612, 3614, 3, 18, 6, 0, 3613, 3615, 3, 12, 3, 0, 3614, 3613, 1, 0, 0, 0, 3615, 3616, 1, 0, 0, 0, 3616, 3614, 1, 0, 0, 0, 3616, 3617, 1, 0, 0, 0, 3617, 3619, 1, 0, 0, 0, 3618, 3612, 1, 0, 0, 0, 3618, 3619, 1, 0, 0, 0, 3619, 3624, 1, 0, 0, 0, 3620, 3623, 3, 20, 7, 0, 3621, 3623, 3, 18, 6, 0, 3622, 3620, 1, 0, 0, 0, 3622, 3621, 1, 0, 0, 0, 3623, 3626, 1, 0, 0, 0, 3624, 3622, 1, 0, 0, 0, 3624, 3625, 1, 0, 0, 0, 3625, 3627, 1, 0, 0, 0, 3626, 3624, 1, 0, 0, 0, 3627, 3628, 3, 20, 7, 0, 3628, 3629, 1, 0, 0, 0, 3629, 3630, 6, 280, 0, 0, 3630, 567, 1, 0, 0, 0, 3631, 3632, 5, 35, 0, 0, 3632, 3633, 1, 0, 0, 0, 3633, 3634, 6, 281, 2, 0, 3634, 569, 1, 0, 0, 0, 3635, 3636, 3, 16, 5, 0, 3636, 571, 1, 0, 0, 0, 3637, 3638, 5, 47, 0, 0, 3638, 3639, 5, 47, 0, 0, 3639, 3643, 1, 0, 0, 0, 3640, 3642, 3, 22, 8, 0, 3641, 3640, 1, 0, 0, 0, 3642, 3645, 1, 0, 0, 0, 3643, 3641, 1, 0, 0, 0, 3643, 3644, 1, 0, 0, 0, 3644, 573, 1, 0, 0, 0, 3645, 3643, 1, 0, 0, 0, 3646, 3647, 5, 47, 0, 0, 3647, 3648, 5, 42, 0, 0, 3648, 3652, 1, 0, 0, 0, 3649, 3651, 9, 0, 0, 0, 3650, 3649, 1, 0, 0, 0, 3651, 3654, 1, 0, 0, 0, 3652, 3653, 1, 0, 0, 0, 3652, 3650, 1, 0, 0, 0, 3653, 3655, 1, 0, 0, 0, 3654, 3652, 1, 0, 0, 0, 3655, 3656, 5, 42, 0, 0, 3656, 3657, 5, 47, 0, 0, 3657, 575, 1, 0, 0, 0, 3658, 3659, 3, 24, 9, 0, 3659, 3660, 1, 0, 0, 0, 3660, 3661, 6, 285, 3, 0, 3661, 577, 1, 0, 0, 0, 3662, 3663, 3, 572, 283, 0, 3663, 3664, 3, 20, 7, 0, 3664, 3665, 1, 0, 0, 0, 3665, 3666, 6, 286, 4, 0, 3666, 579, 1, 0, 0, 0, 3667, 3668, 3, 574, 284, 0, 3668, 3669, 1, 0, 0, 0, 3669, 3670, 6, 287, 4, 0, 3670, 581, 1, 0, 0, 0, 3671, 3672, 3, 18, 6, 0, 3672, 3673, 1, 0, 0, 0, 3673, 3674, 6, 288, 3, 0, 3674, 583, 1, 0, 0, 0, 3675, 3676, 3, 20, 7, 0, 3676, 3677, 1, 0, 0, 0, 3677, 3678, 6, 289, 3, 0, 3678, 585, 1, 0, 0, 0, 3679, 3680, 5, 101, 0, 0, 3680, 3681, 5, 120, 0, 0, 3681, 3682, 5, 116, 0, 0, 3682, 3683, 5, 101, 0, 0, 3683, 3684, 5, 110, 0, 0, 3684, 3685, 5, 115, 0, 0, 3685, 3686, 5, 105, 0, 0, 3686, 3687, 5, 111, 0, 0, 3687, 3688, 5, 110, 0, 0, 3688, 587, 1, 0, 0, 0, 3689, 3690, 5, 118, 0, 0, 3690, 3691, 5, 101, 0, 0, 3691, 3692, 5, 114, 0, 0, 3692, 3693, 5, 115, 0, 0, 3693, 3694, 5, 105, 0, 0, 3694, 3695, 5, 111, 0, 0, 3695, 3696, 5, 110, 0, 0, 3696, 589, 1, 0, 0, 0, 3697, 3698, 5, 99, 0, 0, 3698, 3699, 5, 117, 0, 0, 3699, 3700, 5, 115, 0, 0, 3700, 3701, 5, 116, 0, 0, 3701, 3702, 5, 111, 0, 0, 3702, 3703, 5, 109, 0, 0, 3703, 3704, 1, 0, 0, 0, 3704, 3705, 4, 292, 30, 0, 3705, 3706, 1, 0, 0, 0, 3706, 3707, 6, 292, 5, 0, 3707, 591, 1, 0, 0, 0, 3708, 3709, 5, 105, 0, 0, 3709, 3710, 5, 110, 0, 0, 3710, 3711, 5, 99, 0, 0, 3711, 3712, 5, 108, 0, 0, 3712, 3713, 5, 117, 0, 0, 3713, 3714, 5, 100, 0, 0, 3714, 3715, 5, 101, 0, 0, 3715, 3716, 1, 0, 0, 0, 3716, 3717, 4, 293, 31, 0, 3717, 593, 1, 0, 0, 0, 3718, 3719, 5, 112, 0, 0, 3719, 3720, 5, 114, 0, 0, 3720, 3721, 5, 97, 0, 0, 3721, 3722, 5, 103, 0, 0, 3722, 3723, 5, 109, 0, 0, 3723, 3724, 5, 97, 0, 0, 3724, 595, 1, 0, 0, 0, 3725, 3726, 5, 100, 0, 0, 3726, 3727, 5, 101, 0, 0, 3727, 3728, 5, 98, 0, 0, 3728, 3729, 5, 117, 0, 0, 3729, 3730, 5, 103, 0, 0, 3730, 597, 1, 0, 0, 0, 3731, 3732, 5, 111, 0, 0, 3732, 3733, 5, 112, 0, 0, 3733, 3734, 5, 116, 0, 0, 3734, 3735, 5, 105, 0, 0, 3735, 3736, 5, 109, 0, 0, 3736, 3737, 5, 105, 0, 0, 3737, 3738, 5, 122, 0, 0, 3738, 3739, 5, 101, 0, 0, 3739, 599, 1, 0, 0, 0, 3740, 3741, 5, 105, 0, 0, 3741, 3742, 5, 110, 0, 0, 3742, 3743, 5, 118, 0, 0, 3743, 3744, 5, 97, 0, 0, 3744, 3745, 5, 114, 0, 0, 3745, 3746, 5, 105, 0, 0, 3746, 3747, 5, 97, 0, 0, 3747, 3748, 5, 110, 0, 0, 3748, 3749, 5, 116, 0, 0, 3749, 601, 1, 0, 0, 0, 3750, 3751, 5, 111, 0, 0, 3751, 3752, 5, 110, 0, 0, 3752, 603, 1, 0, 0, 0, 3753, 3754, 5, 111, 0, 0, 3754, 3755, 5, 102, 0, 0, 3755, 3756, 5, 102, 0, 0, 3756, 605, 1, 0, 0, 0, 3757, 3758, 5, 97, 0, 0, 3758, 3759, 5, 108, 0, 0, 3759, 3760, 5, 108, 0, 0, 3760, 607, 1, 0, 0, 0, 3761, 3762, 5, 114, 0, 0, 3762, 3763, 5, 101, 0, 0, 3763, 3764, 5, 113, 0, 0, 3764, 3765, 5, 117, 0, 0, 3765, 3766, 5, 105, 0, 0, 3766, 3767, 5, 114, 0, 0, 3767, 3768, 5, 101, 0, 0, 3768, 609, 1, 0, 0, 0, 3769, 3770, 5, 101, 0, 0, 3770, 3771, 5, 110, 0, 0, 3771, 3772, 5, 97, 0, 0, 3772, 3773, 5, 98, 0, 0, 3773, 3774, 5, 108, 0, 0, 3774, 3775, 5, 101, 0, 0, 3775, 611, 1, 0, 0, 0, 3776, 3777, 5, 119, 0, 0, 3777, 3778, 5, 97, 0, 0, 3778, 3779, 5, 114, 0, 0, 3779, 3780, 5, 110, 0, 0, 3780, 613, 1, 0, 0, 0, 3781, 3782, 5, 100, 0, 0, 3782, 3783, 5, 105, 0, 0, 3783, 3784, 5, 115, 0, 0, 3784, 3785, 5, 97, 0, 0, 3785, 3786, 5, 98, 0, 0, 3786, 3787, 5, 108, 0, 0, 3787, 3788, 5, 101, 0, 0, 3788, 615, 1, 0, 0, 0, 3789, 3790, 5, 58, 0, 0, 3790, 617, 1, 0, 0, 0, 3791, 3792, 5, 40, 0, 0, 3792, 619, 1, 0, 0, 0, 3793, 3794, 5, 41, 0, 0, 3794, 621, 1, 0, 0, 0, 3795, 3796, 5, 83, 0, 0, 3796, 3797, 5, 84, 0, 0, 3797, 3798, 5, 68, 0, 0, 3798, 3799, 5, 71, 0, 0, 3799, 3800, 5, 76, 0, 0, 3800, 623, 1, 0, 0, 0, 3801, 3802, 5, 99, 0, 0, 3802, 3803, 5, 111, 0, 0, 3803, 3804, 5, 114, 0, 0, 3804, 3805, 5, 101, 0, 0, 3805, 625, 1, 0, 0, 0, 3806, 3807, 5, 99, 0, 0, 3807, 3808, 5, 111, 0, 0, 3808, 3809, 5, 109, 0, 0, 3809, 3810, 5, 112, 0, 0, 3810, 3811, 5, 97, 0, 0, 3811, 3812, 5, 116, 0, 0, 3812, 3813, 5, 105, 0, 0, 3813, 3814, 5, 98, 0, 0, 3814, 3815, 5, 105, 0, 0, 3815, 3816, 5, 108, 0, 0, 3816, 3817, 5, 105, 0, 0, 3817, 3818, 5, 116, 0, 0, 3818, 3819, 5, 121, 0, 0, 3819, 627, 1, 0, 0, 0, 3820, 3821, 5, 101, 0, 0, 3821, 3822, 5, 115, 0, 0, 3822, 629, 1, 0, 0, 0, 3823, 3824, 5, 49, 0, 0, 3824, 3825, 5, 49, 0, 0, 3825, 3826, 5, 48, 0, 0, 3826, 631, 1, 0, 0, 0, 3827, 3828, 5, 49, 0, 0, 3828, 3829, 5, 50, 0, 0, 3829, 3830, 5, 48, 0, 0, 3830, 633, 1, 0, 0, 0, 3831, 3832, 5, 49, 0, 0, 3832, 3833, 5, 48, 0, 0, 3833, 3834, 5, 48, 0, 0, 3834, 635, 1, 0, 0, 0, 3835, 3836, 5, 49, 0, 0, 3836, 3837, 5, 51, 0, 0, 3837, 3838, 5, 48, 0, 0, 3838, 637, 1, 0, 0, 0, 3839, 3840, 5, 49, 0, 0, 3840, 3841, 5, 52, 0, 0, 3841, 3842, 5, 48, 0, 0, 3842, 639, 1, 0, 0, 0, 3843, 3844, 5, 49, 0, 0, 3844, 3845, 5, 53, 0, 0, 3845, 3846, 5, 48, 0, 0, 3846, 641, 1, 0, 0, 0, 3847, 3848, 5, 51, 0, 0, 3848, 3849, 5, 51, 0, 0, 3849, 3850, 5, 48, 0, 0, 3850, 643, 1, 0, 0, 0, 3851, 3852, 5, 51, 0, 0, 3852, 3853, 5, 48, 0, 0, 3853, 3854, 5, 48, 0, 0, 3854, 645, 1, 0, 0, 0, 3855, 3856, 5, 51, 0, 0, 3856, 3857, 5, 49, 0, 0, 3857, 3858, 5, 48, 0, 0, 3858, 647, 1, 0, 0, 0, 3859, 3860, 5, 51, 0, 0, 3860, 3861, 5, 50, 0, 0, 3861, 3862, 5, 48, 0, 0, 3862, 649, 1, 0, 0, 0, 3863, 3864, 5, 52, 0, 0, 3864, 3865, 5, 48, 0, 0, 3865, 3866, 5, 48, 0, 0, 3866, 651, 1, 0, 0, 0, 3867, 3868, 5, 52, 0, 0, 3868, 3869, 5, 49, 0, 0, 3869, 3870, 5, 48, 0, 0, 3870, 653, 1, 0, 0, 0, 3871, 3872, 5, 52, 0, 0, 3872, 3873, 5, 50, 0, 0, 3873, 3874, 5, 48, 0, 0, 3874, 655, 1, 0, 0, 0, 3875, 3876, 5, 52, 0, 0, 3876, 3877, 5, 51, 0, 0, 3877, 3878, 5, 48, 0, 0, 3878, 657, 1, 0, 0, 0, 3879, 3880, 5, 52, 0, 0, 3880, 3881, 5, 52, 0, 0, 3881, 3882, 5, 48, 0, 0, 3882, 659, 1, 0, 0, 0, 3883, 3884, 5, 52, 0, 0, 3884, 3885, 5, 53, 0, 0, 3885, 3886, 5, 48, 0, 0, 3886, 661, 1, 0, 0, 0, 3887, 3888, 5, 52, 0, 0, 3888, 3889, 5, 54, 0, 0, 3889, 3890, 5, 48, 0, 0, 3890, 663, 1, 0, 0, 0, 3891, 3892, 5, 34, 0, 0, 3892, 3893, 4, 329, 32, 0, 3893, 3894, 1, 0, 0, 0, 3894, 3895, 6, 329, 6, 0, 3895, 665, 1, 0, 0, 0, 3896, 3897, 5, 60, 0, 0, 3897, 3898, 4, 330, 33, 0, 3898, 3899, 1, 0, 0, 0, 3899, 3900, 6, 330, 7, 0, 3900, 667, 1, 0, 0, 0, 3901, 3902, 3, 142, 68, 0, 3902, 669, 1, 0, 0, 0, 3903, 3904, 3, 16, 5, 0, 3904, 671, 1, 0, 0, 0, 3905, 3906, 3, 24, 9, 0, 3906, 3907, 1, 0, 0, 0, 3907, 3908, 6, 333, 3, 0, 3908, 673, 1, 0, 0, 0, 3909, 3910, 3, 572, 283, 0, 3910, 3911, 1, 0, 0, 0, 3911, 3912, 6, 334, 4, 0, 3912, 675, 1, 0, 0, 0, 3913, 3914, 3, 574, 284, 0, 3914, 3915, 1, 0, 0, 0, 3915, 3916, 6, 335, 4, 0, 3916, 677, 1, 0, 0, 0, 3917, 3918, 3, 20, 7, 0, 3918, 3919, 1, 0, 0, 0, 3919, 3920, 6, 336, 8, 0, 3920, 679, 1, 0, 0, 0, 3921, 3922, 3, 18, 6, 0, 3922, 3923, 1, 0, 0, 0, 3923, 3924, 6, 337, 3, 0, 3924, 681, 1, 0, 0, 0, 3925, 3927, 8, 12, 0, 0, 3926, 3925, 1, 0, 0, 0, 3927, 3928, 1, 0, 0, 0, 3928, 3926, 1, 0, 0, 0, 3928, 3929, 1, 0, 0, 0, 3929, 683, 1, 0, 0, 0, 3930, 3931, 5, 34, 0, 0, 3931, 3932, 1, 0, 0, 0, 3932, 3933, 6, 339, 8, 0, 3933, 685, 1, 0, 0, 0, 3934, 3936, 8, 13, 0, 0, 3935, 3934, 1, 0, 0, 0, 3936, 3937, 1, 0, 0, 0, 3937, 3935, 1, 0, 0, 0, 3937, 3938, 1, 0, 0, 0, 3938, 687, 1, 0, 0, 0, 3939, 3940, 5, 62, 0, 0, 3940, 3941, 1, 0, 0, 0, 3941, 3942, 6, 341, 8, 0, 3942, 689, 1, 0, 0, 0, 3943, 3944, 3, 572, 283, 0, 3944, 3945, 1, 0, 0, 0, 3945, 3946, 6, 342, 4, 0, 3946, 691, 1, 0, 0, 0, 3947, 3948, 3, 574, 284, 0, 3948, 3949, 1, 0, 0, 0, 3949, 3950, 6, 343, 4, 0, 3950, 693, 1, 0, 0, 0, 3951, 3952, 3, 20, 7, 0, 3952, 3953, 1, 0, 0, 0, 3953, 3954, 6, 344, 8, 0, 3954, 3955, 6, 344, 8, 0, 3955, 695, 1, 0, 0, 0, 3956, 3957, 3, 18, 6, 0, 3957, 3958, 1, 0, 0, 0, 3958, 3959, 6, 345, 3, 0, 3959, 697, 1, 0, 0, 0, 3960, 3964, 8, 14, 0, 0, 3961, 3963, 3, 22, 8, 0, 3962, 3961, 1, 0, 0, 0, 3963, 3966, 1, 0, 0, 0, 3964, 3962, 1, 0, 0, 0, 3964, 3965, 1, 0, 0, 0, 3965, 699, 1, 0, 0, 0, 3966, 3964, 1, 0, 0, 0, 3967, 3968, 3, 24, 9, 0, 3968, 3969, 1, 0, 0, 0, 3969, 3970, 6, 347, 3, 0, 3970, 701, 1, 0, 0, 0, 3971, 3972, 3, 572, 283, 0, 3972, 3973, 1, 0, 0, 0, 3973, 3974, 6, 348, 4, 0, 3974, 703, 1, 0, 0, 0, 3975, 3976, 3, 574, 284, 0, 3976, 3977, 1, 0, 0, 0, 3977, 3978, 6, 349, 4, 0, 3978, 705, 1, 0, 0, 0, 3979, 3980, 3, 20, 7, 0, 3980, 3981, 1, 0, 0, 0, 3981, 3982, 6, 350, 0, 0, 3982, 3983, 6, 350, 8, 0, 3983, 707, 1, 0, 0, 0, 3984, 3986, 3, 22, 8, 0, 3985, 3984, 1, 0, 0, 0, 3986, 3989, 1, 0, 0, 0, 3987, 3985, 1, 0, 0, 0, 3987, 3988, 1, 0, 0, 0, 3988, 3990, 1, 0, 0, 0, 3989, 3987, 1, 0, 0, 0, 3990, 3991, 8, 15, 0, 0, 3991, 3992, 1, 0, 0, 0, 3992, 3993, 6, 351, 0, 0, 3993, 709, 1, 0, 0, 0, 78, 0, 1, 2, 3, 4, 5, 715, 718, 724, 731, 733, 740, 746, 749, 755, 757, 761, 766, 769, 774, 776, 782, 785, 1376, 1413, 1428, 1585, 1599, 1613, 1627, 1641, 1655, 1669, 1683, 1800, 1848, 1896, 1912, 1925, 1938, 1951, 1979, 1996, 2013, 2030, 2058, 2075, 2092, 2109, 2137, 2154, 2168, 2182, 2196, 2226, 2244, 2262, 2280, 2310, 2328, 2346, 2364, 2394, 3537, 3583, 3591, 3593, 3610, 3616, 3618, 3622, 3624, 3643, 3652, 3928, 3937, 3964, 3987, 9, 0, 4, 0, 5, 5, 0, 5, 1, 0, 0, 2, 0, 0, 3, 0, 5, 4, 0, 5, 2, 0, 5, 3, 0, 4, 0, 0] \ No newline at end of file diff --git a/src/main/java/io/github/douira/glsl_transformer/GLSLLexer.java b/src/main/java/io/github/douira/glsl_transformer/GLSLLexer.java index 39a0a4635a..2a1702b925 100644 --- a/src/main/java/io/github/douira/glsl_transformer/GLSLLexer.java +++ b/src/main/java/io/github/douira/glsl_transformer/GLSLLexer.java @@ -2,15 +2,13 @@ package io.github.douira.glsl_transformer; import io.github.douira.glsl_transformer.parser.VersionedGLSLLexer; - -import repack.antlr.v4.runtime.Lexer; -import repack.antlr.v4.runtime.CharStream; -import repack.antlr.v4.runtime.Token; -import repack.antlr.v4.runtime.TokenStream; import repack.antlr.v4.runtime.*; -import repack.antlr.v4.runtime.atn.*; +import repack.antlr.v4.runtime.atn.ATN; +import repack.antlr.v4.runtime.atn.ATNDeserializer; +import repack.antlr.v4.runtime.atn.LexerATNSimulator; +import repack.antlr.v4.runtime.atn.PredictionContextCache; import repack.antlr.v4.runtime.dfa.DFA; -import repack.antlr.v4.runtime.misc.*; +import repack.antlr.v4.runtime.misc.Utils; @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"}) public class GLSLLexer extends VersionedGLSLLexer { @@ -20,72 +18,72 @@ public class GLSLLexer extends VersionedGLSLLexer { protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); public static final int - COLON=1, UNIFORM=2, BUFFER=3, IN=4, OUT=5, INOUT=6, HIGHP=7, MEDIUMP=8, - LOWP=9, PRECISION=10, CONST=11, PRECISE=12, INVARIANT=13, SMOOTH=14, FLAT=15, - CENTROID=16, ATTRIBUTE=17, VOLATILE=18, VARYING=19, SHARED=20, LAYOUT=21, - DOT_LENGTH_METHOD_CALL=22, NOPERSPECTIVE=23, SAMPLE=24, PATCH=25, COHERENT=26, - RESTRICT=27, READONLY=28, WRITEONLY=29, SUBROUTINE=30, DEVICECOHERENT=31, - QUEUEFAMILYCOHERENT=32, WORKGROUPCOHERENT=33, SUBGROUPCOHERENT=34, NONPRIVATE=35, - RAY_PAYLOAD_EXT=36, RAY_PAYLOAD_IN_EXT=37, HIT_ATTRIBUTE_EXT=38, CALLABLE_DATA_EXT=39, - CALLABLE_DATA_IN_EXT=40, IGNORE_INTERSECTION_EXT=41, TERMINATE_RAY_EXT=42, - ACCELERATION_STRUCTURE_EXT=43, ATOMIC_UINT=44, STRUCT=45, IF=46, ELSE=47, - SWITCH=48, CASE=49, DEFAULT=50, WHILE=51, DO=52, FOR=53, CONTINUE=54, - BREAK=55, RETURN=56, DISCARD=57, DEMOTE=58, UINT16CONSTANT=59, INT16CONSTANT=60, - UINT32CONSTANT=61, INT32CONSTANT=62, UINT64CONSTANT=63, INT64CONSTANT=64, - FLOAT16CONSTANT=65, FLOAT32CONSTANT=66, FLOAT64CONSTANT=67, BOOLCONSTANT=68, - BOOL=69, BVEC2=70, BVEC3=71, BVEC4=72, INT8=73, I8VEC2=74, I8VEC3=75, - I8VEC4=76, UINT8=77, U8VEC2=78, U8VEC3=79, U8VEC4=80, INT16=81, I16VEC2=82, - I16VEC3=83, I16VEC4=84, UINT16=85, U16VEC2=86, U16VEC3=87, U16VEC4=88, - INT32=89, I32VEC2=90, I32VEC3=91, I32VEC4=92, UINT32=93, U32VEC2=94, U32VEC3=95, - U32VEC4=96, INT64=97, I64VEC2=98, I64VEC3=99, I64VEC4=100, UINT64=101, - U64VEC2=102, U64VEC3=103, U64VEC4=104, FLOAT16=105, F16VEC2=106, F16VEC3=107, - F16VEC4=108, F16MAT2X2=109, F16MAT2X3=110, F16MAT2X4=111, F16MAT3X2=112, - F16MAT3X3=113, F16MAT3X4=114, F16MAT4X2=115, F16MAT4X3=116, F16MAT4X4=117, - FLOAT32=118, F32VEC2=119, F32VEC3=120, F32VEC4=121, F32MAT2X2=122, F32MAT2X3=123, - F32MAT2X4=124, F32MAT3X2=125, F32MAT3X3=126, F32MAT3X4=127, F32MAT4X2=128, - F32MAT4X3=129, F32MAT4X4=130, FLOAT64=131, F64VEC2=132, F64VEC3=133, F64VEC4=134, - F64MAT2X2=135, F64MAT2X3=136, F64MAT2X4=137, F64MAT3X2=138, F64MAT3X3=139, - F64MAT3X4=140, F64MAT4X2=141, F64MAT4X3=142, F64MAT4X4=143, IMAGE1D=144, - IMAGE2D=145, IMAGE3D=146, UIMAGE1D=147, UIMAGE2D=148, UIMAGE3D=149, IIMAGE1D=150, - IIMAGE2D=151, IIMAGE3D=152, SAMPLER1D=153, SAMPLER2D=154, SAMPLER3D=155, - SAMPLER2DRECT=156, SAMPLER1DSHADOW=157, SAMPLER2DSHADOW=158, SAMPLER2DRECTSHADOW=159, - SAMPLER1DARRAY=160, SAMPLER2DARRAY=161, SAMPLER1DARRAYSHADOW=162, SAMPLER2DARRAYSHADOW=163, - ISAMPLER1D=164, ISAMPLER2D=165, ISAMPLER2DRECT=166, ISAMPLER3D=167, ISAMPLER1DARRAY=168, - ISAMPLER2DARRAY=169, USAMPLER1D=170, USAMPLER2D=171, USAMPLER2DRECT=172, - USAMPLER3D=173, USAMPLER1DARRAY=174, USAMPLER2DARRAY=175, SAMPLER2DMS=176, - ISAMPLER2DMS=177, USAMPLER2DMS=178, SAMPLER2DMSARRAY=179, ISAMPLER2DMSARRAY=180, - USAMPLER2DMSARRAY=181, IMAGE2DRECT=182, IMAGE1DARRAY=183, IMAGE2DARRAY=184, - IMAGE2DMS=185, IMAGE2DMSARRAY=186, IIMAGE2DRECT=187, IIMAGE1DARRAY=188, - IIMAGE2DARRAY=189, IIMAGE2DMS=190, IIMAGE2DMSARRAY=191, UIMAGE2DRECT=192, - UIMAGE1DARRAY=193, UIMAGE2DARRAY=194, UIMAGE2DMS=195, UIMAGE2DMSARRAY=196, - SAMPLERCUBESHADOW=197, SAMPLERCUBEARRAYSHADOW=198, SAMPLERCUBE=199, ISAMPLERCUBE=200, - USAMPLERCUBE=201, SAMPLERBUFFER=202, ISAMPLERBUFFER=203, USAMPLERBUFFER=204, - SAMPLERCUBEARRAY=205, ISAMPLERCUBEARRAY=206, USAMPLERCUBEARRAY=207, IMAGECUBE=208, - UIMAGECUBE=209, IIMAGECUBE=210, IMAGEBUFFER=211, IIMAGEBUFFER=212, UIMAGEBUFFER=213, - IMAGECUBEARRAY=214, IIMAGECUBEARRAY=215, UIMAGECUBEARRAY=216, INC_OP=217, - DEC_OP=218, VOID=219, LEFT_OP=220, RIGHT_OP=221, LE_OP=222, GE_OP=223, - EQ_OP=224, NE_OP=225, LOGICAL_AND_OP=226, LOGICAL_XOR_OP=227, LOGICAL_OR_OP=228, - MUL_ASSIGN=229, DIV_ASSIGN=230, MOD_ASSIGN=231, ADD_ASSIGN=232, SUB_ASSIGN=233, - LEFT_ASSIGN=234, RIGHT_ASSIGN=235, AND_ASSIGN=236, XOR_ASSIGN=237, OR_ASSIGN=238, - LPAREN=239, RPAREN=240, LBRACE=241, RBRACE=242, SEMICOLON=243, LBRACKET=244, - RBRACKET=245, COMMA=246, DOT=247, PLUS_OP=248, MINUS_OP=249, LOGICAL_NOT_OP=250, - BITWISE_NEG_OP=251, TIMES_OP=252, DIV_OP=253, MOD_OP=254, LT_OP=255, GT_OP=256, - BITWISE_AND_OP=257, BITWISE_OR_OP=258, BITWISE_XOR_OP=259, QUERY_OP=260, - ASSIGN_OP=261, PP_ENTER_MODE=262, PP_EMPTY=263, NR_LINE=264, NR=265, IDENTIFIER=266, - LINE_CONTINUE=267, LINE_COMMENT=268, BLOCK_COMMENT=269, WS=270, EOL=271, - NR_EXTENSION=272, NR_VERSION=273, NR_CUSTOM=274, NR_INCLUDE=275, NR_PRAGMA=276, - NR_PRAGMA_DEBUG=277, NR_PRAGMA_OPTIMIZE=278, NR_PRAGMA_INVARIANT=279, - NR_ON=280, NR_OFF=281, NR_ALL=282, NR_REQUIRE=283, NR_ENABLE=284, NR_WARN=285, - NR_DISABLE=286, NR_COLON=287, NR_LPAREN=288, NR_RPAREN=289, NR_STDGL=290, - NR_CORE=291, NR_COMPATIBILITY=292, NR_ES=293, NR_GLSL_110=294, NR_GLSL_120=295, - NR_GLSLES_100=296, NR_GLSL_130=297, NR_GLSL_140=298, NR_GLSL_150=299, - NR_GLSL_330=300, NR_GLSLES_300=301, NR_GLSLES_310=302, NR_GLSLES_320=303, - NR_GLSL_400=304, NR_GLSL_410=305, NR_GLSL_420=306, NR_GLSL_430=307, NR_GLSL_440=308, - NR_GLSL_450=309, NR_GLSL_460=310, NR_STRING_START=311, NR_STRING_START_ANGLE=312, - NR_INTCONSTANT=313, NR_IDENTIFIER=314, NR_LINE_CONTINUE=315, NR_LINE_COMMENT=316, - NR_BLOCK_COMMENT=317, NR_EOL=318, NR_WS=319, S_CONTENT=320, S_STRING_END=321, - S_CONTENT_ANGLE=322, S_STRING_END_ANGLE=323, C_LINE_COMMENT=324, C_BLOCK_COMMENT=325, - C_EOL=326, C_WS=327, C_CONTENT=328, PP_LINE_CONTINUE=329, PP_LINE_COMMENT=330, + COLON=1, UNIFORM=2, BUFFER=3, IN=4, OUT=5, INOUT=6, HIGHP=7, MEDIUMP=8, + LOWP=9, PRECISION=10, CONST=11, PRECISE=12, INVARIANT=13, SMOOTH=14, FLAT=15, + CENTROID=16, ATTRIBUTE=17, VOLATILE=18, VARYING=19, SHARED=20, LAYOUT=21, + DOT_LENGTH_METHOD_CALL=22, NOPERSPECTIVE=23, SAMPLE=24, PATCH=25, COHERENT=26, + RESTRICT=27, READONLY=28, WRITEONLY=29, SUBROUTINE=30, DEVICECOHERENT=31, + QUEUEFAMILYCOHERENT=32, WORKGROUPCOHERENT=33, SUBGROUPCOHERENT=34, NONPRIVATE=35, + RAY_PAYLOAD_EXT=36, RAY_PAYLOAD_IN_EXT=37, HIT_ATTRIBUTE_EXT=38, CALLABLE_DATA_EXT=39, + CALLABLE_DATA_IN_EXT=40, IGNORE_INTERSECTION_EXT=41, TERMINATE_RAY_EXT=42, + ACCELERATION_STRUCTURE_EXT=43, ATOMIC_UINT=44, STRUCT=45, IF=46, ELSE=47, + SWITCH=48, CASE=49, DEFAULT=50, WHILE=51, DO=52, FOR=53, CONTINUE=54, + BREAK=55, RETURN=56, DISCARD=57, DEMOTE=58, UINT16CONSTANT=59, INT16CONSTANT=60, + UINT32CONSTANT=61, INT32CONSTANT=62, UINT64CONSTANT=63, INT64CONSTANT=64, + FLOAT16CONSTANT=65, FLOAT32CONSTANT=66, FLOAT64CONSTANT=67, BOOLCONSTANT=68, + BOOL=69, BVEC2=70, BVEC3=71, BVEC4=72, INT8=73, I8VEC2=74, I8VEC3=75, + I8VEC4=76, UINT8=77, U8VEC2=78, U8VEC3=79, U8VEC4=80, INT16=81, I16VEC2=82, + I16VEC3=83, I16VEC4=84, UINT16=85, U16VEC2=86, U16VEC3=87, U16VEC4=88, + INT32=89, I32VEC2=90, I32VEC3=91, I32VEC4=92, UINT32=93, U32VEC2=94, U32VEC3=95, + U32VEC4=96, INT64=97, I64VEC2=98, I64VEC3=99, I64VEC4=100, UINT64=101, + U64VEC2=102, U64VEC3=103, U64VEC4=104, FLOAT16=105, F16VEC2=106, F16VEC3=107, + F16VEC4=108, F16MAT2X2=109, F16MAT2X3=110, F16MAT2X4=111, F16MAT3X2=112, + F16MAT3X3=113, F16MAT3X4=114, F16MAT4X2=115, F16MAT4X3=116, F16MAT4X4=117, + FLOAT32=118, F32VEC2=119, F32VEC3=120, F32VEC4=121, F32MAT2X2=122, F32MAT2X3=123, + F32MAT2X4=124, F32MAT3X2=125, F32MAT3X3=126, F32MAT3X4=127, F32MAT4X2=128, + F32MAT4X3=129, F32MAT4X4=130, FLOAT64=131, F64VEC2=132, F64VEC3=133, F64VEC4=134, + F64MAT2X2=135, F64MAT2X3=136, F64MAT2X4=137, F64MAT3X2=138, F64MAT3X3=139, + F64MAT3X4=140, F64MAT4X2=141, F64MAT4X3=142, F64MAT4X4=143, IMAGE1D=144, + IMAGE2D=145, IMAGE3D=146, UIMAGE1D=147, UIMAGE2D=148, UIMAGE3D=149, IIMAGE1D=150, + IIMAGE2D=151, IIMAGE3D=152, SAMPLER1D=153, SAMPLER2D=154, SAMPLER3D=155, + SAMPLER2DRECT=156, SAMPLER1DSHADOW=157, SAMPLER2DSHADOW=158, SAMPLER2DRECTSHADOW=159, + SAMPLER1DARRAY=160, SAMPLER2DARRAY=161, SAMPLER1DARRAYSHADOW=162, SAMPLER2DARRAYSHADOW=163, + ISAMPLER1D=164, ISAMPLER2D=165, ISAMPLER2DRECT=166, ISAMPLER3D=167, ISAMPLER1DARRAY=168, + ISAMPLER2DARRAY=169, USAMPLER1D=170, USAMPLER2D=171, USAMPLER2DRECT=172, + USAMPLER3D=173, USAMPLER1DARRAY=174, USAMPLER2DARRAY=175, SAMPLER2DMS=176, + ISAMPLER2DMS=177, USAMPLER2DMS=178, SAMPLER2DMSARRAY=179, ISAMPLER2DMSARRAY=180, + USAMPLER2DMSARRAY=181, IMAGE2DRECT=182, IMAGE1DARRAY=183, IMAGE2DARRAY=184, + IMAGE2DMS=185, IMAGE2DMSARRAY=186, IIMAGE2DRECT=187, IIMAGE1DARRAY=188, + IIMAGE2DARRAY=189, IIMAGE2DMS=190, IIMAGE2DMSARRAY=191, UIMAGE2DRECT=192, + UIMAGE1DARRAY=193, UIMAGE2DARRAY=194, UIMAGE2DMS=195, UIMAGE2DMSARRAY=196, + SAMPLERCUBESHADOW=197, SAMPLERCUBEARRAYSHADOW=198, SAMPLERCUBE=199, ISAMPLERCUBE=200, + USAMPLERCUBE=201, SAMPLERBUFFER=202, ISAMPLERBUFFER=203, USAMPLERBUFFER=204, + SAMPLERCUBEARRAY=205, ISAMPLERCUBEARRAY=206, USAMPLERCUBEARRAY=207, IMAGECUBE=208, + UIMAGECUBE=209, IIMAGECUBE=210, IMAGEBUFFER=211, IIMAGEBUFFER=212, UIMAGEBUFFER=213, + IMAGECUBEARRAY=214, IIMAGECUBEARRAY=215, UIMAGECUBEARRAY=216, INC_OP=217, + DEC_OP=218, VOID=219, LEFT_OP=220, RIGHT_OP=221, LE_OP=222, GE_OP=223, + EQ_OP=224, NE_OP=225, LOGICAL_AND_OP=226, LOGICAL_XOR_OP=227, LOGICAL_OR_OP=228, + MUL_ASSIGN=229, DIV_ASSIGN=230, MOD_ASSIGN=231, ADD_ASSIGN=232, SUB_ASSIGN=233, + LEFT_ASSIGN=234, RIGHT_ASSIGN=235, AND_ASSIGN=236, XOR_ASSIGN=237, OR_ASSIGN=238, + LPAREN=239, RPAREN=240, LBRACE=241, RBRACE=242, SEMICOLON=243, LBRACKET=244, + RBRACKET=245, COMMA=246, DOT=247, PLUS_OP=248, MINUS_OP=249, LOGICAL_NOT_OP=250, + BITWISE_NEG_OP=251, TIMES_OP=252, DIV_OP=253, MOD_OP=254, LT_OP=255, GT_OP=256, + BITWISE_AND_OP=257, BITWISE_OR_OP=258, BITWISE_XOR_OP=259, QUERY_OP=260, + ASSIGN_OP=261, PP_ENTER_MODE=262, PP_EMPTY=263, NR_LINE=264, NR=265, IDENTIFIER=266, + LINE_CONTINUE=267, LINE_COMMENT=268, BLOCK_COMMENT=269, WS=270, EOL=271, + NR_EXTENSION=272, NR_VERSION=273, NR_CUSTOM=274, NR_INCLUDE=275, NR_PRAGMA=276, + NR_PRAGMA_DEBUG=277, NR_PRAGMA_OPTIMIZE=278, NR_PRAGMA_INVARIANT=279, + NR_ON=280, NR_OFF=281, NR_ALL=282, NR_REQUIRE=283, NR_ENABLE=284, NR_WARN=285, + NR_DISABLE=286, NR_COLON=287, NR_LPAREN=288, NR_RPAREN=289, NR_STDGL=290, + NR_CORE=291, NR_COMPATIBILITY=292, NR_ES=293, NR_GLSL_110=294, NR_GLSL_120=295, + NR_GLSLES_100=296, NR_GLSL_130=297, NR_GLSL_140=298, NR_GLSL_150=299, + NR_GLSL_330=300, NR_GLSLES_300=301, NR_GLSLES_310=302, NR_GLSLES_320=303, + NR_GLSL_400=304, NR_GLSL_410=305, NR_GLSL_420=306, NR_GLSL_430=307, NR_GLSL_440=308, + NR_GLSL_450=309, NR_GLSL_460=310, NR_STRING_START=311, NR_STRING_START_ANGLE=312, + NR_INTCONSTANT=313, NR_IDENTIFIER=314, NR_LINE_CONTINUE=315, NR_LINE_COMMENT=316, + NR_BLOCK_COMMENT=317, NR_EOL=318, NR_WS=319, S_CONTENT=320, S_STRING_END=321, + S_CONTENT_ANGLE=322, S_STRING_END_ANGLE=323, C_LINE_COMMENT=324, C_BLOCK_COMMENT=325, + C_EOL=326, C_WS=327, C_CONTENT=328, PP_LINE_CONTINUE=329, PP_LINE_COMMENT=330, PP_BLOCK_COMMENT=331, PP_EOL=332, PP_CONTENT=333; public static final int WHITESPACE=2, COMMENTS=3, PREPROCESSOR=4; @@ -96,76 +94,76 @@ public class GLSLLexer extends VersionedGLSLLexer { }; public static String[] modeNames = { - "DEFAULT_MODE", "NR_Mode", "String", "StringAngle", "CustomDirective", + "DEFAULT_MODE", "NR_Mode", "String", "StringAngle", "CustomDirective", "Preprocessor" }; private static String[] makeRuleNames() { return new String[] { - "DECIMAL_DIGITS", "OCTAL_DIGITS", "HEX_DIGITS", "DIGIT", "FLOAT_DIGITS", - "IDENTIFIER_frag", "WS_frag", "NEWLINE", "NO_NEWLINE", "LINE_CONTINUE_frag", - "COLON", "UNIFORM", "BUFFER", "IN", "OUT", "INOUT", "HIGHP", "MEDIUMP", - "LOWP", "PRECISION", "CONST", "PRECISE", "INVARIANT", "SMOOTH", "FLAT", - "CENTROID", "ATTRIBUTE", "VOLATILE", "VARYING", "SHARED", "LAYOUT", "DOT_LENGTH_METHOD_CALL", - "NOPERSPECTIVE", "SAMPLE", "PATCH", "COHERENT", "RESTRICT", "READONLY", - "WRITEONLY", "SUBROUTINE", "DEVICECOHERENT", "QUEUEFAMILYCOHERENT", "WORKGROUPCOHERENT", - "SUBGROUPCOHERENT", "NONPRIVATE", "RAY_PAYLOAD_EXT", "RAY_PAYLOAD_IN_EXT", - "HIT_ATTRIBUTE_EXT", "CALLABLE_DATA_EXT", "CALLABLE_DATA_IN_EXT", "IGNORE_INTERSECTION_EXT", - "TERMINATE_RAY_EXT", "ACCELERATION_STRUCTURE_EXT", "ATOMIC_UINT", "STRUCT", - "IF", "ELSE", "SWITCH", "CASE", "DEFAULT", "WHILE", "DO", "FOR", "CONTINUE", - "BREAK", "RETURN", "DISCARD", "DEMOTE", "INTCONSTANT_frag", "FLOAT_SUFFIX", - "HALF_SUFFIX", "DOUBLE_SUFFIX", "UNSIGNED_SUFFIX", "SHORT_SUFFIX", "UINT16CONSTANT", - "INT16CONSTANT", "UINT32CONSTANT", "INT32CONSTANT", "UINT64CONSTANT", - "INT64CONSTANT", "FLOAT16CONSTANT", "FLOAT32CONSTANT", "FLOAT64CONSTANT", - "BOOLCONSTANT", "BOOL", "BVEC2", "BVEC3", "BVEC4", "INT8", "I8VEC2", - "I8VEC3", "I8VEC4", "UINT8", "U8VEC2", "U8VEC3", "U8VEC4", "INT16", "I16VEC2", - "I16VEC3", "I16VEC4", "UINT16", "U16VEC2", "U16VEC3", "U16VEC4", "INT32", - "I32VEC2", "I32VEC3", "I32VEC4", "UINT32", "U32VEC2", "U32VEC3", "U32VEC4", - "INT64", "I64VEC2", "I64VEC3", "I64VEC4", "UINT64", "U64VEC2", "U64VEC3", - "U64VEC4", "FLOAT16", "F16VEC2", "F16VEC3", "F16VEC4", "F16MAT2X2", "F16MAT2X3", - "F16MAT2X4", "F16MAT3X2", "F16MAT3X3", "F16MAT3X4", "F16MAT4X2", "F16MAT4X3", - "F16MAT4X4", "FLOAT32", "F32VEC2", "F32VEC3", "F32VEC4", "F32MAT2X2", - "F32MAT2X3", "F32MAT2X4", "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", "F32MAT4X2", - "F32MAT4X3", "F32MAT4X4", "FLOAT64", "F64VEC2", "F64VEC3", "F64VEC4", - "F64MAT2X2", "F64MAT2X3", "F64MAT2X4", "F64MAT3X2", "F64MAT3X3", "F64MAT3X4", - "F64MAT4X2", "F64MAT4X3", "F64MAT4X4", "IMAGE1D", "IMAGE2D", "IMAGE3D", - "UIMAGE1D", "UIMAGE2D", "UIMAGE3D", "IIMAGE1D", "IIMAGE2D", "IIMAGE3D", - "SAMPLER1D", "SAMPLER2D", "SAMPLER3D", "SAMPLER2DRECT", "SAMPLER1DSHADOW", - "SAMPLER2DSHADOW", "SAMPLER2DRECTSHADOW", "SAMPLER1DARRAY", "SAMPLER2DARRAY", - "SAMPLER1DARRAYSHADOW", "SAMPLER2DARRAYSHADOW", "ISAMPLER1D", "ISAMPLER2D", - "ISAMPLER2DRECT", "ISAMPLER3D", "ISAMPLER1DARRAY", "ISAMPLER2DARRAY", - "USAMPLER1D", "USAMPLER2D", "USAMPLER2DRECT", "USAMPLER3D", "USAMPLER1DARRAY", - "USAMPLER2DARRAY", "SAMPLER2DMS", "ISAMPLER2DMS", "USAMPLER2DMS", "SAMPLER2DMSARRAY", - "ISAMPLER2DMSARRAY", "USAMPLER2DMSARRAY", "IMAGE2DRECT", "IMAGE1DARRAY", - "IMAGE2DARRAY", "IMAGE2DMS", "IMAGE2DMSARRAY", "IIMAGE2DRECT", "IIMAGE1DARRAY", - "IIMAGE2DARRAY", "IIMAGE2DMS", "IIMAGE2DMSARRAY", "UIMAGE2DRECT", "UIMAGE1DARRAY", - "UIMAGE2DARRAY", "UIMAGE2DMS", "UIMAGE2DMSARRAY", "SAMPLERCUBESHADOW", - "SAMPLERCUBEARRAYSHADOW", "SAMPLERCUBE", "ISAMPLERCUBE", "USAMPLERCUBE", - "SAMPLERBUFFER", "ISAMPLERBUFFER", "USAMPLERBUFFER", "SAMPLERCUBEARRAY", - "ISAMPLERCUBEARRAY", "USAMPLERCUBEARRAY", "IMAGECUBE", "UIMAGECUBE", - "IIMAGECUBE", "IMAGEBUFFER", "IIMAGEBUFFER", "UIMAGEBUFFER", "IMAGECUBEARRAY", - "IIMAGECUBEARRAY", "UIMAGECUBEARRAY", "INC_OP", "DEC_OP", "VOID", "LEFT_OP", - "RIGHT_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "LOGICAL_AND_OP", "LOGICAL_XOR_OP", - "LOGICAL_OR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "MOD_ASSIGN", "ADD_ASSIGN", - "SUB_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", - "OR_ASSIGN", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "SEMICOLON", "LBRACKET", - "RBRACKET", "COMMA", "DOT", "PLUS_OP", "MINUS_OP", "LOGICAL_NOT_OP", - "BITWISE_NEG_OP", "TIMES_OP", "DIV_OP", "MOD_OP", "LT_OP", "GT_OP", "BITWISE_AND_OP", - "BITWISE_OR_OP", "BITWISE_XOR_OP", "QUERY_OP", "ASSIGN_OP", "NR_PP_PREFIX", - "PP_ENTER_MODE", "PP_EMPTY", "NR_LINE", "NR", "IDENTIFIER", "LINE_COMMENT_frag", - "BLOCK_COMMENT_frag", "LINE_CONTINUE", "LINE_COMMENT", "BLOCK_COMMENT", - "WS", "EOL", "NR_EXTENSION", "NR_VERSION", "NR_CUSTOM", "NR_INCLUDE", - "NR_PRAGMA", "NR_PRAGMA_DEBUG", "NR_PRAGMA_OPTIMIZE", "NR_PRAGMA_INVARIANT", - "NR_ON", "NR_OFF", "NR_ALL", "NR_REQUIRE", "NR_ENABLE", "NR_WARN", "NR_DISABLE", - "NR_COLON", "NR_LPAREN", "NR_RPAREN", "NR_STDGL", "NR_CORE", "NR_COMPATIBILITY", - "NR_ES", "NR_GLSL_110", "NR_GLSL_120", "NR_GLSLES_100", "NR_GLSL_130", - "NR_GLSL_140", "NR_GLSL_150", "NR_GLSL_330", "NR_GLSLES_300", "NR_GLSLES_310", - "NR_GLSLES_320", "NR_GLSL_400", "NR_GLSL_410", "NR_GLSL_420", "NR_GLSL_430", - "NR_GLSL_440", "NR_GLSL_450", "NR_GLSL_460", "NR_STRING_START", "NR_STRING_START_ANGLE", - "NR_INTCONSTANT", "NR_IDENTIFIER", "NR_LINE_CONTINUE", "NR_LINE_COMMENT", - "NR_BLOCK_COMMENT", "NR_EOL", "NR_WS", "S_CONTENT", "S_STRING_END", "S_CONTENT_ANGLE", - "S_STRING_END_ANGLE", "C_LINE_COMMENT", "C_BLOCK_COMMENT", "C_EOL", "C_WS", - "C_CONTENT", "PP_LINE_CONTINUE", "PP_LINE_COMMENT", "PP_BLOCK_COMMENT", + "DECIMAL_DIGITS", "OCTAL_DIGITS", "HEX_DIGITS", "DIGIT", "FLOAT_DIGITS", + "IDENTIFIER_frag", "WS_frag", "NEWLINE", "NO_NEWLINE", "LINE_CONTINUE_frag", + "COLON", "UNIFORM", "BUFFER", "IN", "OUT", "INOUT", "HIGHP", "MEDIUMP", + "LOWP", "PRECISION", "CONST", "PRECISE", "INVARIANT", "SMOOTH", "FLAT", + "CENTROID", "ATTRIBUTE", "VOLATILE", "VARYING", "SHARED", "LAYOUT", "DOT_LENGTH_METHOD_CALL", + "NOPERSPECTIVE", "SAMPLE", "PATCH", "COHERENT", "RESTRICT", "READONLY", + "WRITEONLY", "SUBROUTINE", "DEVICECOHERENT", "QUEUEFAMILYCOHERENT", "WORKGROUPCOHERENT", + "SUBGROUPCOHERENT", "NONPRIVATE", "RAY_PAYLOAD_EXT", "RAY_PAYLOAD_IN_EXT", + "HIT_ATTRIBUTE_EXT", "CALLABLE_DATA_EXT", "CALLABLE_DATA_IN_EXT", "IGNORE_INTERSECTION_EXT", + "TERMINATE_RAY_EXT", "ACCELERATION_STRUCTURE_EXT", "ATOMIC_UINT", "STRUCT", + "IF", "ELSE", "SWITCH", "CASE", "DEFAULT", "WHILE", "DO", "FOR", "CONTINUE", + "BREAK", "RETURN", "DISCARD", "DEMOTE", "INTCONSTANT_frag", "FLOAT_SUFFIX", + "HALF_SUFFIX", "DOUBLE_SUFFIX", "UNSIGNED_SUFFIX", "SHORT_SUFFIX", "UINT16CONSTANT", + "INT16CONSTANT", "UINT32CONSTANT", "INT32CONSTANT", "UINT64CONSTANT", + "INT64CONSTANT", "FLOAT16CONSTANT", "FLOAT32CONSTANT", "FLOAT64CONSTANT", + "BOOLCONSTANT", "BOOL", "BVEC2", "BVEC3", "BVEC4", "INT8", "I8VEC2", + "I8VEC3", "I8VEC4", "UINT8", "U8VEC2", "U8VEC3", "U8VEC4", "INT16", "I16VEC2", + "I16VEC3", "I16VEC4", "UINT16", "U16VEC2", "U16VEC3", "U16VEC4", "INT32", + "I32VEC2", "I32VEC3", "I32VEC4", "UINT32", "U32VEC2", "U32VEC3", "U32VEC4", + "INT64", "I64VEC2", "I64VEC3", "I64VEC4", "UINT64", "U64VEC2", "U64VEC3", + "U64VEC4", "FLOAT16", "F16VEC2", "F16VEC3", "F16VEC4", "F16MAT2X2", "F16MAT2X3", + "F16MAT2X4", "F16MAT3X2", "F16MAT3X3", "F16MAT3X4", "F16MAT4X2", "F16MAT4X3", + "F16MAT4X4", "FLOAT32", "F32VEC2", "F32VEC3", "F32VEC4", "F32MAT2X2", + "F32MAT2X3", "F32MAT2X4", "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", "F32MAT4X2", + "F32MAT4X3", "F32MAT4X4", "FLOAT64", "F64VEC2", "F64VEC3", "F64VEC4", + "F64MAT2X2", "F64MAT2X3", "F64MAT2X4", "F64MAT3X2", "F64MAT3X3", "F64MAT3X4", + "F64MAT4X2", "F64MAT4X3", "F64MAT4X4", "IMAGE1D", "IMAGE2D", "IMAGE3D", + "UIMAGE1D", "UIMAGE2D", "UIMAGE3D", "IIMAGE1D", "IIMAGE2D", "IIMAGE3D", + "SAMPLER1D", "SAMPLER2D", "SAMPLER3D", "SAMPLER2DRECT", "SAMPLER1DSHADOW", + "SAMPLER2DSHADOW", "SAMPLER2DRECTSHADOW", "SAMPLER1DARRAY", "SAMPLER2DARRAY", + "SAMPLER1DARRAYSHADOW", "SAMPLER2DARRAYSHADOW", "ISAMPLER1D", "ISAMPLER2D", + "ISAMPLER2DRECT", "ISAMPLER3D", "ISAMPLER1DARRAY", "ISAMPLER2DARRAY", + "USAMPLER1D", "USAMPLER2D", "USAMPLER2DRECT", "USAMPLER3D", "USAMPLER1DARRAY", + "USAMPLER2DARRAY", "SAMPLER2DMS", "ISAMPLER2DMS", "USAMPLER2DMS", "SAMPLER2DMSARRAY", + "ISAMPLER2DMSARRAY", "USAMPLER2DMSARRAY", "IMAGE2DRECT", "IMAGE1DARRAY", + "IMAGE2DARRAY", "IMAGE2DMS", "IMAGE2DMSARRAY", "IIMAGE2DRECT", "IIMAGE1DARRAY", + "IIMAGE2DARRAY", "IIMAGE2DMS", "IIMAGE2DMSARRAY", "UIMAGE2DRECT", "UIMAGE1DARRAY", + "UIMAGE2DARRAY", "UIMAGE2DMS", "UIMAGE2DMSARRAY", "SAMPLERCUBESHADOW", + "SAMPLERCUBEARRAYSHADOW", "SAMPLERCUBE", "ISAMPLERCUBE", "USAMPLERCUBE", + "SAMPLERBUFFER", "ISAMPLERBUFFER", "USAMPLERBUFFER", "SAMPLERCUBEARRAY", + "ISAMPLERCUBEARRAY", "USAMPLERCUBEARRAY", "IMAGECUBE", "UIMAGECUBE", + "IIMAGECUBE", "IMAGEBUFFER", "IIMAGEBUFFER", "UIMAGEBUFFER", "IMAGECUBEARRAY", + "IIMAGECUBEARRAY", "UIMAGECUBEARRAY", "INC_OP", "DEC_OP", "VOID", "LEFT_OP", + "RIGHT_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "LOGICAL_AND_OP", "LOGICAL_XOR_OP", + "LOGICAL_OR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "MOD_ASSIGN", "ADD_ASSIGN", + "SUB_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", + "OR_ASSIGN", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "SEMICOLON", "LBRACKET", + "RBRACKET", "COMMA", "DOT", "PLUS_OP", "MINUS_OP", "LOGICAL_NOT_OP", + "BITWISE_NEG_OP", "TIMES_OP", "DIV_OP", "MOD_OP", "LT_OP", "GT_OP", "BITWISE_AND_OP", + "BITWISE_OR_OP", "BITWISE_XOR_OP", "QUERY_OP", "ASSIGN_OP", "NR_PP_PREFIX", + "PP_ENTER_MODE", "PP_EMPTY", "NR_LINE", "NR", "IDENTIFIER", "LINE_COMMENT_frag", + "BLOCK_COMMENT_frag", "LINE_CONTINUE", "LINE_COMMENT", "BLOCK_COMMENT", + "WS", "EOL", "NR_EXTENSION", "NR_VERSION", "NR_CUSTOM", "NR_INCLUDE", + "NR_PRAGMA", "NR_PRAGMA_DEBUG", "NR_PRAGMA_OPTIMIZE", "NR_PRAGMA_INVARIANT", + "NR_ON", "NR_OFF", "NR_ALL", "NR_REQUIRE", "NR_ENABLE", "NR_WARN", "NR_DISABLE", + "NR_COLON", "NR_LPAREN", "NR_RPAREN", "NR_STDGL", "NR_CORE", "NR_COMPATIBILITY", + "NR_ES", "NR_GLSL_110", "NR_GLSL_120", "NR_GLSLES_100", "NR_GLSL_130", + "NR_GLSL_140", "NR_GLSL_150", "NR_GLSL_330", "NR_GLSLES_300", "NR_GLSLES_310", + "NR_GLSLES_320", "NR_GLSL_400", "NR_GLSL_410", "NR_GLSL_420", "NR_GLSL_430", + "NR_GLSL_440", "NR_GLSL_450", "NR_GLSL_460", "NR_STRING_START", "NR_STRING_START_ANGLE", + "NR_INTCONSTANT", "NR_IDENTIFIER", "NR_LINE_CONTINUE", "NR_LINE_COMMENT", + "NR_BLOCK_COMMENT", "NR_EOL", "NR_WS", "S_CONTENT", "S_STRING_END", "S_CONTENT_ANGLE", + "S_STRING_END_ANGLE", "C_LINE_COMMENT", "C_BLOCK_COMMENT", "C_EOL", "C_WS", + "C_CONTENT", "PP_LINE_CONTINUE", "PP_LINE_COMMENT", "PP_BLOCK_COMMENT", "PP_EOL", "PP_CONTENT" }; } @@ -173,122 +171,122 @@ private static String[] makeRuleNames() { private static String[] makeLiteralNames() { return new String[] { - null, null, "'uniform'", "'buffer'", "'in'", "'out'", "'inout'", "'highp'", - "'mediump'", "'lowp'", "'precision'", "'const'", "'precise'", null, "'smooth'", - "'flat'", "'centroid'", "'attribute'", "'volatile'", "'varying'", "'shared'", - "'layout'", "'.length()'", "'noperspective'", "'sample'", "'patch'", - "'coherent'", "'restrict'", "'readonly'", "'writeonly'", "'subroutine'", - "'devicecoherent'", "'queuefamilycoherent'", "'workgroupcoherent'", "'subgroupcoherent'", - "'nonprivate'", "'rayPayloadEXT'", "'rayPayloadInEXT'", "'hitAttributeEXT'", - "'callableDataEXT'", "'callableDataInEXT'", "'ignoreIntersectionEXT'", - "'terminateRayEXT'", "'accelerationStructureEXT'", "'atomic_uint'", "'struct'", - "'if'", "'else'", "'switch'", "'case'", "'default'", "'while'", "'do'", - "'for'", "'continue'", "'break'", "'return'", "'discard'", "'demote'", - null, null, null, null, null, null, null, null, null, null, "'bool'", - "'bvec2'", "'bvec3'", "'bvec4'", "'int8_t'", "'i8vec2'", "'i8vec3'", - "'i8vec4'", "'uint8_t'", "'u8vec2'", "'u8vec3'", "'u8vec4'", "'int16_t'", - "'i16vec2'", "'i16vec3'", "'i16vec4'", "'uint16_t'", "'u16vec2'", "'u16vec3'", - "'u16vec4'", null, null, null, null, null, null, null, null, "'int64_t'", - "'i64vec2'", "'i64vec3'", "'i64vec4'", "'uint64_t'", "'u64vec2'", "'u64vec3'", - "'u64vec4'", "'float16_t'", "'f16vec2'", "'f16vec3'", "'f16vec4'", null, - "'f16mat2x3'", "'f16mat2x4'", "'f16mat3x2'", null, "'f16mat3x4'", "'f16mat4x2'", - "'f16mat4x3'", null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, "'image1D'", "'image2D'", "'image3D'", - "'uimage1D'", "'uimage2D'", "'uimage3D'", "'iimage1D'", "'iimage2D'", - "'iimage3D'", "'sampler1D'", "'sampler2D'", "'sampler3D'", "'sampler2DRect'", - "'sampler1DShadow'", "'sampler2DShadow'", "'sampler2DRectShadow'", "'sampler1DArray'", - "'sampler2DArray'", "'sampler1DArrayShadow'", "'sampler2DArrayShadow'", - "'isampler1D'", "'isampler2D'", "'isampler2DRect'", "'isampler3D'", "'isampler1DArray'", - "'isampler2DArray'", "'usampler1D'", "'usampler2D'", "'usampler2DRect'", - "'usampler3D'", "'usampler1DArray'", "'usampler2DArray'", "'sampler2DMS'", - "'isampler2DMS'", "'usampler2DMS'", "'sampler2DMSArray'", "'isampler2DMSArray'", - "'usampler2DMSArray'", "'image2DRect'", "'image1DArray'", "'image2DArray'", - "'image2DMS'", "'image2DMSArray'", "'iimage2DRect'", "'iimage1DArray'", - "'iimage2DArray'", "'iimage2DMS'", "'iimage2DMSArray'", "'uimage2DRect'", - "'uimage1DArray'", "'uimage2DArray'", "'uimage2DMS'", "'uimage2DMSArray'", - "'samplerCubeShadow'", "'samplerCubeArrayShadow'", "'samplerCube'", "'isamplerCube'", - "'usamplerCube'", "'samplerBuffer'", "'isamplerBuffer'", "'usamplerBuffer'", - "'samplerCubeArray'", "'isamplerCubeArray'", "'usamplerCubeArray'", "'imageCube'", - "'uimageCube'", "'iimageCube'", "'imageBuffer'", "'iimageBuffer'", "'uimageBuffer'", - "'imageCubeArray'", "'iimageCubeArray'", "'uimageCubeArray'", "'++'", - "'--'", "'void'", "'<<'", "'>>'", "'<='", "'>='", "'=='", "'!='", "'&&'", - "'^^'", "'||'", "'*='", "'/='", "'%='", "'+='", "'-='", "'<<='", "'>>='", - "'&='", "'^='", "'|='", null, null, "'{'", "'}'", "';'", "'['", "']'", - "','", "'.'", "'+'", "'-'", "'!'", "'~'", "'*'", "'/'", "'%'", "'<'", - null, "'&'", "'|'", "'^'", "'?'", "'='", null, null, null, "'#'", null, - null, null, null, null, null, "'extension'", "'version'", null, "'include'", - "'pragma'", "'debug'", "'optimize'", null, "'on'", "'off'", "'all'", - "'require'", "'enable'", "'warn'", "'disable'", null, null, null, "'STDGL'", - "'core'", "'compatibility'", "'es'", "'110'", "'120'", "'100'", "'130'", - "'140'", "'150'", "'330'", "'300'", "'310'", "'320'", "'400'", "'410'", - "'420'", "'430'", "'440'", "'450'", "'460'", null, null, null, null, + null, null, "'uniform'", "'buffer'", "'in'", "'out'", "'inout'", "'highp'", + "'mediump'", "'lowp'", "'precision'", "'const'", "'precise'", null, "'smooth'", + "'flat'", "'centroid'", "'attribute'", "'volatile'", "'varying'", "'shared'", + "'layout'", "'.length()'", "'noperspective'", "'sample'", "'patch'", + "'coherent'", "'restrict'", "'readonly'", "'writeonly'", "'subroutine'", + "'devicecoherent'", "'queuefamilycoherent'", "'workgroupcoherent'", "'subgroupcoherent'", + "'nonprivate'", "'rayPayloadEXT'", "'rayPayloadInEXT'", "'hitAttributeEXT'", + "'callableDataEXT'", "'callableDataInEXT'", "'ignoreIntersectionEXT'", + "'terminateRayEXT'", "'accelerationStructureEXT'", "'atomic_uint'", "'struct'", + "'if'", "'else'", "'switch'", "'case'", "'default'", "'while'", "'do'", + "'for'", "'continue'", "'break'", "'return'", "'discard'", "'demote'", + null, null, null, null, null, null, null, null, null, null, "'bool'", + "'bvec2'", "'bvec3'", "'bvec4'", "'int8_t'", "'i8vec2'", "'i8vec3'", + "'i8vec4'", "'uint8_t'", "'u8vec2'", "'u8vec3'", "'u8vec4'", "'int16_t'", + "'i16vec2'", "'i16vec3'", "'i16vec4'", "'uint16_t'", "'u16vec2'", "'u16vec3'", + "'u16vec4'", null, null, null, null, null, null, null, null, "'int64_t'", + "'i64vec2'", "'i64vec3'", "'i64vec4'", "'uint64_t'", "'u64vec2'", "'u64vec3'", + "'u64vec4'", "'float16_t'", "'f16vec2'", "'f16vec3'", "'f16vec4'", null, + "'f16mat2x3'", "'f16mat2x4'", "'f16mat3x2'", null, "'f16mat3x4'", "'f16mat4x2'", + "'f16mat4x3'", null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, "'image1D'", "'image2D'", "'image3D'", + "'uimage1D'", "'uimage2D'", "'uimage3D'", "'iimage1D'", "'iimage2D'", + "'iimage3D'", "'sampler1D'", "'sampler2D'", "'sampler3D'", "'sampler2DRect'", + "'sampler1DShadow'", "'sampler2DShadow'", "'sampler2DRectShadow'", "'sampler1DArray'", + "'sampler2DArray'", "'sampler1DArrayShadow'", "'sampler2DArrayShadow'", + "'isampler1D'", "'isampler2D'", "'isampler2DRect'", "'isampler3D'", "'isampler1DArray'", + "'isampler2DArray'", "'usampler1D'", "'usampler2D'", "'usampler2DRect'", + "'usampler3D'", "'usampler1DArray'", "'usampler2DArray'", "'sampler2DMS'", + "'isampler2DMS'", "'usampler2DMS'", "'sampler2DMSArray'", "'isampler2DMSArray'", + "'usampler2DMSArray'", "'image2DRect'", "'image1DArray'", "'image2DArray'", + "'image2DMS'", "'image2DMSArray'", "'iimage2DRect'", "'iimage1DArray'", + "'iimage2DArray'", "'iimage2DMS'", "'iimage2DMSArray'", "'uimage2DRect'", + "'uimage1DArray'", "'uimage2DArray'", "'uimage2DMS'", "'uimage2DMSArray'", + "'samplerCubeShadow'", "'samplerCubeArrayShadow'", "'samplerCube'", "'isamplerCube'", + "'usamplerCube'", "'samplerBuffer'", "'isamplerBuffer'", "'usamplerBuffer'", + "'samplerCubeArray'", "'isamplerCubeArray'", "'usamplerCubeArray'", "'imageCube'", + "'uimageCube'", "'iimageCube'", "'imageBuffer'", "'iimageBuffer'", "'uimageBuffer'", + "'imageCubeArray'", "'iimageCubeArray'", "'uimageCubeArray'", "'++'", + "'--'", "'void'", "'<<'", "'>>'", "'<='", "'>='", "'=='", "'!='", "'&&'", + "'^^'", "'||'", "'*='", "'/='", "'%='", "'+='", "'-='", "'<<='", "'>>='", + "'&='", "'^='", "'|='", null, null, "'{'", "'}'", "';'", "'['", "']'", + "','", "'.'", "'+'", "'-'", "'!'", "'~'", "'*'", "'/'", "'%'", "'<'", + null, "'&'", "'|'", "'^'", "'?'", "'='", null, null, null, "'#'", null, + null, null, null, null, null, "'extension'", "'version'", null, "'include'", + "'pragma'", "'debug'", "'optimize'", null, "'on'", "'off'", "'all'", + "'require'", "'enable'", "'warn'", "'disable'", null, null, null, "'STDGL'", + "'core'", "'compatibility'", "'es'", "'110'", "'120'", "'100'", "'130'", + "'140'", "'150'", "'330'", "'300'", "'310'", "'320'", "'400'", "'410'", + "'420'", "'430'", "'440'", "'450'", "'460'", null, null, null, null, null, null, null, null, null, null, "'\"'" }; } private static final String[] _LITERAL_NAMES = makeLiteralNames(); private static String[] makeSymbolicNames() { return new String[] { - null, "COLON", "UNIFORM", "BUFFER", "IN", "OUT", "INOUT", "HIGHP", "MEDIUMP", - "LOWP", "PRECISION", "CONST", "PRECISE", "INVARIANT", "SMOOTH", "FLAT", - "CENTROID", "ATTRIBUTE", "VOLATILE", "VARYING", "SHARED", "LAYOUT", "DOT_LENGTH_METHOD_CALL", - "NOPERSPECTIVE", "SAMPLE", "PATCH", "COHERENT", "RESTRICT", "READONLY", - "WRITEONLY", "SUBROUTINE", "DEVICECOHERENT", "QUEUEFAMILYCOHERENT", "WORKGROUPCOHERENT", - "SUBGROUPCOHERENT", "NONPRIVATE", "RAY_PAYLOAD_EXT", "RAY_PAYLOAD_IN_EXT", - "HIT_ATTRIBUTE_EXT", "CALLABLE_DATA_EXT", "CALLABLE_DATA_IN_EXT", "IGNORE_INTERSECTION_EXT", - "TERMINATE_RAY_EXT", "ACCELERATION_STRUCTURE_EXT", "ATOMIC_UINT", "STRUCT", - "IF", "ELSE", "SWITCH", "CASE", "DEFAULT", "WHILE", "DO", "FOR", "CONTINUE", - "BREAK", "RETURN", "DISCARD", "DEMOTE", "UINT16CONSTANT", "INT16CONSTANT", - "UINT32CONSTANT", "INT32CONSTANT", "UINT64CONSTANT", "INT64CONSTANT", - "FLOAT16CONSTANT", "FLOAT32CONSTANT", "FLOAT64CONSTANT", "BOOLCONSTANT", - "BOOL", "BVEC2", "BVEC3", "BVEC4", "INT8", "I8VEC2", "I8VEC3", "I8VEC4", - "UINT8", "U8VEC2", "U8VEC3", "U8VEC4", "INT16", "I16VEC2", "I16VEC3", - "I16VEC4", "UINT16", "U16VEC2", "U16VEC3", "U16VEC4", "INT32", "I32VEC2", - "I32VEC3", "I32VEC4", "UINT32", "U32VEC2", "U32VEC3", "U32VEC4", "INT64", - "I64VEC2", "I64VEC3", "I64VEC4", "UINT64", "U64VEC2", "U64VEC3", "U64VEC4", - "FLOAT16", "F16VEC2", "F16VEC3", "F16VEC4", "F16MAT2X2", "F16MAT2X3", - "F16MAT2X4", "F16MAT3X2", "F16MAT3X3", "F16MAT3X4", "F16MAT4X2", "F16MAT4X3", - "F16MAT4X4", "FLOAT32", "F32VEC2", "F32VEC3", "F32VEC4", "F32MAT2X2", - "F32MAT2X3", "F32MAT2X4", "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", "F32MAT4X2", - "F32MAT4X3", "F32MAT4X4", "FLOAT64", "F64VEC2", "F64VEC3", "F64VEC4", - "F64MAT2X2", "F64MAT2X3", "F64MAT2X4", "F64MAT3X2", "F64MAT3X3", "F64MAT3X4", - "F64MAT4X2", "F64MAT4X3", "F64MAT4X4", "IMAGE1D", "IMAGE2D", "IMAGE3D", - "UIMAGE1D", "UIMAGE2D", "UIMAGE3D", "IIMAGE1D", "IIMAGE2D", "IIMAGE3D", - "SAMPLER1D", "SAMPLER2D", "SAMPLER3D", "SAMPLER2DRECT", "SAMPLER1DSHADOW", - "SAMPLER2DSHADOW", "SAMPLER2DRECTSHADOW", "SAMPLER1DARRAY", "SAMPLER2DARRAY", - "SAMPLER1DARRAYSHADOW", "SAMPLER2DARRAYSHADOW", "ISAMPLER1D", "ISAMPLER2D", - "ISAMPLER2DRECT", "ISAMPLER3D", "ISAMPLER1DARRAY", "ISAMPLER2DARRAY", - "USAMPLER1D", "USAMPLER2D", "USAMPLER2DRECT", "USAMPLER3D", "USAMPLER1DARRAY", - "USAMPLER2DARRAY", "SAMPLER2DMS", "ISAMPLER2DMS", "USAMPLER2DMS", "SAMPLER2DMSARRAY", - "ISAMPLER2DMSARRAY", "USAMPLER2DMSARRAY", "IMAGE2DRECT", "IMAGE1DARRAY", - "IMAGE2DARRAY", "IMAGE2DMS", "IMAGE2DMSARRAY", "IIMAGE2DRECT", "IIMAGE1DARRAY", - "IIMAGE2DARRAY", "IIMAGE2DMS", "IIMAGE2DMSARRAY", "UIMAGE2DRECT", "UIMAGE1DARRAY", - "UIMAGE2DARRAY", "UIMAGE2DMS", "UIMAGE2DMSARRAY", "SAMPLERCUBESHADOW", - "SAMPLERCUBEARRAYSHADOW", "SAMPLERCUBE", "ISAMPLERCUBE", "USAMPLERCUBE", - "SAMPLERBUFFER", "ISAMPLERBUFFER", "USAMPLERBUFFER", "SAMPLERCUBEARRAY", - "ISAMPLERCUBEARRAY", "USAMPLERCUBEARRAY", "IMAGECUBE", "UIMAGECUBE", - "IIMAGECUBE", "IMAGEBUFFER", "IIMAGEBUFFER", "UIMAGEBUFFER", "IMAGECUBEARRAY", - "IIMAGECUBEARRAY", "UIMAGECUBEARRAY", "INC_OP", "DEC_OP", "VOID", "LEFT_OP", - "RIGHT_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "LOGICAL_AND_OP", "LOGICAL_XOR_OP", - "LOGICAL_OR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "MOD_ASSIGN", "ADD_ASSIGN", - "SUB_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", - "OR_ASSIGN", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "SEMICOLON", "LBRACKET", - "RBRACKET", "COMMA", "DOT", "PLUS_OP", "MINUS_OP", "LOGICAL_NOT_OP", - "BITWISE_NEG_OP", "TIMES_OP", "DIV_OP", "MOD_OP", "LT_OP", "GT_OP", "BITWISE_AND_OP", - "BITWISE_OR_OP", "BITWISE_XOR_OP", "QUERY_OP", "ASSIGN_OP", "PP_ENTER_MODE", - "PP_EMPTY", "NR_LINE", "NR", "IDENTIFIER", "LINE_CONTINUE", "LINE_COMMENT", - "BLOCK_COMMENT", "WS", "EOL", "NR_EXTENSION", "NR_VERSION", "NR_CUSTOM", - "NR_INCLUDE", "NR_PRAGMA", "NR_PRAGMA_DEBUG", "NR_PRAGMA_OPTIMIZE", "NR_PRAGMA_INVARIANT", - "NR_ON", "NR_OFF", "NR_ALL", "NR_REQUIRE", "NR_ENABLE", "NR_WARN", "NR_DISABLE", - "NR_COLON", "NR_LPAREN", "NR_RPAREN", "NR_STDGL", "NR_CORE", "NR_COMPATIBILITY", - "NR_ES", "NR_GLSL_110", "NR_GLSL_120", "NR_GLSLES_100", "NR_GLSL_130", - "NR_GLSL_140", "NR_GLSL_150", "NR_GLSL_330", "NR_GLSLES_300", "NR_GLSLES_310", - "NR_GLSLES_320", "NR_GLSL_400", "NR_GLSL_410", "NR_GLSL_420", "NR_GLSL_430", - "NR_GLSL_440", "NR_GLSL_450", "NR_GLSL_460", "NR_STRING_START", "NR_STRING_START_ANGLE", - "NR_INTCONSTANT", "NR_IDENTIFIER", "NR_LINE_CONTINUE", "NR_LINE_COMMENT", - "NR_BLOCK_COMMENT", "NR_EOL", "NR_WS", "S_CONTENT", "S_STRING_END", "S_CONTENT_ANGLE", - "S_STRING_END_ANGLE", "C_LINE_COMMENT", "C_BLOCK_COMMENT", "C_EOL", "C_WS", - "C_CONTENT", "PP_LINE_CONTINUE", "PP_LINE_COMMENT", "PP_BLOCK_COMMENT", + null, "COLON", "UNIFORM", "BUFFER", "IN", "OUT", "INOUT", "HIGHP", "MEDIUMP", + "LOWP", "PRECISION", "CONST", "PRECISE", "INVARIANT", "SMOOTH", "FLAT", + "CENTROID", "ATTRIBUTE", "VOLATILE", "VARYING", "SHARED", "LAYOUT", "DOT_LENGTH_METHOD_CALL", + "NOPERSPECTIVE", "SAMPLE", "PATCH", "COHERENT", "RESTRICT", "READONLY", + "WRITEONLY", "SUBROUTINE", "DEVICECOHERENT", "QUEUEFAMILYCOHERENT", "WORKGROUPCOHERENT", + "SUBGROUPCOHERENT", "NONPRIVATE", "RAY_PAYLOAD_EXT", "RAY_PAYLOAD_IN_EXT", + "HIT_ATTRIBUTE_EXT", "CALLABLE_DATA_EXT", "CALLABLE_DATA_IN_EXT", "IGNORE_INTERSECTION_EXT", + "TERMINATE_RAY_EXT", "ACCELERATION_STRUCTURE_EXT", "ATOMIC_UINT", "STRUCT", + "IF", "ELSE", "SWITCH", "CASE", "DEFAULT", "WHILE", "DO", "FOR", "CONTINUE", + "BREAK", "RETURN", "DISCARD", "DEMOTE", "UINT16CONSTANT", "INT16CONSTANT", + "UINT32CONSTANT", "INT32CONSTANT", "UINT64CONSTANT", "INT64CONSTANT", + "FLOAT16CONSTANT", "FLOAT32CONSTANT", "FLOAT64CONSTANT", "BOOLCONSTANT", + "BOOL", "BVEC2", "BVEC3", "BVEC4", "INT8", "I8VEC2", "I8VEC3", "I8VEC4", + "UINT8", "U8VEC2", "U8VEC3", "U8VEC4", "INT16", "I16VEC2", "I16VEC3", + "I16VEC4", "UINT16", "U16VEC2", "U16VEC3", "U16VEC4", "INT32", "I32VEC2", + "I32VEC3", "I32VEC4", "UINT32", "U32VEC2", "U32VEC3", "U32VEC4", "INT64", + "I64VEC2", "I64VEC3", "I64VEC4", "UINT64", "U64VEC2", "U64VEC3", "U64VEC4", + "FLOAT16", "F16VEC2", "F16VEC3", "F16VEC4", "F16MAT2X2", "F16MAT2X3", + "F16MAT2X4", "F16MAT3X2", "F16MAT3X3", "F16MAT3X4", "F16MAT4X2", "F16MAT4X3", + "F16MAT4X4", "FLOAT32", "F32VEC2", "F32VEC3", "F32VEC4", "F32MAT2X2", + "F32MAT2X3", "F32MAT2X4", "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", "F32MAT4X2", + "F32MAT4X3", "F32MAT4X4", "FLOAT64", "F64VEC2", "F64VEC3", "F64VEC4", + "F64MAT2X2", "F64MAT2X3", "F64MAT2X4", "F64MAT3X2", "F64MAT3X3", "F64MAT3X4", + "F64MAT4X2", "F64MAT4X3", "F64MAT4X4", "IMAGE1D", "IMAGE2D", "IMAGE3D", + "UIMAGE1D", "UIMAGE2D", "UIMAGE3D", "IIMAGE1D", "IIMAGE2D", "IIMAGE3D", + "SAMPLER1D", "SAMPLER2D", "SAMPLER3D", "SAMPLER2DRECT", "SAMPLER1DSHADOW", + "SAMPLER2DSHADOW", "SAMPLER2DRECTSHADOW", "SAMPLER1DARRAY", "SAMPLER2DARRAY", + "SAMPLER1DARRAYSHADOW", "SAMPLER2DARRAYSHADOW", "ISAMPLER1D", "ISAMPLER2D", + "ISAMPLER2DRECT", "ISAMPLER3D", "ISAMPLER1DARRAY", "ISAMPLER2DARRAY", + "USAMPLER1D", "USAMPLER2D", "USAMPLER2DRECT", "USAMPLER3D", "USAMPLER1DARRAY", + "USAMPLER2DARRAY", "SAMPLER2DMS", "ISAMPLER2DMS", "USAMPLER2DMS", "SAMPLER2DMSARRAY", + "ISAMPLER2DMSARRAY", "USAMPLER2DMSARRAY", "IMAGE2DRECT", "IMAGE1DARRAY", + "IMAGE2DARRAY", "IMAGE2DMS", "IMAGE2DMSARRAY", "IIMAGE2DRECT", "IIMAGE1DARRAY", + "IIMAGE2DARRAY", "IIMAGE2DMS", "IIMAGE2DMSARRAY", "UIMAGE2DRECT", "UIMAGE1DARRAY", + "UIMAGE2DARRAY", "UIMAGE2DMS", "UIMAGE2DMSARRAY", "SAMPLERCUBESHADOW", + "SAMPLERCUBEARRAYSHADOW", "SAMPLERCUBE", "ISAMPLERCUBE", "USAMPLERCUBE", + "SAMPLERBUFFER", "ISAMPLERBUFFER", "USAMPLERBUFFER", "SAMPLERCUBEARRAY", + "ISAMPLERCUBEARRAY", "USAMPLERCUBEARRAY", "IMAGECUBE", "UIMAGECUBE", + "IIMAGECUBE", "IMAGEBUFFER", "IIMAGEBUFFER", "UIMAGEBUFFER", "IMAGECUBEARRAY", + "IIMAGECUBEARRAY", "UIMAGECUBEARRAY", "INC_OP", "DEC_OP", "VOID", "LEFT_OP", + "RIGHT_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "LOGICAL_AND_OP", "LOGICAL_XOR_OP", + "LOGICAL_OR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "MOD_ASSIGN", "ADD_ASSIGN", + "SUB_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", + "OR_ASSIGN", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "SEMICOLON", "LBRACKET", + "RBRACKET", "COMMA", "DOT", "PLUS_OP", "MINUS_OP", "LOGICAL_NOT_OP", + "BITWISE_NEG_OP", "TIMES_OP", "DIV_OP", "MOD_OP", "LT_OP", "GT_OP", "BITWISE_AND_OP", + "BITWISE_OR_OP", "BITWISE_XOR_OP", "QUERY_OP", "ASSIGN_OP", "PP_ENTER_MODE", + "PP_EMPTY", "NR_LINE", "NR", "IDENTIFIER", "LINE_CONTINUE", "LINE_COMMENT", + "BLOCK_COMMENT", "WS", "EOL", "NR_EXTENSION", "NR_VERSION", "NR_CUSTOM", + "NR_INCLUDE", "NR_PRAGMA", "NR_PRAGMA_DEBUG", "NR_PRAGMA_OPTIMIZE", "NR_PRAGMA_INVARIANT", + "NR_ON", "NR_OFF", "NR_ALL", "NR_REQUIRE", "NR_ENABLE", "NR_WARN", "NR_DISABLE", + "NR_COLON", "NR_LPAREN", "NR_RPAREN", "NR_STDGL", "NR_CORE", "NR_COMPATIBILITY", + "NR_ES", "NR_GLSL_110", "NR_GLSL_120", "NR_GLSLES_100", "NR_GLSL_130", + "NR_GLSL_140", "NR_GLSL_150", "NR_GLSL_330", "NR_GLSLES_300", "NR_GLSLES_310", + "NR_GLSLES_320", "NR_GLSL_400", "NR_GLSL_410", "NR_GLSL_420", "NR_GLSL_430", + "NR_GLSL_440", "NR_GLSL_450", "NR_GLSL_460", "NR_STRING_START", "NR_STRING_START_ANGLE", + "NR_INTCONSTANT", "NR_IDENTIFIER", "NR_LINE_CONTINUE", "NR_LINE_COMMENT", + "NR_BLOCK_COMMENT", "NR_EOL", "NR_WS", "S_CONTENT", "S_STRING_END", "S_CONTENT_ANGLE", + "S_STRING_END_ANGLE", "C_LINE_COMMENT", "C_BLOCK_COMMENT", "C_EOL", "C_WS", + "C_CONTENT", "PP_LINE_CONTINUE", "PP_LINE_COMMENT", "PP_BLOCK_COMMENT", "PP_EOL", "PP_CONTENT" }; } @@ -3163,4 +3161,4 @@ private boolean NR_STRING_START_ANGLE_sempred(RuleContext _localctx, int predInd _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); } } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/douira/glsl_transformer/GLSLLexer.tokens b/src/main/java/io/github/douira/glsl_transformer/GLSLLexer.tokens new file mode 100644 index 0000000000..c10b12e6b6 --- /dev/null +++ b/src/main/java/io/github/douira/glsl_transformer/GLSLLexer.tokens @@ -0,0 +1,578 @@ +COLON=1 +UNIFORM=2 +BUFFER=3 +IN=4 +OUT=5 +INOUT=6 +HIGHP=7 +MEDIUMP=8 +LOWP=9 +PRECISION=10 +CONST=11 +PRECISE=12 +INVARIANT=13 +SMOOTH=14 +FLAT=15 +CENTROID=16 +ATTRIBUTE=17 +VOLATILE=18 +VARYING=19 +SHARED=20 +LAYOUT=21 +DOT_LENGTH_METHOD_CALL=22 +NOPERSPECTIVE=23 +SAMPLE=24 +PATCH=25 +COHERENT=26 +RESTRICT=27 +READONLY=28 +WRITEONLY=29 +SUBROUTINE=30 +DEVICECOHERENT=31 +QUEUEFAMILYCOHERENT=32 +WORKGROUPCOHERENT=33 +SUBGROUPCOHERENT=34 +NONPRIVATE=35 +RAY_PAYLOAD_EXT=36 +RAY_PAYLOAD_IN_EXT=37 +HIT_ATTRIBUTE_EXT=38 +CALLABLE_DATA_EXT=39 +CALLABLE_DATA_IN_EXT=40 +IGNORE_INTERSECTION_EXT=41 +TERMINATE_RAY_EXT=42 +ACCELERATION_STRUCTURE_EXT=43 +ATOMIC_UINT=44 +STRUCT=45 +IF=46 +ELSE=47 +SWITCH=48 +CASE=49 +DEFAULT=50 +WHILE=51 +DO=52 +FOR=53 +CONTINUE=54 +BREAK=55 +RETURN=56 +DISCARD=57 +DEMOTE=58 +UINT16CONSTANT=59 +INT16CONSTANT=60 +UINT32CONSTANT=61 +INT32CONSTANT=62 +UINT64CONSTANT=63 +INT64CONSTANT=64 +FLOAT16CONSTANT=65 +FLOAT32CONSTANT=66 +FLOAT64CONSTANT=67 +BOOLCONSTANT=68 +BOOL=69 +BVEC2=70 +BVEC3=71 +BVEC4=72 +INT8=73 +I8VEC2=74 +I8VEC3=75 +I8VEC4=76 +UINT8=77 +U8VEC2=78 +U8VEC3=79 +U8VEC4=80 +INT16=81 +I16VEC2=82 +I16VEC3=83 +I16VEC4=84 +UINT16=85 +U16VEC2=86 +U16VEC3=87 +U16VEC4=88 +INT32=89 +I32VEC2=90 +I32VEC3=91 +I32VEC4=92 +UINT32=93 +U32VEC2=94 +U32VEC3=95 +U32VEC4=96 +INT64=97 +I64VEC2=98 +I64VEC3=99 +I64VEC4=100 +UINT64=101 +U64VEC2=102 +U64VEC3=103 +U64VEC4=104 +FLOAT16=105 +F16VEC2=106 +F16VEC3=107 +F16VEC4=108 +F16MAT2X2=109 +F16MAT2X3=110 +F16MAT2X4=111 +F16MAT3X2=112 +F16MAT3X3=113 +F16MAT3X4=114 +F16MAT4X2=115 +F16MAT4X3=116 +F16MAT4X4=117 +FLOAT32=118 +F32VEC2=119 +F32VEC3=120 +F32VEC4=121 +F32MAT2X2=122 +F32MAT2X3=123 +F32MAT2X4=124 +F32MAT3X2=125 +F32MAT3X3=126 +F32MAT3X4=127 +F32MAT4X2=128 +F32MAT4X3=129 +F32MAT4X4=130 +FLOAT64=131 +F64VEC2=132 +F64VEC3=133 +F64VEC4=134 +F64MAT2X2=135 +F64MAT2X3=136 +F64MAT2X4=137 +F64MAT3X2=138 +F64MAT3X3=139 +F64MAT3X4=140 +F64MAT4X2=141 +F64MAT4X3=142 +F64MAT4X4=143 +IMAGE1D=144 +IMAGE2D=145 +IMAGE3D=146 +UIMAGE1D=147 +UIMAGE2D=148 +UIMAGE3D=149 +IIMAGE1D=150 +IIMAGE2D=151 +IIMAGE3D=152 +SAMPLER1D=153 +SAMPLER2D=154 +SAMPLER3D=155 +SAMPLER2DRECT=156 +SAMPLER1DSHADOW=157 +SAMPLER2DSHADOW=158 +SAMPLER2DRECTSHADOW=159 +SAMPLER1DARRAY=160 +SAMPLER2DARRAY=161 +SAMPLER1DARRAYSHADOW=162 +SAMPLER2DARRAYSHADOW=163 +ISAMPLER1D=164 +ISAMPLER2D=165 +ISAMPLER2DRECT=166 +ISAMPLER3D=167 +ISAMPLER1DARRAY=168 +ISAMPLER2DARRAY=169 +USAMPLER1D=170 +USAMPLER2D=171 +USAMPLER2DRECT=172 +USAMPLER3D=173 +USAMPLER1DARRAY=174 +USAMPLER2DARRAY=175 +SAMPLER2DMS=176 +ISAMPLER2DMS=177 +USAMPLER2DMS=178 +SAMPLER2DMSARRAY=179 +ISAMPLER2DMSARRAY=180 +USAMPLER2DMSARRAY=181 +IMAGE2DRECT=182 +IMAGE1DARRAY=183 +IMAGE2DARRAY=184 +IMAGE2DMS=185 +IMAGE2DMSARRAY=186 +IIMAGE2DRECT=187 +IIMAGE1DARRAY=188 +IIMAGE2DARRAY=189 +IIMAGE2DMS=190 +IIMAGE2DMSARRAY=191 +UIMAGE2DRECT=192 +UIMAGE1DARRAY=193 +UIMAGE2DARRAY=194 +UIMAGE2DMS=195 +UIMAGE2DMSARRAY=196 +SAMPLERCUBESHADOW=197 +SAMPLERCUBEARRAYSHADOW=198 +SAMPLERCUBE=199 +ISAMPLERCUBE=200 +USAMPLERCUBE=201 +SAMPLERBUFFER=202 +ISAMPLERBUFFER=203 +USAMPLERBUFFER=204 +SAMPLERCUBEARRAY=205 +ISAMPLERCUBEARRAY=206 +USAMPLERCUBEARRAY=207 +IMAGECUBE=208 +UIMAGECUBE=209 +IIMAGECUBE=210 +IMAGEBUFFER=211 +IIMAGEBUFFER=212 +UIMAGEBUFFER=213 +IMAGECUBEARRAY=214 +IIMAGECUBEARRAY=215 +UIMAGECUBEARRAY=216 +INC_OP=217 +DEC_OP=218 +VOID=219 +LEFT_OP=220 +RIGHT_OP=221 +LE_OP=222 +GE_OP=223 +EQ_OP=224 +NE_OP=225 +LOGICAL_AND_OP=226 +LOGICAL_XOR_OP=227 +LOGICAL_OR_OP=228 +MUL_ASSIGN=229 +DIV_ASSIGN=230 +MOD_ASSIGN=231 +ADD_ASSIGN=232 +SUB_ASSIGN=233 +LEFT_ASSIGN=234 +RIGHT_ASSIGN=235 +AND_ASSIGN=236 +XOR_ASSIGN=237 +OR_ASSIGN=238 +LPAREN=239 +RPAREN=240 +LBRACE=241 +RBRACE=242 +SEMICOLON=243 +LBRACKET=244 +RBRACKET=245 +COMMA=246 +DOT=247 +PLUS_OP=248 +MINUS_OP=249 +LOGICAL_NOT_OP=250 +BITWISE_NEG_OP=251 +TIMES_OP=252 +DIV_OP=253 +MOD_OP=254 +LT_OP=255 +GT_OP=256 +BITWISE_AND_OP=257 +BITWISE_OR_OP=258 +BITWISE_XOR_OP=259 +QUERY_OP=260 +ASSIGN_OP=261 +PP_ENTER_MODE=262 +PP_EMPTY=263 +NR_LINE=264 +NR=265 +IDENTIFIER=266 +LINE_CONTINUE=267 +LINE_COMMENT=268 +BLOCK_COMMENT=269 +WS=270 +EOL=271 +NR_EXTENSION=272 +NR_VERSION=273 +NR_CUSTOM=274 +NR_INCLUDE=275 +NR_PRAGMA=276 +NR_PRAGMA_DEBUG=277 +NR_PRAGMA_OPTIMIZE=278 +NR_PRAGMA_INVARIANT=279 +NR_ON=280 +NR_OFF=281 +NR_ALL=282 +NR_REQUIRE=283 +NR_ENABLE=284 +NR_WARN=285 +NR_DISABLE=286 +NR_COLON=287 +NR_LPAREN=288 +NR_RPAREN=289 +NR_STDGL=290 +NR_CORE=291 +NR_COMPATIBILITY=292 +NR_ES=293 +NR_GLSL_110=294 +NR_GLSL_120=295 +NR_GLSLES_100=296 +NR_GLSL_130=297 +NR_GLSL_140=298 +NR_GLSL_150=299 +NR_GLSL_330=300 +NR_GLSLES_300=301 +NR_GLSLES_310=302 +NR_GLSLES_320=303 +NR_GLSL_400=304 +NR_GLSL_410=305 +NR_GLSL_420=306 +NR_GLSL_430=307 +NR_GLSL_440=308 +NR_GLSL_450=309 +NR_GLSL_460=310 +NR_STRING_START=311 +NR_STRING_START_ANGLE=312 +NR_INTCONSTANT=313 +NR_IDENTIFIER=314 +NR_LINE_CONTINUE=315 +NR_LINE_COMMENT=316 +NR_BLOCK_COMMENT=317 +NR_EOL=318 +NR_WS=319 +S_CONTENT=320 +S_STRING_END=321 +S_CONTENT_ANGLE=322 +S_STRING_END_ANGLE=323 +C_LINE_COMMENT=324 +C_BLOCK_COMMENT=325 +C_EOL=326 +C_WS=327 +C_CONTENT=328 +PP_LINE_CONTINUE=329 +PP_LINE_COMMENT=330 +PP_BLOCK_COMMENT=331 +PP_EOL=332 +PP_CONTENT=333 +'uniform'=2 +'buffer'=3 +'in'=4 +'out'=5 +'inout'=6 +'highp'=7 +'mediump'=8 +'lowp'=9 +'precision'=10 +'const'=11 +'precise'=12 +'smooth'=14 +'flat'=15 +'centroid'=16 +'attribute'=17 +'volatile'=18 +'varying'=19 +'shared'=20 +'layout'=21 +'.length()'=22 +'noperspective'=23 +'sample'=24 +'patch'=25 +'coherent'=26 +'restrict'=27 +'readonly'=28 +'writeonly'=29 +'subroutine'=30 +'devicecoherent'=31 +'queuefamilycoherent'=32 +'workgroupcoherent'=33 +'subgroupcoherent'=34 +'nonprivate'=35 +'rayPayloadEXT'=36 +'rayPayloadInEXT'=37 +'hitAttributeEXT'=38 +'callableDataEXT'=39 +'callableDataInEXT'=40 +'ignoreIntersectionEXT'=41 +'terminateRayEXT'=42 +'accelerationStructureEXT'=43 +'atomic_uint'=44 +'struct'=45 +'if'=46 +'else'=47 +'switch'=48 +'case'=49 +'default'=50 +'while'=51 +'do'=52 +'for'=53 +'continue'=54 +'break'=55 +'return'=56 +'discard'=57 +'demote'=58 +'bool'=69 +'bvec2'=70 +'bvec3'=71 +'bvec4'=72 +'int8_t'=73 +'i8vec2'=74 +'i8vec3'=75 +'i8vec4'=76 +'uint8_t'=77 +'u8vec2'=78 +'u8vec3'=79 +'u8vec4'=80 +'int16_t'=81 +'i16vec2'=82 +'i16vec3'=83 +'i16vec4'=84 +'uint16_t'=85 +'u16vec2'=86 +'u16vec3'=87 +'u16vec4'=88 +'int64_t'=97 +'i64vec2'=98 +'i64vec3'=99 +'i64vec4'=100 +'uint64_t'=101 +'u64vec2'=102 +'u64vec3'=103 +'u64vec4'=104 +'float16_t'=105 +'f16vec2'=106 +'f16vec3'=107 +'f16vec4'=108 +'f16mat2x3'=110 +'f16mat2x4'=111 +'f16mat3x2'=112 +'f16mat3x4'=114 +'f16mat4x2'=115 +'f16mat4x3'=116 +'image1D'=144 +'image2D'=145 +'image3D'=146 +'uimage1D'=147 +'uimage2D'=148 +'uimage3D'=149 +'iimage1D'=150 +'iimage2D'=151 +'iimage3D'=152 +'sampler1D'=153 +'sampler2D'=154 +'sampler3D'=155 +'sampler2DRect'=156 +'sampler1DShadow'=157 +'sampler2DShadow'=158 +'sampler2DRectShadow'=159 +'sampler1DArray'=160 +'sampler2DArray'=161 +'sampler1DArrayShadow'=162 +'sampler2DArrayShadow'=163 +'isampler1D'=164 +'isampler2D'=165 +'isampler2DRect'=166 +'isampler3D'=167 +'isampler1DArray'=168 +'isampler2DArray'=169 +'usampler1D'=170 +'usampler2D'=171 +'usampler2DRect'=172 +'usampler3D'=173 +'usampler1DArray'=174 +'usampler2DArray'=175 +'sampler2DMS'=176 +'isampler2DMS'=177 +'usampler2DMS'=178 +'sampler2DMSArray'=179 +'isampler2DMSArray'=180 +'usampler2DMSArray'=181 +'image2DRect'=182 +'image1DArray'=183 +'image2DArray'=184 +'image2DMS'=185 +'image2DMSArray'=186 +'iimage2DRect'=187 +'iimage1DArray'=188 +'iimage2DArray'=189 +'iimage2DMS'=190 +'iimage2DMSArray'=191 +'uimage2DRect'=192 +'uimage1DArray'=193 +'uimage2DArray'=194 +'uimage2DMS'=195 +'uimage2DMSArray'=196 +'samplerCubeShadow'=197 +'samplerCubeArrayShadow'=198 +'samplerCube'=199 +'isamplerCube'=200 +'usamplerCube'=201 +'samplerBuffer'=202 +'isamplerBuffer'=203 +'usamplerBuffer'=204 +'samplerCubeArray'=205 +'isamplerCubeArray'=206 +'usamplerCubeArray'=207 +'imageCube'=208 +'uimageCube'=209 +'iimageCube'=210 +'imageBuffer'=211 +'iimageBuffer'=212 +'uimageBuffer'=213 +'imageCubeArray'=214 +'iimageCubeArray'=215 +'uimageCubeArray'=216 +'++'=217 +'--'=218 +'void'=219 +'<<'=220 +'>>'=221 +'<='=222 +'>='=223 +'=='=224 +'!='=225 +'&&'=226 +'^^'=227 +'||'=228 +'*='=229 +'/='=230 +'%='=231 +'+='=232 +'-='=233 +'<<='=234 +'>>='=235 +'&='=236 +'^='=237 +'|='=238 +'{'=241 +'}'=242 +';'=243 +'['=244 +']'=245 +','=246 +'.'=247 +'+'=248 +'-'=249 +'!'=250 +'~'=251 +'*'=252 +'/'=253 +'%'=254 +'<'=255 +'&'=257 +'|'=258 +'^'=259 +'?'=260 +'='=261 +'#'=265 +'extension'=272 +'version'=273 +'include'=275 +'pragma'=276 +'debug'=277 +'optimize'=278 +'on'=280 +'off'=281 +'all'=282 +'require'=283 +'enable'=284 +'warn'=285 +'disable'=286 +'STDGL'=290 +'core'=291 +'compatibility'=292 +'es'=293 +'110'=294 +'120'=295 +'100'=296 +'130'=297 +'140'=298 +'150'=299 +'330'=300 +'300'=301 +'310'=302 +'320'=303 +'400'=304 +'410'=305 +'420'=306 +'430'=307 +'440'=308 +'450'=309 +'460'=310 +'"'=321 diff --git a/src/main/java/io/github/douira/glsl_transformer/GLSLParser.interp b/src/main/java/io/github/douira/glsl_transformer/GLSLParser.interp new file mode 100644 index 0000000000..37c893859c --- /dev/null +++ b/src/main/java/io/github/douira/glsl_transformer/GLSLParser.interp @@ -0,0 +1,729 @@ +token literal names: +null +null +'uniform' +'buffer' +'in' +'out' +'inout' +'highp' +'mediump' +'lowp' +'precision' +'const' +'precise' +null +'smooth' +'flat' +'centroid' +'attribute' +'volatile' +'varying' +'shared' +'layout' +'.length()' +'noperspective' +'sample' +'patch' +'coherent' +'restrict' +'readonly' +'writeonly' +'subroutine' +'devicecoherent' +'queuefamilycoherent' +'workgroupcoherent' +'subgroupcoherent' +'nonprivate' +'rayPayloadEXT' +'rayPayloadInEXT' +'hitAttributeEXT' +'callableDataEXT' +'callableDataInEXT' +'ignoreIntersectionEXT' +'terminateRayEXT' +'accelerationStructureEXT' +'atomic_uint' +'struct' +'if' +'else' +'switch' +'case' +'default' +'while' +'do' +'for' +'continue' +'break' +'return' +'discard' +'demote' +null +null +null +null +null +null +null +null +null +null +'bool' +'bvec2' +'bvec3' +'bvec4' +'int8_t' +'i8vec2' +'i8vec3' +'i8vec4' +'uint8_t' +'u8vec2' +'u8vec3' +'u8vec4' +'int16_t' +'i16vec2' +'i16vec3' +'i16vec4' +'uint16_t' +'u16vec2' +'u16vec3' +'u16vec4' +null +null +null +null +null +null +null +null +'int64_t' +'i64vec2' +'i64vec3' +'i64vec4' +'uint64_t' +'u64vec2' +'u64vec3' +'u64vec4' +'float16_t' +'f16vec2' +'f16vec3' +'f16vec4' +null +'f16mat2x3' +'f16mat2x4' +'f16mat3x2' +null +'f16mat3x4' +'f16mat4x2' +'f16mat4x3' +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +'image1D' +'image2D' +'image3D' +'uimage1D' +'uimage2D' +'uimage3D' +'iimage1D' +'iimage2D' +'iimage3D' +'sampler1D' +'sampler2D' +'sampler3D' +'sampler2DRect' +'sampler1DShadow' +'sampler2DShadow' +'sampler2DRectShadow' +'sampler1DArray' +'sampler2DArray' +'sampler1DArrayShadow' +'sampler2DArrayShadow' +'isampler1D' +'isampler2D' +'isampler2DRect' +'isampler3D' +'isampler1DArray' +'isampler2DArray' +'usampler1D' +'usampler2D' +'usampler2DRect' +'usampler3D' +'usampler1DArray' +'usampler2DArray' +'sampler2DMS' +'isampler2DMS' +'usampler2DMS' +'sampler2DMSArray' +'isampler2DMSArray' +'usampler2DMSArray' +'image2DRect' +'image1DArray' +'image2DArray' +'image2DMS' +'image2DMSArray' +'iimage2DRect' +'iimage1DArray' +'iimage2DArray' +'iimage2DMS' +'iimage2DMSArray' +'uimage2DRect' +'uimage1DArray' +'uimage2DArray' +'uimage2DMS' +'uimage2DMSArray' +'samplerCubeShadow' +'samplerCubeArrayShadow' +'samplerCube' +'isamplerCube' +'usamplerCube' +'samplerBuffer' +'isamplerBuffer' +'usamplerBuffer' +'samplerCubeArray' +'isamplerCubeArray' +'usamplerCubeArray' +'imageCube' +'uimageCube' +'iimageCube' +'imageBuffer' +'iimageBuffer' +'uimageBuffer' +'imageCubeArray' +'iimageCubeArray' +'uimageCubeArray' +'++' +'--' +'void' +'<<' +'>>' +'<=' +'>=' +'==' +'!=' +'&&' +'^^' +'||' +'*=' +'/=' +'%=' +'+=' +'-=' +'<<=' +'>>=' +'&=' +'^=' +'|=' +null +null +'{' +'}' +';' +'[' +']' +',' +'.' +'+' +'-' +'!' +'~' +'*' +'/' +'%' +'<' +null +'&' +'|' +'^' +'?' +'=' +null +null +null +'#' +null +null +null +null +null +null +'extension' +'version' +null +'include' +'pragma' +'debug' +'optimize' +null +'on' +'off' +'all' +'require' +'enable' +'warn' +'disable' +null +null +null +'STDGL' +'core' +'compatibility' +'es' +'110' +'120' +'100' +'130' +'140' +'150' +'330' +'300' +'310' +'320' +'400' +'410' +'420' +'430' +'440' +'450' +'460' +null +null +null +null +null +null +null +null +null +null +'"' +null +null +null +null +null +null +null +null +null +null +null +null + +token symbolic names: +null +COLON +UNIFORM +BUFFER +IN +OUT +INOUT +HIGHP +MEDIUMP +LOWP +PRECISION +CONST +PRECISE +INVARIANT +SMOOTH +FLAT +CENTROID +ATTRIBUTE +VOLATILE +VARYING +SHARED +LAYOUT +DOT_LENGTH_METHOD_CALL +NOPERSPECTIVE +SAMPLE +PATCH +COHERENT +RESTRICT +READONLY +WRITEONLY +SUBROUTINE +DEVICECOHERENT +QUEUEFAMILYCOHERENT +WORKGROUPCOHERENT +SUBGROUPCOHERENT +NONPRIVATE +RAY_PAYLOAD_EXT +RAY_PAYLOAD_IN_EXT +HIT_ATTRIBUTE_EXT +CALLABLE_DATA_EXT +CALLABLE_DATA_IN_EXT +IGNORE_INTERSECTION_EXT +TERMINATE_RAY_EXT +ACCELERATION_STRUCTURE_EXT +ATOMIC_UINT +STRUCT +IF +ELSE +SWITCH +CASE +DEFAULT +WHILE +DO +FOR +CONTINUE +BREAK +RETURN +DISCARD +DEMOTE +UINT16CONSTANT +INT16CONSTANT +UINT32CONSTANT +INT32CONSTANT +UINT64CONSTANT +INT64CONSTANT +FLOAT16CONSTANT +FLOAT32CONSTANT +FLOAT64CONSTANT +BOOLCONSTANT +BOOL +BVEC2 +BVEC3 +BVEC4 +INT8 +I8VEC2 +I8VEC3 +I8VEC4 +UINT8 +U8VEC2 +U8VEC3 +U8VEC4 +INT16 +I16VEC2 +I16VEC3 +I16VEC4 +UINT16 +U16VEC2 +U16VEC3 +U16VEC4 +INT32 +I32VEC2 +I32VEC3 +I32VEC4 +UINT32 +U32VEC2 +U32VEC3 +U32VEC4 +INT64 +I64VEC2 +I64VEC3 +I64VEC4 +UINT64 +U64VEC2 +U64VEC3 +U64VEC4 +FLOAT16 +F16VEC2 +F16VEC3 +F16VEC4 +F16MAT2X2 +F16MAT2X3 +F16MAT2X4 +F16MAT3X2 +F16MAT3X3 +F16MAT3X4 +F16MAT4X2 +F16MAT4X3 +F16MAT4X4 +FLOAT32 +F32VEC2 +F32VEC3 +F32VEC4 +F32MAT2X2 +F32MAT2X3 +F32MAT2X4 +F32MAT3X2 +F32MAT3X3 +F32MAT3X4 +F32MAT4X2 +F32MAT4X3 +F32MAT4X4 +FLOAT64 +F64VEC2 +F64VEC3 +F64VEC4 +F64MAT2X2 +F64MAT2X3 +F64MAT2X4 +F64MAT3X2 +F64MAT3X3 +F64MAT3X4 +F64MAT4X2 +F64MAT4X3 +F64MAT4X4 +IMAGE1D +IMAGE2D +IMAGE3D +UIMAGE1D +UIMAGE2D +UIMAGE3D +IIMAGE1D +IIMAGE2D +IIMAGE3D +SAMPLER1D +SAMPLER2D +SAMPLER3D +SAMPLER2DRECT +SAMPLER1DSHADOW +SAMPLER2DSHADOW +SAMPLER2DRECTSHADOW +SAMPLER1DARRAY +SAMPLER2DARRAY +SAMPLER1DARRAYSHADOW +SAMPLER2DARRAYSHADOW +ISAMPLER1D +ISAMPLER2D +ISAMPLER2DRECT +ISAMPLER3D +ISAMPLER1DARRAY +ISAMPLER2DARRAY +USAMPLER1D +USAMPLER2D +USAMPLER2DRECT +USAMPLER3D +USAMPLER1DARRAY +USAMPLER2DARRAY +SAMPLER2DMS +ISAMPLER2DMS +USAMPLER2DMS +SAMPLER2DMSARRAY +ISAMPLER2DMSARRAY +USAMPLER2DMSARRAY +IMAGE2DRECT +IMAGE1DARRAY +IMAGE2DARRAY +IMAGE2DMS +IMAGE2DMSARRAY +IIMAGE2DRECT +IIMAGE1DARRAY +IIMAGE2DARRAY +IIMAGE2DMS +IIMAGE2DMSARRAY +UIMAGE2DRECT +UIMAGE1DARRAY +UIMAGE2DARRAY +UIMAGE2DMS +UIMAGE2DMSARRAY +SAMPLERCUBESHADOW +SAMPLERCUBEARRAYSHADOW +SAMPLERCUBE +ISAMPLERCUBE +USAMPLERCUBE +SAMPLERBUFFER +ISAMPLERBUFFER +USAMPLERBUFFER +SAMPLERCUBEARRAY +ISAMPLERCUBEARRAY +USAMPLERCUBEARRAY +IMAGECUBE +UIMAGECUBE +IIMAGECUBE +IMAGEBUFFER +IIMAGEBUFFER +UIMAGEBUFFER +IMAGECUBEARRAY +IIMAGECUBEARRAY +UIMAGECUBEARRAY +INC_OP +DEC_OP +VOID +LEFT_OP +RIGHT_OP +LE_OP +GE_OP +EQ_OP +NE_OP +LOGICAL_AND_OP +LOGICAL_XOR_OP +LOGICAL_OR_OP +MUL_ASSIGN +DIV_ASSIGN +MOD_ASSIGN +ADD_ASSIGN +SUB_ASSIGN +LEFT_ASSIGN +RIGHT_ASSIGN +AND_ASSIGN +XOR_ASSIGN +OR_ASSIGN +LPAREN +RPAREN +LBRACE +RBRACE +SEMICOLON +LBRACKET +RBRACKET +COMMA +DOT +PLUS_OP +MINUS_OP +LOGICAL_NOT_OP +BITWISE_NEG_OP +TIMES_OP +DIV_OP +MOD_OP +LT_OP +GT_OP +BITWISE_AND_OP +BITWISE_OR_OP +BITWISE_XOR_OP +QUERY_OP +ASSIGN_OP +PP_ENTER_MODE +PP_EMPTY +NR_LINE +NR +IDENTIFIER +LINE_CONTINUE +LINE_COMMENT +BLOCK_COMMENT +WS +EOL +NR_EXTENSION +NR_VERSION +NR_CUSTOM +NR_INCLUDE +NR_PRAGMA +NR_PRAGMA_DEBUG +NR_PRAGMA_OPTIMIZE +NR_PRAGMA_INVARIANT +NR_ON +NR_OFF +NR_ALL +NR_REQUIRE +NR_ENABLE +NR_WARN +NR_DISABLE +NR_COLON +NR_LPAREN +NR_RPAREN +NR_STDGL +NR_CORE +NR_COMPATIBILITY +NR_ES +NR_GLSL_110 +NR_GLSL_120 +NR_GLSLES_100 +NR_GLSL_130 +NR_GLSL_140 +NR_GLSL_150 +NR_GLSL_330 +NR_GLSLES_300 +NR_GLSLES_310 +NR_GLSLES_320 +NR_GLSL_400 +NR_GLSL_410 +NR_GLSL_420 +NR_GLSL_430 +NR_GLSL_440 +NR_GLSL_450 +NR_GLSL_460 +NR_STRING_START +NR_STRING_START_ANGLE +NR_INTCONSTANT +NR_IDENTIFIER +NR_LINE_CONTINUE +NR_LINE_COMMENT +NR_BLOCK_COMMENT +NR_EOL +NR_WS +S_CONTENT +S_STRING_END +S_CONTENT_ANGLE +S_STRING_END_ANGLE +C_LINE_COMMENT +C_BLOCK_COMMENT +C_EOL +C_WS +C_CONTENT +PP_LINE_CONTINUE +PP_LINE_COMMENT +PP_BLOCK_COMMENT +PP_EOL +PP_CONTENT + +rule names: +translationUnit +versionStatement +externalDeclaration +emptyDeclaration +pragmaDirective +extensionDirective +customDirective +includeDirective +layoutDefaults +functionDefinition +finiteExpression +expression +declaration +functionPrototype +functionParameterList +parameterDeclaration +attribute +singleAttribute +declarationMember +fullySpecifiedType +storageQualifier +layoutQualifier +layoutQualifierId +precisionQualifier +interpolationQualifier +invariantQualifier +preciseQualifier +typeQualifier +typeSpecifier +arraySpecifier +arraySpecifierSegment +builtinTypeSpecifierParseable +builtinTypeSpecifierFixed +structSpecifier +structBody +structMember +structDeclarator +initializer +statement +compoundStatement +declarationStatement +expressionStatement +emptyStatement +selectionStatement +iterationCondition +switchStatement +caseLabel +whileStatement +doWhileStatement +forStatement +jumpStatement +demoteStatement + + +atn: +[4, 1, 333, 681, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 1, 0, 3, 0, 106, 8, 0, 1, 0, 5, 0, 109, 8, 0, 10, 0, 12, 0, 112, 9, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 120, 8, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 132, 8, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 3, 4, 139, 8, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 3, 4, 150, 8, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 159, 8, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 3, 6, 166, 8, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 174, 8, 7, 1, 7, 1, 7, 1, 7, 3, 7, 179, 8, 7, 1, 7, 3, 7, 182, 8, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 3, 10, 202, 8, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 210, 8, 10, 10, 10, 12, 10, 213, 9, 10, 3, 10, 215, 8, 10, 1, 10, 1, 10, 1, 10, 3, 10, 220, 8, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 276, 8, 10, 10, 10, 12, 10, 279, 9, 10, 1, 11, 1, 11, 1, 11, 5, 11, 284, 8, 11, 10, 11, 12, 11, 287, 9, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 3, 12, 297, 8, 12, 3, 12, 299, 8, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 5, 12, 307, 8, 12, 10, 12, 12, 12, 310, 9, 12, 3, 12, 312, 8, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 5, 12, 325, 8, 12, 10, 12, 12, 12, 328, 9, 12, 3, 12, 330, 8, 12, 1, 12, 1, 12, 3, 12, 334, 8, 12, 1, 13, 3, 13, 337, 8, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 3, 13, 345, 8, 13, 1, 14, 1, 14, 1, 14, 5, 14, 350, 8, 14, 10, 14, 12, 14, 353, 9, 14, 3, 14, 355, 8, 14, 1, 15, 1, 15, 1, 15, 3, 15, 360, 8, 15, 3, 15, 362, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 5, 16, 369, 8, 16, 10, 16, 12, 16, 372, 9, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 3, 17, 380, 8, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 387, 8, 17, 1, 18, 1, 18, 3, 18, 391, 8, 18, 1, 18, 1, 18, 3, 18, 395, 8, 18, 1, 19, 3, 19, 398, 8, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 5, 20, 424, 8, 20, 10, 20, 12, 20, 427, 9, 20, 1, 20, 3, 20, 430, 8, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 3, 20, 442, 8, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 5, 21, 449, 8, 21, 10, 21, 12, 21, 452, 9, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 3, 22, 459, 8, 22, 1, 22, 3, 22, 462, 8, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 4, 27, 478, 8, 27, 11, 27, 12, 27, 479, 1, 28, 1, 28, 1, 28, 1, 28, 3, 28, 486, 8, 28, 1, 28, 3, 28, 489, 8, 28, 1, 29, 4, 29, 492, 8, 29, 11, 29, 12, 29, 493, 1, 30, 1, 30, 3, 30, 498, 8, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 3, 33, 508, 8, 33, 1, 33, 1, 33, 1, 34, 1, 34, 4, 34, 514, 8, 34, 11, 34, 12, 34, 515, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 524, 8, 35, 10, 35, 12, 35, 527, 9, 35, 1, 35, 1, 35, 1, 36, 1, 36, 3, 36, 533, 8, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 540, 8, 37, 10, 37, 12, 37, 543, 9, 37, 1, 37, 3, 37, 546, 8, 37, 3, 37, 548, 8, 37, 1, 37, 3, 37, 551, 8, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 565, 8, 38, 1, 39, 1, 39, 5, 39, 569, 8, 39, 10, 39, 12, 39, 572, 9, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 43, 3, 43, 584, 8, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 3, 43, 593, 8, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 3, 45, 601, 8, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 3, 46, 615, 8, 46, 1, 47, 3, 47, 618, 8, 47, 1, 47, 1, 47, 1, 47, 1, 47, 3, 47, 624, 8, 47, 1, 47, 1, 47, 1, 47, 1, 48, 3, 48, 630, 8, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 3, 49, 641, 8, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 3, 49, 648, 8, 49, 1, 49, 1, 49, 3, 49, 652, 8, 49, 1, 49, 1, 49, 3, 49, 656, 8, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 667, 8, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 676, 8, 50, 1, 51, 1, 51, 1, 51, 1, 51, 0, 1, 20, 52, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 0, 19, 1, 0, 294, 310, 1, 0, 291, 293, 1, 0, 277, 278, 1, 0, 280, 281, 1, 0, 283, 286, 1, 0, 2, 5, 1, 0, 59, 68, 2, 0, 217, 218, 248, 251, 1, 0, 252, 254, 1, 0, 248, 249, 1, 0, 220, 221, 2, 0, 222, 223, 255, 256, 1, 0, 224, 225, 2, 0, 229, 238, 261, 261, 1, 0, 217, 218, 1, 0, 7, 9, 2, 0, 14, 15, 23, 23, 1, 0, 69, 143, 3, 0, 43, 44, 144, 216, 219, 219, 777, 0, 105, 1, 0, 0, 0, 2, 115, 1, 0, 0, 0, 4, 131, 1, 0, 0, 0, 6, 133, 1, 0, 0, 0, 8, 135, 1, 0, 0, 0, 10, 153, 1, 0, 0, 0, 12, 162, 1, 0, 0, 0, 14, 169, 1, 0, 0, 0, 16, 185, 1, 0, 0, 0, 18, 189, 1, 0, 0, 0, 20, 219, 1, 0, 0, 0, 22, 280, 1, 0, 0, 0, 24, 333, 1, 0, 0, 0, 26, 336, 1, 0, 0, 0, 28, 354, 1, 0, 0, 0, 30, 356, 1, 0, 0, 0, 32, 363, 1, 0, 0, 0, 34, 379, 1, 0, 0, 0, 36, 388, 1, 0, 0, 0, 38, 397, 1, 0, 0, 0, 40, 441, 1, 0, 0, 0, 42, 443, 1, 0, 0, 0, 44, 461, 1, 0, 0, 0, 46, 463, 1, 0, 0, 0, 48, 465, 1, 0, 0, 0, 50, 467, 1, 0, 0, 0, 52, 469, 1, 0, 0, 0, 54, 477, 1, 0, 0, 0, 56, 485, 1, 0, 0, 0, 58, 491, 1, 0, 0, 0, 60, 495, 1, 0, 0, 0, 62, 501, 1, 0, 0, 0, 64, 503, 1, 0, 0, 0, 66, 505, 1, 0, 0, 0, 68, 511, 1, 0, 0, 0, 70, 519, 1, 0, 0, 0, 72, 530, 1, 0, 0, 0, 74, 550, 1, 0, 0, 0, 76, 564, 1, 0, 0, 0, 78, 566, 1, 0, 0, 0, 80, 575, 1, 0, 0, 0, 82, 577, 1, 0, 0, 0, 84, 580, 1, 0, 0, 0, 86, 583, 1, 0, 0, 0, 88, 594, 1, 0, 0, 0, 90, 600, 1, 0, 0, 0, 92, 614, 1, 0, 0, 0, 94, 617, 1, 0, 0, 0, 96, 629, 1, 0, 0, 0, 98, 640, 1, 0, 0, 0, 100, 675, 1, 0, 0, 0, 102, 677, 1, 0, 0, 0, 104, 106, 3, 2, 1, 0, 105, 104, 1, 0, 0, 0, 105, 106, 1, 0, 0, 0, 106, 110, 1, 0, 0, 0, 107, 109, 3, 4, 2, 0, 108, 107, 1, 0, 0, 0, 109, 112, 1, 0, 0, 0, 110, 108, 1, 0, 0, 0, 110, 111, 1, 0, 0, 0, 111, 113, 1, 0, 0, 0, 112, 110, 1, 0, 0, 0, 113, 114, 5, 0, 0, 1, 114, 1, 1, 0, 0, 0, 115, 116, 5, 265, 0, 0, 116, 117, 5, 273, 0, 0, 117, 119, 7, 0, 0, 0, 118, 120, 7, 1, 0, 0, 119, 118, 1, 0, 0, 0, 119, 120, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 5, 318, 0, 0, 122, 3, 1, 0, 0, 0, 123, 132, 3, 18, 9, 0, 124, 132, 3, 24, 12, 0, 125, 132, 3, 8, 4, 0, 126, 132, 3, 10, 5, 0, 127, 132, 3, 12, 6, 0, 128, 132, 3, 14, 7, 0, 129, 132, 3, 16, 8, 0, 130, 132, 3, 6, 3, 0, 131, 123, 1, 0, 0, 0, 131, 124, 1, 0, 0, 0, 131, 125, 1, 0, 0, 0, 131, 126, 1, 0, 0, 0, 131, 127, 1, 0, 0, 0, 131, 128, 1, 0, 0, 0, 131, 129, 1, 0, 0, 0, 131, 130, 1, 0, 0, 0, 132, 5, 1, 0, 0, 0, 133, 134, 5, 243, 0, 0, 134, 7, 1, 0, 0, 0, 135, 136, 5, 265, 0, 0, 136, 138, 5, 276, 0, 0, 137, 139, 5, 290, 0, 0, 138, 137, 1, 0, 0, 0, 138, 139, 1, 0, 0, 0, 139, 149, 1, 0, 0, 0, 140, 150, 5, 314, 0, 0, 141, 142, 7, 2, 0, 0, 142, 143, 5, 288, 0, 0, 143, 144, 7, 3, 0, 0, 144, 150, 5, 289, 0, 0, 145, 146, 5, 279, 0, 0, 146, 147, 5, 288, 0, 0, 147, 148, 5, 282, 0, 0, 148, 150, 5, 289, 0, 0, 149, 140, 1, 0, 0, 0, 149, 141, 1, 0, 0, 0, 149, 145, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 152, 5, 318, 0, 0, 152, 9, 1, 0, 0, 0, 153, 154, 5, 265, 0, 0, 154, 155, 5, 272, 0, 0, 155, 158, 5, 314, 0, 0, 156, 157, 5, 287, 0, 0, 157, 159, 7, 4, 0, 0, 158, 156, 1, 0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 160, 1, 0, 0, 0, 160, 161, 5, 318, 0, 0, 161, 11, 1, 0, 0, 0, 162, 163, 5, 265, 0, 0, 163, 165, 5, 274, 0, 0, 164, 166, 5, 328, 0, 0, 165, 164, 1, 0, 0, 0, 165, 166, 1, 0, 0, 0, 166, 167, 1, 0, 0, 0, 167, 168, 5, 326, 0, 0, 168, 13, 1, 0, 0, 0, 169, 170, 5, 265, 0, 0, 170, 181, 5, 275, 0, 0, 171, 173, 5, 311, 0, 0, 172, 174, 5, 320, 0, 0, 173, 172, 1, 0, 0, 0, 173, 174, 1, 0, 0, 0, 174, 175, 1, 0, 0, 0, 175, 182, 5, 321, 0, 0, 176, 178, 5, 312, 0, 0, 177, 179, 5, 322, 0, 0, 178, 177, 1, 0, 0, 0, 178, 179, 1, 0, 0, 0, 179, 180, 1, 0, 0, 0, 180, 182, 5, 323, 0, 0, 181, 171, 1, 0, 0, 0, 181, 176, 1, 0, 0, 0, 182, 183, 1, 0, 0, 0, 183, 184, 5, 318, 0, 0, 184, 15, 1, 0, 0, 0, 185, 186, 3, 42, 21, 0, 186, 187, 7, 5, 0, 0, 187, 188, 5, 243, 0, 0, 188, 17, 1, 0, 0, 0, 189, 190, 3, 26, 13, 0, 190, 191, 3, 78, 39, 0, 191, 19, 1, 0, 0, 0, 192, 193, 6, 10, -1, 0, 193, 220, 5, 266, 0, 0, 194, 220, 7, 6, 0, 0, 195, 196, 5, 239, 0, 0, 196, 197, 3, 22, 11, 0, 197, 198, 5, 240, 0, 0, 198, 220, 1, 0, 0, 0, 199, 202, 5, 266, 0, 0, 200, 202, 3, 56, 28, 0, 201, 199, 1, 0, 0, 0, 201, 200, 1, 0, 0, 0, 202, 203, 1, 0, 0, 0, 203, 214, 5, 239, 0, 0, 204, 215, 1, 0, 0, 0, 205, 215, 5, 219, 0, 0, 206, 211, 3, 20, 10, 0, 207, 208, 5, 246, 0, 0, 208, 210, 3, 20, 10, 0, 209, 207, 1, 0, 0, 0, 210, 213, 1, 0, 0, 0, 211, 209, 1, 0, 0, 0, 211, 212, 1, 0, 0, 0, 212, 215, 1, 0, 0, 0, 213, 211, 1, 0, 0, 0, 214, 204, 1, 0, 0, 0, 214, 205, 1, 0, 0, 0, 214, 206, 1, 0, 0, 0, 215, 216, 1, 0, 0, 0, 216, 220, 5, 240, 0, 0, 217, 218, 7, 7, 0, 0, 218, 220, 3, 20, 10, 14, 219, 192, 1, 0, 0, 0, 219, 194, 1, 0, 0, 0, 219, 195, 1, 0, 0, 0, 219, 201, 1, 0, 0, 0, 219, 217, 1, 0, 0, 0, 220, 277, 1, 0, 0, 0, 221, 222, 10, 13, 0, 0, 222, 223, 7, 8, 0, 0, 223, 276, 3, 20, 10, 14, 224, 225, 10, 12, 0, 0, 225, 226, 7, 9, 0, 0, 226, 276, 3, 20, 10, 13, 227, 228, 10, 11, 0, 0, 228, 229, 7, 10, 0, 0, 229, 276, 3, 20, 10, 12, 230, 231, 10, 10, 0, 0, 231, 232, 7, 11, 0, 0, 232, 276, 3, 20, 10, 11, 233, 234, 10, 9, 0, 0, 234, 235, 7, 12, 0, 0, 235, 276, 3, 20, 10, 10, 236, 237, 10, 8, 0, 0, 237, 238, 5, 257, 0, 0, 238, 276, 3, 20, 10, 9, 239, 240, 10, 7, 0, 0, 240, 241, 5, 259, 0, 0, 241, 276, 3, 20, 10, 8, 242, 243, 10, 6, 0, 0, 243, 244, 5, 258, 0, 0, 244, 276, 3, 20, 10, 7, 245, 246, 10, 5, 0, 0, 246, 247, 5, 226, 0, 0, 247, 276, 3, 20, 10, 6, 248, 249, 10, 4, 0, 0, 249, 250, 5, 227, 0, 0, 250, 276, 3, 20, 10, 5, 251, 252, 10, 3, 0, 0, 252, 253, 5, 228, 0, 0, 253, 276, 3, 20, 10, 4, 254, 255, 10, 2, 0, 0, 255, 256, 5, 260, 0, 0, 256, 257, 3, 20, 10, 0, 257, 258, 5, 1, 0, 0, 258, 259, 3, 20, 10, 2, 259, 276, 1, 0, 0, 0, 260, 261, 10, 1, 0, 0, 261, 262, 7, 13, 0, 0, 262, 276, 3, 20, 10, 1, 263, 264, 10, 19, 0, 0, 264, 265, 5, 244, 0, 0, 265, 266, 3, 22, 11, 0, 266, 267, 5, 245, 0, 0, 267, 276, 1, 0, 0, 0, 268, 269, 10, 18, 0, 0, 269, 276, 5, 22, 0, 0, 270, 271, 10, 16, 0, 0, 271, 272, 5, 247, 0, 0, 272, 276, 5, 266, 0, 0, 273, 274, 10, 15, 0, 0, 274, 276, 7, 14, 0, 0, 275, 221, 1, 0, 0, 0, 275, 224, 1, 0, 0, 0, 275, 227, 1, 0, 0, 0, 275, 230, 1, 0, 0, 0, 275, 233, 1, 0, 0, 0, 275, 236, 1, 0, 0, 0, 275, 239, 1, 0, 0, 0, 275, 242, 1, 0, 0, 0, 275, 245, 1, 0, 0, 0, 275, 248, 1, 0, 0, 0, 275, 251, 1, 0, 0, 0, 275, 254, 1, 0, 0, 0, 275, 260, 1, 0, 0, 0, 275, 263, 1, 0, 0, 0, 275, 268, 1, 0, 0, 0, 275, 270, 1, 0, 0, 0, 275, 273, 1, 0, 0, 0, 276, 279, 1, 0, 0, 0, 277, 275, 1, 0, 0, 0, 277, 278, 1, 0, 0, 0, 278, 21, 1, 0, 0, 0, 279, 277, 1, 0, 0, 0, 280, 285, 3, 20, 10, 0, 281, 282, 5, 246, 0, 0, 282, 284, 3, 20, 10, 0, 283, 281, 1, 0, 0, 0, 284, 287, 1, 0, 0, 0, 285, 283, 1, 0, 0, 0, 285, 286, 1, 0, 0, 0, 286, 23, 1, 0, 0, 0, 287, 285, 1, 0, 0, 0, 288, 289, 3, 26, 13, 0, 289, 290, 5, 243, 0, 0, 290, 334, 1, 0, 0, 0, 291, 292, 3, 54, 27, 0, 292, 293, 5, 266, 0, 0, 293, 298, 3, 68, 34, 0, 294, 296, 5, 266, 0, 0, 295, 297, 3, 58, 29, 0, 296, 295, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 299, 1, 0, 0, 0, 298, 294, 1, 0, 0, 0, 298, 299, 1, 0, 0, 0, 299, 300, 1, 0, 0, 0, 300, 301, 5, 243, 0, 0, 301, 334, 1, 0, 0, 0, 302, 311, 3, 54, 27, 0, 303, 308, 5, 266, 0, 0, 304, 305, 5, 246, 0, 0, 305, 307, 5, 266, 0, 0, 306, 304, 1, 0, 0, 0, 307, 310, 1, 0, 0, 0, 308, 306, 1, 0, 0, 0, 308, 309, 1, 0, 0, 0, 309, 312, 1, 0, 0, 0, 310, 308, 1, 0, 0, 0, 311, 303, 1, 0, 0, 0, 311, 312, 1, 0, 0, 0, 312, 313, 1, 0, 0, 0, 313, 314, 5, 243, 0, 0, 314, 334, 1, 0, 0, 0, 315, 316, 5, 10, 0, 0, 316, 317, 3, 46, 23, 0, 317, 318, 3, 56, 28, 0, 318, 319, 5, 243, 0, 0, 319, 334, 1, 0, 0, 0, 320, 329, 3, 38, 19, 0, 321, 326, 3, 36, 18, 0, 322, 323, 5, 246, 0, 0, 323, 325, 3, 36, 18, 0, 324, 322, 1, 0, 0, 0, 325, 328, 1, 0, 0, 0, 326, 324, 1, 0, 0, 0, 326, 327, 1, 0, 0, 0, 327, 330, 1, 0, 0, 0, 328, 326, 1, 0, 0, 0, 329, 321, 1, 0, 0, 0, 329, 330, 1, 0, 0, 0, 330, 331, 1, 0, 0, 0, 331, 332, 5, 243, 0, 0, 332, 334, 1, 0, 0, 0, 333, 288, 1, 0, 0, 0, 333, 291, 1, 0, 0, 0, 333, 302, 1, 0, 0, 0, 333, 315, 1, 0, 0, 0, 333, 320, 1, 0, 0, 0, 334, 25, 1, 0, 0, 0, 335, 337, 3, 32, 16, 0, 336, 335, 1, 0, 0, 0, 336, 337, 1, 0, 0, 0, 337, 338, 1, 0, 0, 0, 338, 339, 3, 38, 19, 0, 339, 340, 5, 266, 0, 0, 340, 341, 5, 239, 0, 0, 341, 342, 3, 28, 14, 0, 342, 344, 5, 240, 0, 0, 343, 345, 3, 32, 16, 0, 344, 343, 1, 0, 0, 0, 344, 345, 1, 0, 0, 0, 345, 27, 1, 0, 0, 0, 346, 351, 3, 30, 15, 0, 347, 348, 5, 246, 0, 0, 348, 350, 3, 30, 15, 0, 349, 347, 1, 0, 0, 0, 350, 353, 1, 0, 0, 0, 351, 349, 1, 0, 0, 0, 351, 352, 1, 0, 0, 0, 352, 355, 1, 0, 0, 0, 353, 351, 1, 0, 0, 0, 354, 346, 1, 0, 0, 0, 354, 355, 1, 0, 0, 0, 355, 29, 1, 0, 0, 0, 356, 361, 3, 38, 19, 0, 357, 359, 5, 266, 0, 0, 358, 360, 3, 58, 29, 0, 359, 358, 1, 0, 0, 0, 359, 360, 1, 0, 0, 0, 360, 362, 1, 0, 0, 0, 361, 357, 1, 0, 0, 0, 361, 362, 1, 0, 0, 0, 362, 31, 1, 0, 0, 0, 363, 364, 5, 244, 0, 0, 364, 365, 5, 244, 0, 0, 365, 370, 3, 34, 17, 0, 366, 367, 5, 246, 0, 0, 367, 369, 3, 34, 17, 0, 368, 366, 1, 0, 0, 0, 369, 372, 1, 0, 0, 0, 370, 368, 1, 0, 0, 0, 370, 371, 1, 0, 0, 0, 371, 373, 1, 0, 0, 0, 372, 370, 1, 0, 0, 0, 373, 374, 5, 245, 0, 0, 374, 375, 5, 245, 0, 0, 375, 33, 1, 0, 0, 0, 376, 377, 5, 266, 0, 0, 377, 378, 5, 1, 0, 0, 378, 380, 5, 1, 0, 0, 379, 376, 1, 0, 0, 0, 379, 380, 1, 0, 0, 0, 380, 381, 1, 0, 0, 0, 381, 386, 5, 266, 0, 0, 382, 383, 5, 239, 0, 0, 383, 384, 3, 22, 11, 0, 384, 385, 5, 240, 0, 0, 385, 387, 1, 0, 0, 0, 386, 382, 1, 0, 0, 0, 386, 387, 1, 0, 0, 0, 387, 35, 1, 0, 0, 0, 388, 390, 5, 266, 0, 0, 389, 391, 3, 58, 29, 0, 390, 389, 1, 0, 0, 0, 390, 391, 1, 0, 0, 0, 391, 394, 1, 0, 0, 0, 392, 393, 5, 261, 0, 0, 393, 395, 3, 74, 37, 0, 394, 392, 1, 0, 0, 0, 394, 395, 1, 0, 0, 0, 395, 37, 1, 0, 0, 0, 396, 398, 3, 54, 27, 0, 397, 396, 1, 0, 0, 0, 397, 398, 1, 0, 0, 0, 398, 399, 1, 0, 0, 0, 399, 400, 3, 56, 28, 0, 400, 39, 1, 0, 0, 0, 401, 442, 5, 11, 0, 0, 402, 442, 5, 4, 0, 0, 403, 442, 5, 5, 0, 0, 404, 442, 5, 6, 0, 0, 405, 442, 5, 16, 0, 0, 406, 442, 5, 25, 0, 0, 407, 442, 5, 24, 0, 0, 408, 442, 5, 2, 0, 0, 409, 442, 5, 19, 0, 0, 410, 442, 5, 17, 0, 0, 411, 442, 5, 3, 0, 0, 412, 442, 5, 20, 0, 0, 413, 442, 5, 27, 0, 0, 414, 442, 5, 18, 0, 0, 415, 442, 5, 26, 0, 0, 416, 442, 5, 28, 0, 0, 417, 442, 5, 29, 0, 0, 418, 429, 5, 30, 0, 0, 419, 420, 5, 239, 0, 0, 420, 425, 5, 266, 0, 0, 421, 422, 5, 246, 0, 0, 422, 424, 5, 266, 0, 0, 423, 421, 1, 0, 0, 0, 424, 427, 1, 0, 0, 0, 425, 423, 1, 0, 0, 0, 425, 426, 1, 0, 0, 0, 426, 428, 1, 0, 0, 0, 427, 425, 1, 0, 0, 0, 428, 430, 5, 240, 0, 0, 429, 419, 1, 0, 0, 0, 429, 430, 1, 0, 0, 0, 430, 442, 1, 0, 0, 0, 431, 442, 5, 31, 0, 0, 432, 442, 5, 32, 0, 0, 433, 442, 5, 33, 0, 0, 434, 442, 5, 34, 0, 0, 435, 442, 5, 35, 0, 0, 436, 442, 5, 36, 0, 0, 437, 442, 5, 37, 0, 0, 438, 442, 5, 38, 0, 0, 439, 442, 5, 39, 0, 0, 440, 442, 5, 40, 0, 0, 441, 401, 1, 0, 0, 0, 441, 402, 1, 0, 0, 0, 441, 403, 1, 0, 0, 0, 441, 404, 1, 0, 0, 0, 441, 405, 1, 0, 0, 0, 441, 406, 1, 0, 0, 0, 441, 407, 1, 0, 0, 0, 441, 408, 1, 0, 0, 0, 441, 409, 1, 0, 0, 0, 441, 410, 1, 0, 0, 0, 441, 411, 1, 0, 0, 0, 441, 412, 1, 0, 0, 0, 441, 413, 1, 0, 0, 0, 441, 414, 1, 0, 0, 0, 441, 415, 1, 0, 0, 0, 441, 416, 1, 0, 0, 0, 441, 417, 1, 0, 0, 0, 441, 418, 1, 0, 0, 0, 441, 431, 1, 0, 0, 0, 441, 432, 1, 0, 0, 0, 441, 433, 1, 0, 0, 0, 441, 434, 1, 0, 0, 0, 441, 435, 1, 0, 0, 0, 441, 436, 1, 0, 0, 0, 441, 437, 1, 0, 0, 0, 441, 438, 1, 0, 0, 0, 441, 439, 1, 0, 0, 0, 441, 440, 1, 0, 0, 0, 442, 41, 1, 0, 0, 0, 443, 444, 5, 21, 0, 0, 444, 445, 5, 239, 0, 0, 445, 450, 3, 44, 22, 0, 446, 447, 5, 246, 0, 0, 447, 449, 3, 44, 22, 0, 448, 446, 1, 0, 0, 0, 449, 452, 1, 0, 0, 0, 450, 448, 1, 0, 0, 0, 450, 451, 1, 0, 0, 0, 451, 453, 1, 0, 0, 0, 452, 450, 1, 0, 0, 0, 453, 454, 5, 240, 0, 0, 454, 43, 1, 0, 0, 0, 455, 458, 5, 266, 0, 0, 456, 457, 5, 261, 0, 0, 457, 459, 3, 22, 11, 0, 458, 456, 1, 0, 0, 0, 458, 459, 1, 0, 0, 0, 459, 462, 1, 0, 0, 0, 460, 462, 5, 20, 0, 0, 461, 455, 1, 0, 0, 0, 461, 460, 1, 0, 0, 0, 462, 45, 1, 0, 0, 0, 463, 464, 7, 15, 0, 0, 464, 47, 1, 0, 0, 0, 465, 466, 7, 16, 0, 0, 466, 49, 1, 0, 0, 0, 467, 468, 5, 13, 0, 0, 468, 51, 1, 0, 0, 0, 469, 470, 5, 12, 0, 0, 470, 53, 1, 0, 0, 0, 471, 478, 3, 40, 20, 0, 472, 478, 3, 42, 21, 0, 473, 478, 3, 46, 23, 0, 474, 478, 3, 48, 24, 0, 475, 478, 3, 50, 25, 0, 476, 478, 3, 52, 26, 0, 477, 471, 1, 0, 0, 0, 477, 472, 1, 0, 0, 0, 477, 473, 1, 0, 0, 0, 477, 474, 1, 0, 0, 0, 477, 475, 1, 0, 0, 0, 477, 476, 1, 0, 0, 0, 478, 479, 1, 0, 0, 0, 479, 477, 1, 0, 0, 0, 479, 480, 1, 0, 0, 0, 480, 55, 1, 0, 0, 0, 481, 486, 5, 266, 0, 0, 482, 486, 3, 64, 32, 0, 483, 486, 3, 62, 31, 0, 484, 486, 3, 66, 33, 0, 485, 481, 1, 0, 0, 0, 485, 482, 1, 0, 0, 0, 485, 483, 1, 0, 0, 0, 485, 484, 1, 0, 0, 0, 486, 488, 1, 0, 0, 0, 487, 489, 3, 58, 29, 0, 488, 487, 1, 0, 0, 0, 488, 489, 1, 0, 0, 0, 489, 57, 1, 0, 0, 0, 490, 492, 3, 60, 30, 0, 491, 490, 1, 0, 0, 0, 492, 493, 1, 0, 0, 0, 493, 491, 1, 0, 0, 0, 493, 494, 1, 0, 0, 0, 494, 59, 1, 0, 0, 0, 495, 497, 5, 244, 0, 0, 496, 498, 3, 22, 11, 0, 497, 496, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 500, 5, 245, 0, 0, 500, 61, 1, 0, 0, 0, 501, 502, 7, 17, 0, 0, 502, 63, 1, 0, 0, 0, 503, 504, 7, 18, 0, 0, 504, 65, 1, 0, 0, 0, 505, 507, 5, 45, 0, 0, 506, 508, 5, 266, 0, 0, 507, 506, 1, 0, 0, 0, 507, 508, 1, 0, 0, 0, 508, 509, 1, 0, 0, 0, 509, 510, 3, 68, 34, 0, 510, 67, 1, 0, 0, 0, 511, 513, 5, 241, 0, 0, 512, 514, 3, 70, 35, 0, 513, 512, 1, 0, 0, 0, 514, 515, 1, 0, 0, 0, 515, 513, 1, 0, 0, 0, 515, 516, 1, 0, 0, 0, 516, 517, 1, 0, 0, 0, 517, 518, 5, 242, 0, 0, 518, 69, 1, 0, 0, 0, 519, 520, 3, 38, 19, 0, 520, 525, 3, 72, 36, 0, 521, 522, 5, 246, 0, 0, 522, 524, 3, 72, 36, 0, 523, 521, 1, 0, 0, 0, 524, 527, 1, 0, 0, 0, 525, 523, 1, 0, 0, 0, 525, 526, 1, 0, 0, 0, 526, 528, 1, 0, 0, 0, 527, 525, 1, 0, 0, 0, 528, 529, 5, 243, 0, 0, 529, 71, 1, 0, 0, 0, 530, 532, 5, 266, 0, 0, 531, 533, 3, 58, 29, 0, 532, 531, 1, 0, 0, 0, 532, 533, 1, 0, 0, 0, 533, 73, 1, 0, 0, 0, 534, 551, 3, 20, 10, 0, 535, 547, 5, 241, 0, 0, 536, 541, 3, 74, 37, 0, 537, 538, 5, 246, 0, 0, 538, 540, 3, 74, 37, 0, 539, 537, 1, 0, 0, 0, 540, 543, 1, 0, 0, 0, 541, 539, 1, 0, 0, 0, 541, 542, 1, 0, 0, 0, 542, 545, 1, 0, 0, 0, 543, 541, 1, 0, 0, 0, 544, 546, 5, 246, 0, 0, 545, 544, 1, 0, 0, 0, 545, 546, 1, 0, 0, 0, 546, 548, 1, 0, 0, 0, 547, 536, 1, 0, 0, 0, 547, 548, 1, 0, 0, 0, 548, 549, 1, 0, 0, 0, 549, 551, 5, 242, 0, 0, 550, 534, 1, 0, 0, 0, 550, 535, 1, 0, 0, 0, 551, 75, 1, 0, 0, 0, 552, 565, 3, 78, 39, 0, 553, 565, 3, 80, 40, 0, 554, 565, 3, 82, 41, 0, 555, 565, 3, 84, 42, 0, 556, 565, 3, 86, 43, 0, 557, 565, 3, 90, 45, 0, 558, 565, 3, 92, 46, 0, 559, 565, 3, 98, 49, 0, 560, 565, 3, 94, 47, 0, 561, 565, 3, 96, 48, 0, 562, 565, 3, 100, 50, 0, 563, 565, 3, 102, 51, 0, 564, 552, 1, 0, 0, 0, 564, 553, 1, 0, 0, 0, 564, 554, 1, 0, 0, 0, 564, 555, 1, 0, 0, 0, 564, 556, 1, 0, 0, 0, 564, 557, 1, 0, 0, 0, 564, 558, 1, 0, 0, 0, 564, 559, 1, 0, 0, 0, 564, 560, 1, 0, 0, 0, 564, 561, 1, 0, 0, 0, 564, 562, 1, 0, 0, 0, 564, 563, 1, 0, 0, 0, 565, 77, 1, 0, 0, 0, 566, 570, 5, 241, 0, 0, 567, 569, 3, 76, 38, 0, 568, 567, 1, 0, 0, 0, 569, 572, 1, 0, 0, 0, 570, 568, 1, 0, 0, 0, 570, 571, 1, 0, 0, 0, 571, 573, 1, 0, 0, 0, 572, 570, 1, 0, 0, 0, 573, 574, 5, 242, 0, 0, 574, 79, 1, 0, 0, 0, 575, 576, 3, 24, 12, 0, 576, 81, 1, 0, 0, 0, 577, 578, 3, 22, 11, 0, 578, 579, 5, 243, 0, 0, 579, 83, 1, 0, 0, 0, 580, 581, 5, 243, 0, 0, 581, 85, 1, 0, 0, 0, 582, 584, 3, 32, 16, 0, 583, 582, 1, 0, 0, 0, 583, 584, 1, 0, 0, 0, 584, 585, 1, 0, 0, 0, 585, 586, 5, 46, 0, 0, 586, 587, 5, 239, 0, 0, 587, 588, 3, 22, 11, 0, 588, 589, 5, 240, 0, 0, 589, 592, 3, 76, 38, 0, 590, 591, 5, 47, 0, 0, 591, 593, 3, 76, 38, 0, 592, 590, 1, 0, 0, 0, 592, 593, 1, 0, 0, 0, 593, 87, 1, 0, 0, 0, 594, 595, 3, 38, 19, 0, 595, 596, 5, 266, 0, 0, 596, 597, 5, 261, 0, 0, 597, 598, 3, 74, 37, 0, 598, 89, 1, 0, 0, 0, 599, 601, 3, 32, 16, 0, 600, 599, 1, 0, 0, 0, 600, 601, 1, 0, 0, 0, 601, 602, 1, 0, 0, 0, 602, 603, 5, 48, 0, 0, 603, 604, 5, 239, 0, 0, 604, 605, 3, 22, 11, 0, 605, 606, 5, 240, 0, 0, 606, 607, 3, 78, 39, 0, 607, 91, 1, 0, 0, 0, 608, 609, 5, 49, 0, 0, 609, 610, 3, 22, 11, 0, 610, 611, 5, 1, 0, 0, 611, 615, 1, 0, 0, 0, 612, 613, 5, 50, 0, 0, 613, 615, 5, 1, 0, 0, 614, 608, 1, 0, 0, 0, 614, 612, 1, 0, 0, 0, 615, 93, 1, 0, 0, 0, 616, 618, 3, 32, 16, 0, 617, 616, 1, 0, 0, 0, 617, 618, 1, 0, 0, 0, 618, 619, 1, 0, 0, 0, 619, 620, 5, 51, 0, 0, 620, 623, 5, 239, 0, 0, 621, 624, 3, 22, 11, 0, 622, 624, 3, 88, 44, 0, 623, 621, 1, 0, 0, 0, 623, 622, 1, 0, 0, 0, 624, 625, 1, 0, 0, 0, 625, 626, 5, 240, 0, 0, 626, 627, 3, 76, 38, 0, 627, 95, 1, 0, 0, 0, 628, 630, 3, 32, 16, 0, 629, 628, 1, 0, 0, 0, 629, 630, 1, 0, 0, 0, 630, 631, 1, 0, 0, 0, 631, 632, 5, 52, 0, 0, 632, 633, 3, 76, 38, 0, 633, 634, 5, 51, 0, 0, 634, 635, 5, 239, 0, 0, 635, 636, 3, 22, 11, 0, 636, 637, 5, 240, 0, 0, 637, 638, 5, 243, 0, 0, 638, 97, 1, 0, 0, 0, 639, 641, 3, 32, 16, 0, 640, 639, 1, 0, 0, 0, 640, 641, 1, 0, 0, 0, 641, 642, 1, 0, 0, 0, 642, 643, 5, 53, 0, 0, 643, 647, 5, 239, 0, 0, 644, 648, 3, 84, 42, 0, 645, 648, 3, 82, 41, 0, 646, 648, 3, 80, 40, 0, 647, 644, 1, 0, 0, 0, 647, 645, 1, 0, 0, 0, 647, 646, 1, 0, 0, 0, 648, 651, 1, 0, 0, 0, 649, 652, 3, 22, 11, 0, 650, 652, 3, 88, 44, 0, 651, 649, 1, 0, 0, 0, 651, 650, 1, 0, 0, 0, 651, 652, 1, 0, 0, 0, 652, 653, 1, 0, 0, 0, 653, 655, 5, 243, 0, 0, 654, 656, 3, 22, 11, 0, 655, 654, 1, 0, 0, 0, 655, 656, 1, 0, 0, 0, 656, 657, 1, 0, 0, 0, 657, 658, 5, 240, 0, 0, 658, 659, 3, 76, 38, 0, 659, 99, 1, 0, 0, 0, 660, 661, 5, 54, 0, 0, 661, 676, 5, 243, 0, 0, 662, 663, 5, 55, 0, 0, 663, 676, 5, 243, 0, 0, 664, 666, 5, 56, 0, 0, 665, 667, 3, 22, 11, 0, 666, 665, 1, 0, 0, 0, 666, 667, 1, 0, 0, 0, 667, 668, 1, 0, 0, 0, 668, 676, 5, 243, 0, 0, 669, 670, 5, 57, 0, 0, 670, 676, 5, 243, 0, 0, 671, 672, 5, 41, 0, 0, 672, 676, 5, 243, 0, 0, 673, 674, 5, 42, 0, 0, 674, 676, 5, 243, 0, 0, 675, 660, 1, 0, 0, 0, 675, 662, 1, 0, 0, 0, 675, 664, 1, 0, 0, 0, 675, 669, 1, 0, 0, 0, 675, 671, 1, 0, 0, 0, 675, 673, 1, 0, 0, 0, 676, 101, 1, 0, 0, 0, 677, 678, 5, 58, 0, 0, 678, 679, 5, 243, 0, 0, 679, 103, 1, 0, 0, 0, 72, 105, 110, 119, 131, 138, 149, 158, 165, 173, 178, 181, 201, 211, 214, 219, 275, 277, 285, 296, 298, 308, 311, 326, 329, 333, 336, 344, 351, 354, 359, 361, 370, 379, 386, 390, 394, 397, 425, 429, 441, 450, 458, 461, 477, 479, 485, 488, 493, 497, 507, 515, 525, 532, 541, 545, 547, 550, 564, 570, 583, 592, 600, 614, 617, 623, 629, 640, 647, 651, 655, 666, 675] \ No newline at end of file diff --git a/src/main/java/io/github/douira/glsl_transformer/GLSLParser.java b/src/main/java/io/github/douira/glsl_transformer/GLSLParser.java index d28387d10e..4653eeec3c 100644 --- a/src/main/java/io/github/douira/glsl_transformer/GLSLParser.java +++ b/src/main/java/io/github/douira/glsl_transformer/GLSLParser.java @@ -2,15 +2,18 @@ package io.github.douira.glsl_transformer; import io.github.douira.glsl_transformer.parser.ExtendedParser; - -import repack.antlr.v4.runtime.atn.*; -import repack.antlr.v4.runtime.dfa.DFA; import repack.antlr.v4.runtime.*; -import repack.antlr.v4.runtime.misc.*; -import repack.antlr.v4.runtime.tree.*; -import java.util.List; -import java.util.Iterator; +import repack.antlr.v4.runtime.atn.ATN; +import repack.antlr.v4.runtime.atn.ATNDeserializer; +import repack.antlr.v4.runtime.atn.ParserATNSimulator; +import repack.antlr.v4.runtime.atn.PredictionContextCache; +import repack.antlr.v4.runtime.dfa.DFA; +import repack.antlr.v4.runtime.tree.ParseTreeListener; +import repack.antlr.v4.runtime.tree.ParseTreeVisitor; +import repack.antlr.v4.runtime.tree.TerminalNode; + import java.util.ArrayList; +import java.util.List; @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"}) public class GLSLParser extends ExtendedParser { @@ -20,106 +23,106 @@ public class GLSLParser extends ExtendedParser { protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); public static final int - COLON=1, UNIFORM=2, BUFFER=3, IN=4, OUT=5, INOUT=6, HIGHP=7, MEDIUMP=8, - LOWP=9, PRECISION=10, CONST=11, PRECISE=12, INVARIANT=13, SMOOTH=14, FLAT=15, - CENTROID=16, ATTRIBUTE=17, VOLATILE=18, VARYING=19, SHARED=20, LAYOUT=21, - DOT_LENGTH_METHOD_CALL=22, NOPERSPECTIVE=23, SAMPLE=24, PATCH=25, COHERENT=26, - RESTRICT=27, READONLY=28, WRITEONLY=29, SUBROUTINE=30, DEVICECOHERENT=31, - QUEUEFAMILYCOHERENT=32, WORKGROUPCOHERENT=33, SUBGROUPCOHERENT=34, NONPRIVATE=35, - RAY_PAYLOAD_EXT=36, RAY_PAYLOAD_IN_EXT=37, HIT_ATTRIBUTE_EXT=38, CALLABLE_DATA_EXT=39, - CALLABLE_DATA_IN_EXT=40, IGNORE_INTERSECTION_EXT=41, TERMINATE_RAY_EXT=42, - ACCELERATION_STRUCTURE_EXT=43, ATOMIC_UINT=44, STRUCT=45, IF=46, ELSE=47, - SWITCH=48, CASE=49, DEFAULT=50, WHILE=51, DO=52, FOR=53, CONTINUE=54, - BREAK=55, RETURN=56, DISCARD=57, DEMOTE=58, UINT16CONSTANT=59, INT16CONSTANT=60, - UINT32CONSTANT=61, INT32CONSTANT=62, UINT64CONSTANT=63, INT64CONSTANT=64, - FLOAT16CONSTANT=65, FLOAT32CONSTANT=66, FLOAT64CONSTANT=67, BOOLCONSTANT=68, - BOOL=69, BVEC2=70, BVEC3=71, BVEC4=72, INT8=73, I8VEC2=74, I8VEC3=75, - I8VEC4=76, UINT8=77, U8VEC2=78, U8VEC3=79, U8VEC4=80, INT16=81, I16VEC2=82, - I16VEC3=83, I16VEC4=84, UINT16=85, U16VEC2=86, U16VEC3=87, U16VEC4=88, - INT32=89, I32VEC2=90, I32VEC3=91, I32VEC4=92, UINT32=93, U32VEC2=94, U32VEC3=95, - U32VEC4=96, INT64=97, I64VEC2=98, I64VEC3=99, I64VEC4=100, UINT64=101, - U64VEC2=102, U64VEC3=103, U64VEC4=104, FLOAT16=105, F16VEC2=106, F16VEC3=107, - F16VEC4=108, F16MAT2X2=109, F16MAT2X3=110, F16MAT2X4=111, F16MAT3X2=112, - F16MAT3X3=113, F16MAT3X4=114, F16MAT4X2=115, F16MAT4X3=116, F16MAT4X4=117, - FLOAT32=118, F32VEC2=119, F32VEC3=120, F32VEC4=121, F32MAT2X2=122, F32MAT2X3=123, - F32MAT2X4=124, F32MAT3X2=125, F32MAT3X3=126, F32MAT3X4=127, F32MAT4X2=128, - F32MAT4X3=129, F32MAT4X4=130, FLOAT64=131, F64VEC2=132, F64VEC3=133, F64VEC4=134, - F64MAT2X2=135, F64MAT2X3=136, F64MAT2X4=137, F64MAT3X2=138, F64MAT3X3=139, - F64MAT3X4=140, F64MAT4X2=141, F64MAT4X3=142, F64MAT4X4=143, IMAGE1D=144, - IMAGE2D=145, IMAGE3D=146, UIMAGE1D=147, UIMAGE2D=148, UIMAGE3D=149, IIMAGE1D=150, - IIMAGE2D=151, IIMAGE3D=152, SAMPLER1D=153, SAMPLER2D=154, SAMPLER3D=155, - SAMPLER2DRECT=156, SAMPLER1DSHADOW=157, SAMPLER2DSHADOW=158, SAMPLER2DRECTSHADOW=159, - SAMPLER1DARRAY=160, SAMPLER2DARRAY=161, SAMPLER1DARRAYSHADOW=162, SAMPLER2DARRAYSHADOW=163, - ISAMPLER1D=164, ISAMPLER2D=165, ISAMPLER2DRECT=166, ISAMPLER3D=167, ISAMPLER1DARRAY=168, - ISAMPLER2DARRAY=169, USAMPLER1D=170, USAMPLER2D=171, USAMPLER2DRECT=172, - USAMPLER3D=173, USAMPLER1DARRAY=174, USAMPLER2DARRAY=175, SAMPLER2DMS=176, - ISAMPLER2DMS=177, USAMPLER2DMS=178, SAMPLER2DMSARRAY=179, ISAMPLER2DMSARRAY=180, - USAMPLER2DMSARRAY=181, IMAGE2DRECT=182, IMAGE1DARRAY=183, IMAGE2DARRAY=184, - IMAGE2DMS=185, IMAGE2DMSARRAY=186, IIMAGE2DRECT=187, IIMAGE1DARRAY=188, - IIMAGE2DARRAY=189, IIMAGE2DMS=190, IIMAGE2DMSARRAY=191, UIMAGE2DRECT=192, - UIMAGE1DARRAY=193, UIMAGE2DARRAY=194, UIMAGE2DMS=195, UIMAGE2DMSARRAY=196, - SAMPLERCUBESHADOW=197, SAMPLERCUBEARRAYSHADOW=198, SAMPLERCUBE=199, ISAMPLERCUBE=200, - USAMPLERCUBE=201, SAMPLERBUFFER=202, ISAMPLERBUFFER=203, USAMPLERBUFFER=204, - SAMPLERCUBEARRAY=205, ISAMPLERCUBEARRAY=206, USAMPLERCUBEARRAY=207, IMAGECUBE=208, - UIMAGECUBE=209, IIMAGECUBE=210, IMAGEBUFFER=211, IIMAGEBUFFER=212, UIMAGEBUFFER=213, - IMAGECUBEARRAY=214, IIMAGECUBEARRAY=215, UIMAGECUBEARRAY=216, INC_OP=217, - DEC_OP=218, VOID=219, LEFT_OP=220, RIGHT_OP=221, LE_OP=222, GE_OP=223, - EQ_OP=224, NE_OP=225, LOGICAL_AND_OP=226, LOGICAL_XOR_OP=227, LOGICAL_OR_OP=228, - MUL_ASSIGN=229, DIV_ASSIGN=230, MOD_ASSIGN=231, ADD_ASSIGN=232, SUB_ASSIGN=233, - LEFT_ASSIGN=234, RIGHT_ASSIGN=235, AND_ASSIGN=236, XOR_ASSIGN=237, OR_ASSIGN=238, - LPAREN=239, RPAREN=240, LBRACE=241, RBRACE=242, SEMICOLON=243, LBRACKET=244, - RBRACKET=245, COMMA=246, DOT=247, PLUS_OP=248, MINUS_OP=249, LOGICAL_NOT_OP=250, - BITWISE_NEG_OP=251, TIMES_OP=252, DIV_OP=253, MOD_OP=254, LT_OP=255, GT_OP=256, - BITWISE_AND_OP=257, BITWISE_OR_OP=258, BITWISE_XOR_OP=259, QUERY_OP=260, - ASSIGN_OP=261, PP_ENTER_MODE=262, PP_EMPTY=263, NR_LINE=264, NR=265, IDENTIFIER=266, - LINE_CONTINUE=267, LINE_COMMENT=268, BLOCK_COMMENT=269, WS=270, EOL=271, - NR_EXTENSION=272, NR_VERSION=273, NR_CUSTOM=274, NR_INCLUDE=275, NR_PRAGMA=276, - NR_PRAGMA_DEBUG=277, NR_PRAGMA_OPTIMIZE=278, NR_PRAGMA_INVARIANT=279, - NR_ON=280, NR_OFF=281, NR_ALL=282, NR_REQUIRE=283, NR_ENABLE=284, NR_WARN=285, - NR_DISABLE=286, NR_COLON=287, NR_LPAREN=288, NR_RPAREN=289, NR_STDGL=290, - NR_CORE=291, NR_COMPATIBILITY=292, NR_ES=293, NR_GLSL_110=294, NR_GLSL_120=295, - NR_GLSLES_100=296, NR_GLSL_130=297, NR_GLSL_140=298, NR_GLSL_150=299, - NR_GLSL_330=300, NR_GLSLES_300=301, NR_GLSLES_310=302, NR_GLSLES_320=303, - NR_GLSL_400=304, NR_GLSL_410=305, NR_GLSL_420=306, NR_GLSL_430=307, NR_GLSL_440=308, - NR_GLSL_450=309, NR_GLSL_460=310, NR_STRING_START=311, NR_STRING_START_ANGLE=312, - NR_INTCONSTANT=313, NR_IDENTIFIER=314, NR_LINE_CONTINUE=315, NR_LINE_COMMENT=316, - NR_BLOCK_COMMENT=317, NR_EOL=318, NR_WS=319, S_CONTENT=320, S_STRING_END=321, - S_CONTENT_ANGLE=322, S_STRING_END_ANGLE=323, C_LINE_COMMENT=324, C_BLOCK_COMMENT=325, - C_EOL=326, C_WS=327, C_CONTENT=328, PP_LINE_CONTINUE=329, PP_LINE_COMMENT=330, + COLON=1, UNIFORM=2, BUFFER=3, IN=4, OUT=5, INOUT=6, HIGHP=7, MEDIUMP=8, + LOWP=9, PRECISION=10, CONST=11, PRECISE=12, INVARIANT=13, SMOOTH=14, FLAT=15, + CENTROID=16, ATTRIBUTE=17, VOLATILE=18, VARYING=19, SHARED=20, LAYOUT=21, + DOT_LENGTH_METHOD_CALL=22, NOPERSPECTIVE=23, SAMPLE=24, PATCH=25, COHERENT=26, + RESTRICT=27, READONLY=28, WRITEONLY=29, SUBROUTINE=30, DEVICECOHERENT=31, + QUEUEFAMILYCOHERENT=32, WORKGROUPCOHERENT=33, SUBGROUPCOHERENT=34, NONPRIVATE=35, + RAY_PAYLOAD_EXT=36, RAY_PAYLOAD_IN_EXT=37, HIT_ATTRIBUTE_EXT=38, CALLABLE_DATA_EXT=39, + CALLABLE_DATA_IN_EXT=40, IGNORE_INTERSECTION_EXT=41, TERMINATE_RAY_EXT=42, + ACCELERATION_STRUCTURE_EXT=43, ATOMIC_UINT=44, STRUCT=45, IF=46, ELSE=47, + SWITCH=48, CASE=49, DEFAULT=50, WHILE=51, DO=52, FOR=53, CONTINUE=54, + BREAK=55, RETURN=56, DISCARD=57, DEMOTE=58, UINT16CONSTANT=59, INT16CONSTANT=60, + UINT32CONSTANT=61, INT32CONSTANT=62, UINT64CONSTANT=63, INT64CONSTANT=64, + FLOAT16CONSTANT=65, FLOAT32CONSTANT=66, FLOAT64CONSTANT=67, BOOLCONSTANT=68, + BOOL=69, BVEC2=70, BVEC3=71, BVEC4=72, INT8=73, I8VEC2=74, I8VEC3=75, + I8VEC4=76, UINT8=77, U8VEC2=78, U8VEC3=79, U8VEC4=80, INT16=81, I16VEC2=82, + I16VEC3=83, I16VEC4=84, UINT16=85, U16VEC2=86, U16VEC3=87, U16VEC4=88, + INT32=89, I32VEC2=90, I32VEC3=91, I32VEC4=92, UINT32=93, U32VEC2=94, U32VEC3=95, + U32VEC4=96, INT64=97, I64VEC2=98, I64VEC3=99, I64VEC4=100, UINT64=101, + U64VEC2=102, U64VEC3=103, U64VEC4=104, FLOAT16=105, F16VEC2=106, F16VEC3=107, + F16VEC4=108, F16MAT2X2=109, F16MAT2X3=110, F16MAT2X4=111, F16MAT3X2=112, + F16MAT3X3=113, F16MAT3X4=114, F16MAT4X2=115, F16MAT4X3=116, F16MAT4X4=117, + FLOAT32=118, F32VEC2=119, F32VEC3=120, F32VEC4=121, F32MAT2X2=122, F32MAT2X3=123, + F32MAT2X4=124, F32MAT3X2=125, F32MAT3X3=126, F32MAT3X4=127, F32MAT4X2=128, + F32MAT4X3=129, F32MAT4X4=130, FLOAT64=131, F64VEC2=132, F64VEC3=133, F64VEC4=134, + F64MAT2X2=135, F64MAT2X3=136, F64MAT2X4=137, F64MAT3X2=138, F64MAT3X3=139, + F64MAT3X4=140, F64MAT4X2=141, F64MAT4X3=142, F64MAT4X4=143, IMAGE1D=144, + IMAGE2D=145, IMAGE3D=146, UIMAGE1D=147, UIMAGE2D=148, UIMAGE3D=149, IIMAGE1D=150, + IIMAGE2D=151, IIMAGE3D=152, SAMPLER1D=153, SAMPLER2D=154, SAMPLER3D=155, + SAMPLER2DRECT=156, SAMPLER1DSHADOW=157, SAMPLER2DSHADOW=158, SAMPLER2DRECTSHADOW=159, + SAMPLER1DARRAY=160, SAMPLER2DARRAY=161, SAMPLER1DARRAYSHADOW=162, SAMPLER2DARRAYSHADOW=163, + ISAMPLER1D=164, ISAMPLER2D=165, ISAMPLER2DRECT=166, ISAMPLER3D=167, ISAMPLER1DARRAY=168, + ISAMPLER2DARRAY=169, USAMPLER1D=170, USAMPLER2D=171, USAMPLER2DRECT=172, + USAMPLER3D=173, USAMPLER1DARRAY=174, USAMPLER2DARRAY=175, SAMPLER2DMS=176, + ISAMPLER2DMS=177, USAMPLER2DMS=178, SAMPLER2DMSARRAY=179, ISAMPLER2DMSARRAY=180, + USAMPLER2DMSARRAY=181, IMAGE2DRECT=182, IMAGE1DARRAY=183, IMAGE2DARRAY=184, + IMAGE2DMS=185, IMAGE2DMSARRAY=186, IIMAGE2DRECT=187, IIMAGE1DARRAY=188, + IIMAGE2DARRAY=189, IIMAGE2DMS=190, IIMAGE2DMSARRAY=191, UIMAGE2DRECT=192, + UIMAGE1DARRAY=193, UIMAGE2DARRAY=194, UIMAGE2DMS=195, UIMAGE2DMSARRAY=196, + SAMPLERCUBESHADOW=197, SAMPLERCUBEARRAYSHADOW=198, SAMPLERCUBE=199, ISAMPLERCUBE=200, + USAMPLERCUBE=201, SAMPLERBUFFER=202, ISAMPLERBUFFER=203, USAMPLERBUFFER=204, + SAMPLERCUBEARRAY=205, ISAMPLERCUBEARRAY=206, USAMPLERCUBEARRAY=207, IMAGECUBE=208, + UIMAGECUBE=209, IIMAGECUBE=210, IMAGEBUFFER=211, IIMAGEBUFFER=212, UIMAGEBUFFER=213, + IMAGECUBEARRAY=214, IIMAGECUBEARRAY=215, UIMAGECUBEARRAY=216, INC_OP=217, + DEC_OP=218, VOID=219, LEFT_OP=220, RIGHT_OP=221, LE_OP=222, GE_OP=223, + EQ_OP=224, NE_OP=225, LOGICAL_AND_OP=226, LOGICAL_XOR_OP=227, LOGICAL_OR_OP=228, + MUL_ASSIGN=229, DIV_ASSIGN=230, MOD_ASSIGN=231, ADD_ASSIGN=232, SUB_ASSIGN=233, + LEFT_ASSIGN=234, RIGHT_ASSIGN=235, AND_ASSIGN=236, XOR_ASSIGN=237, OR_ASSIGN=238, + LPAREN=239, RPAREN=240, LBRACE=241, RBRACE=242, SEMICOLON=243, LBRACKET=244, + RBRACKET=245, COMMA=246, DOT=247, PLUS_OP=248, MINUS_OP=249, LOGICAL_NOT_OP=250, + BITWISE_NEG_OP=251, TIMES_OP=252, DIV_OP=253, MOD_OP=254, LT_OP=255, GT_OP=256, + BITWISE_AND_OP=257, BITWISE_OR_OP=258, BITWISE_XOR_OP=259, QUERY_OP=260, + ASSIGN_OP=261, PP_ENTER_MODE=262, PP_EMPTY=263, NR_LINE=264, NR=265, IDENTIFIER=266, + LINE_CONTINUE=267, LINE_COMMENT=268, BLOCK_COMMENT=269, WS=270, EOL=271, + NR_EXTENSION=272, NR_VERSION=273, NR_CUSTOM=274, NR_INCLUDE=275, NR_PRAGMA=276, + NR_PRAGMA_DEBUG=277, NR_PRAGMA_OPTIMIZE=278, NR_PRAGMA_INVARIANT=279, + NR_ON=280, NR_OFF=281, NR_ALL=282, NR_REQUIRE=283, NR_ENABLE=284, NR_WARN=285, + NR_DISABLE=286, NR_COLON=287, NR_LPAREN=288, NR_RPAREN=289, NR_STDGL=290, + NR_CORE=291, NR_COMPATIBILITY=292, NR_ES=293, NR_GLSL_110=294, NR_GLSL_120=295, + NR_GLSLES_100=296, NR_GLSL_130=297, NR_GLSL_140=298, NR_GLSL_150=299, + NR_GLSL_330=300, NR_GLSLES_300=301, NR_GLSLES_310=302, NR_GLSLES_320=303, + NR_GLSL_400=304, NR_GLSL_410=305, NR_GLSL_420=306, NR_GLSL_430=307, NR_GLSL_440=308, + NR_GLSL_450=309, NR_GLSL_460=310, NR_STRING_START=311, NR_STRING_START_ANGLE=312, + NR_INTCONSTANT=313, NR_IDENTIFIER=314, NR_LINE_CONTINUE=315, NR_LINE_COMMENT=316, + NR_BLOCK_COMMENT=317, NR_EOL=318, NR_WS=319, S_CONTENT=320, S_STRING_END=321, + S_CONTENT_ANGLE=322, S_STRING_END_ANGLE=323, C_LINE_COMMENT=324, C_BLOCK_COMMENT=325, + C_EOL=326, C_WS=327, C_CONTENT=328, PP_LINE_CONTINUE=329, PP_LINE_COMMENT=330, PP_BLOCK_COMMENT=331, PP_EOL=332, PP_CONTENT=333; public static final int - RULE_translationUnit = 0, RULE_versionStatement = 1, RULE_externalDeclaration = 2, - RULE_emptyDeclaration = 3, RULE_pragmaDirective = 4, RULE_extensionDirective = 5, - RULE_customDirective = 6, RULE_includeDirective = 7, RULE_layoutDefaults = 8, - RULE_functionDefinition = 9, RULE_finiteExpression = 10, RULE_expression = 11, - RULE_declaration = 12, RULE_functionPrototype = 13, RULE_functionParameterList = 14, - RULE_parameterDeclaration = 15, RULE_attribute = 16, RULE_singleAttribute = 17, - RULE_declarationMember = 18, RULE_fullySpecifiedType = 19, RULE_storageQualifier = 20, - RULE_layoutQualifier = 21, RULE_layoutQualifierId = 22, RULE_precisionQualifier = 23, - RULE_interpolationQualifier = 24, RULE_invariantQualifier = 25, RULE_preciseQualifier = 26, - RULE_typeQualifier = 27, RULE_typeSpecifier = 28, RULE_arraySpecifier = 29, - RULE_arraySpecifierSegment = 30, RULE_builtinTypeSpecifierParseable = 31, - RULE_builtinTypeSpecifierFixed = 32, RULE_structSpecifier = 33, RULE_structBody = 34, - RULE_structMember = 35, RULE_structDeclarator = 36, RULE_initializer = 37, - RULE_statement = 38, RULE_compoundStatement = 39, RULE_declarationStatement = 40, - RULE_expressionStatement = 41, RULE_emptyStatement = 42, RULE_selectionStatement = 43, - RULE_iterationCondition = 44, RULE_switchStatement = 45, RULE_caseLabel = 46, - RULE_whileStatement = 47, RULE_doWhileStatement = 48, RULE_forStatement = 49, + RULE_translationUnit = 0, RULE_versionStatement = 1, RULE_externalDeclaration = 2, + RULE_emptyDeclaration = 3, RULE_pragmaDirective = 4, RULE_extensionDirective = 5, + RULE_customDirective = 6, RULE_includeDirective = 7, RULE_layoutDefaults = 8, + RULE_functionDefinition = 9, RULE_finiteExpression = 10, RULE_expression = 11, + RULE_declaration = 12, RULE_functionPrototype = 13, RULE_functionParameterList = 14, + RULE_parameterDeclaration = 15, RULE_attribute = 16, RULE_singleAttribute = 17, + RULE_declarationMember = 18, RULE_fullySpecifiedType = 19, RULE_storageQualifier = 20, + RULE_layoutQualifier = 21, RULE_layoutQualifierId = 22, RULE_precisionQualifier = 23, + RULE_interpolationQualifier = 24, RULE_invariantQualifier = 25, RULE_preciseQualifier = 26, + RULE_typeQualifier = 27, RULE_typeSpecifier = 28, RULE_arraySpecifier = 29, + RULE_arraySpecifierSegment = 30, RULE_builtinTypeSpecifierParseable = 31, + RULE_builtinTypeSpecifierFixed = 32, RULE_structSpecifier = 33, RULE_structBody = 34, + RULE_structMember = 35, RULE_structDeclarator = 36, RULE_initializer = 37, + RULE_statement = 38, RULE_compoundStatement = 39, RULE_declarationStatement = 40, + RULE_expressionStatement = 41, RULE_emptyStatement = 42, RULE_selectionStatement = 43, + RULE_iterationCondition = 44, RULE_switchStatement = 45, RULE_caseLabel = 46, + RULE_whileStatement = 47, RULE_doWhileStatement = 48, RULE_forStatement = 49, RULE_jumpStatement = 50, RULE_demoteStatement = 51; private static String[] makeRuleNames() { return new String[] { - "translationUnit", "versionStatement", "externalDeclaration", "emptyDeclaration", - "pragmaDirective", "extensionDirective", "customDirective", "includeDirective", - "layoutDefaults", "functionDefinition", "finiteExpression", "expression", - "declaration", "functionPrototype", "functionParameterList", "parameterDeclaration", - "attribute", "singleAttribute", "declarationMember", "fullySpecifiedType", - "storageQualifier", "layoutQualifier", "layoutQualifierId", "precisionQualifier", - "interpolationQualifier", "invariantQualifier", "preciseQualifier", "typeQualifier", - "typeSpecifier", "arraySpecifier", "arraySpecifierSegment", "builtinTypeSpecifierParseable", - "builtinTypeSpecifierFixed", "structSpecifier", "structBody", "structMember", - "structDeclarator", "initializer", "statement", "compoundStatement", - "declarationStatement", "expressionStatement", "emptyStatement", "selectionStatement", - "iterationCondition", "switchStatement", "caseLabel", "whileStatement", + "translationUnit", "versionStatement", "externalDeclaration", "emptyDeclaration", + "pragmaDirective", "extensionDirective", "customDirective", "includeDirective", + "layoutDefaults", "functionDefinition", "finiteExpression", "expression", + "declaration", "functionPrototype", "functionParameterList", "parameterDeclaration", + "attribute", "singleAttribute", "declarationMember", "fullySpecifiedType", + "storageQualifier", "layoutQualifier", "layoutQualifierId", "precisionQualifier", + "interpolationQualifier", "invariantQualifier", "preciseQualifier", "typeQualifier", + "typeSpecifier", "arraySpecifier", "arraySpecifierSegment", "builtinTypeSpecifierParseable", + "builtinTypeSpecifierFixed", "structSpecifier", "structBody", "structMember", + "structDeclarator", "initializer", "statement", "compoundStatement", + "declarationStatement", "expressionStatement", "emptyStatement", "selectionStatement", + "iterationCondition", "switchStatement", "caseLabel", "whileStatement", "doWhileStatement", "forStatement", "jumpStatement", "demoteStatement" }; } @@ -127,122 +130,122 @@ private static String[] makeRuleNames() { private static String[] makeLiteralNames() { return new String[] { - null, null, "'uniform'", "'buffer'", "'in'", "'out'", "'inout'", "'highp'", - "'mediump'", "'lowp'", "'precision'", "'const'", "'precise'", null, "'smooth'", - "'flat'", "'centroid'", "'attribute'", "'volatile'", "'varying'", "'shared'", - "'layout'", "'.length()'", "'noperspective'", "'sample'", "'patch'", - "'coherent'", "'restrict'", "'readonly'", "'writeonly'", "'subroutine'", - "'devicecoherent'", "'queuefamilycoherent'", "'workgroupcoherent'", "'subgroupcoherent'", - "'nonprivate'", "'rayPayloadEXT'", "'rayPayloadInEXT'", "'hitAttributeEXT'", - "'callableDataEXT'", "'callableDataInEXT'", "'ignoreIntersectionEXT'", - "'terminateRayEXT'", "'accelerationStructureEXT'", "'atomic_uint'", "'struct'", - "'if'", "'else'", "'switch'", "'case'", "'default'", "'while'", "'do'", - "'for'", "'continue'", "'break'", "'return'", "'discard'", "'demote'", - null, null, null, null, null, null, null, null, null, null, "'bool'", - "'bvec2'", "'bvec3'", "'bvec4'", "'int8_t'", "'i8vec2'", "'i8vec3'", - "'i8vec4'", "'uint8_t'", "'u8vec2'", "'u8vec3'", "'u8vec4'", "'int16_t'", - "'i16vec2'", "'i16vec3'", "'i16vec4'", "'uint16_t'", "'u16vec2'", "'u16vec3'", - "'u16vec4'", null, null, null, null, null, null, null, null, "'int64_t'", - "'i64vec2'", "'i64vec3'", "'i64vec4'", "'uint64_t'", "'u64vec2'", "'u64vec3'", - "'u64vec4'", "'float16_t'", "'f16vec2'", "'f16vec3'", "'f16vec4'", null, - "'f16mat2x3'", "'f16mat2x4'", "'f16mat3x2'", null, "'f16mat3x4'", "'f16mat4x2'", - "'f16mat4x3'", null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, "'image1D'", "'image2D'", "'image3D'", - "'uimage1D'", "'uimage2D'", "'uimage3D'", "'iimage1D'", "'iimage2D'", - "'iimage3D'", "'sampler1D'", "'sampler2D'", "'sampler3D'", "'sampler2DRect'", - "'sampler1DShadow'", "'sampler2DShadow'", "'sampler2DRectShadow'", "'sampler1DArray'", - "'sampler2DArray'", "'sampler1DArrayShadow'", "'sampler2DArrayShadow'", - "'isampler1D'", "'isampler2D'", "'isampler2DRect'", "'isampler3D'", "'isampler1DArray'", - "'isampler2DArray'", "'usampler1D'", "'usampler2D'", "'usampler2DRect'", - "'usampler3D'", "'usampler1DArray'", "'usampler2DArray'", "'sampler2DMS'", - "'isampler2DMS'", "'usampler2DMS'", "'sampler2DMSArray'", "'isampler2DMSArray'", - "'usampler2DMSArray'", "'image2DRect'", "'image1DArray'", "'image2DArray'", - "'image2DMS'", "'image2DMSArray'", "'iimage2DRect'", "'iimage1DArray'", - "'iimage2DArray'", "'iimage2DMS'", "'iimage2DMSArray'", "'uimage2DRect'", - "'uimage1DArray'", "'uimage2DArray'", "'uimage2DMS'", "'uimage2DMSArray'", - "'samplerCubeShadow'", "'samplerCubeArrayShadow'", "'samplerCube'", "'isamplerCube'", - "'usamplerCube'", "'samplerBuffer'", "'isamplerBuffer'", "'usamplerBuffer'", - "'samplerCubeArray'", "'isamplerCubeArray'", "'usamplerCubeArray'", "'imageCube'", - "'uimageCube'", "'iimageCube'", "'imageBuffer'", "'iimageBuffer'", "'uimageBuffer'", - "'imageCubeArray'", "'iimageCubeArray'", "'uimageCubeArray'", "'++'", - "'--'", "'void'", "'<<'", "'>>'", "'<='", "'>='", "'=='", "'!='", "'&&'", - "'^^'", "'||'", "'*='", "'/='", "'%='", "'+='", "'-='", "'<<='", "'>>='", - "'&='", "'^='", "'|='", null, null, "'{'", "'}'", "';'", "'['", "']'", - "','", "'.'", "'+'", "'-'", "'!'", "'~'", "'*'", "'/'", "'%'", "'<'", - null, "'&'", "'|'", "'^'", "'?'", "'='", null, null, null, "'#'", null, - null, null, null, null, null, "'extension'", "'version'", null, "'include'", - "'pragma'", "'debug'", "'optimize'", null, "'on'", "'off'", "'all'", - "'require'", "'enable'", "'warn'", "'disable'", null, null, null, "'STDGL'", - "'core'", "'compatibility'", "'es'", "'110'", "'120'", "'100'", "'130'", - "'140'", "'150'", "'330'", "'300'", "'310'", "'320'", "'400'", "'410'", - "'420'", "'430'", "'440'", "'450'", "'460'", null, null, null, null, + null, null, "'uniform'", "'buffer'", "'in'", "'out'", "'inout'", "'highp'", + "'mediump'", "'lowp'", "'precision'", "'const'", "'precise'", null, "'smooth'", + "'flat'", "'centroid'", "'attribute'", "'volatile'", "'varying'", "'shared'", + "'layout'", "'.length()'", "'noperspective'", "'sample'", "'patch'", + "'coherent'", "'restrict'", "'readonly'", "'writeonly'", "'subroutine'", + "'devicecoherent'", "'queuefamilycoherent'", "'workgroupcoherent'", "'subgroupcoherent'", + "'nonprivate'", "'rayPayloadEXT'", "'rayPayloadInEXT'", "'hitAttributeEXT'", + "'callableDataEXT'", "'callableDataInEXT'", "'ignoreIntersectionEXT'", + "'terminateRayEXT'", "'accelerationStructureEXT'", "'atomic_uint'", "'struct'", + "'if'", "'else'", "'switch'", "'case'", "'default'", "'while'", "'do'", + "'for'", "'continue'", "'break'", "'return'", "'discard'", "'demote'", + null, null, null, null, null, null, null, null, null, null, "'bool'", + "'bvec2'", "'bvec3'", "'bvec4'", "'int8_t'", "'i8vec2'", "'i8vec3'", + "'i8vec4'", "'uint8_t'", "'u8vec2'", "'u8vec3'", "'u8vec4'", "'int16_t'", + "'i16vec2'", "'i16vec3'", "'i16vec4'", "'uint16_t'", "'u16vec2'", "'u16vec3'", + "'u16vec4'", null, null, null, null, null, null, null, null, "'int64_t'", + "'i64vec2'", "'i64vec3'", "'i64vec4'", "'uint64_t'", "'u64vec2'", "'u64vec3'", + "'u64vec4'", "'float16_t'", "'f16vec2'", "'f16vec3'", "'f16vec4'", null, + "'f16mat2x3'", "'f16mat2x4'", "'f16mat3x2'", null, "'f16mat3x4'", "'f16mat4x2'", + "'f16mat4x3'", null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, "'image1D'", "'image2D'", "'image3D'", + "'uimage1D'", "'uimage2D'", "'uimage3D'", "'iimage1D'", "'iimage2D'", + "'iimage3D'", "'sampler1D'", "'sampler2D'", "'sampler3D'", "'sampler2DRect'", + "'sampler1DShadow'", "'sampler2DShadow'", "'sampler2DRectShadow'", "'sampler1DArray'", + "'sampler2DArray'", "'sampler1DArrayShadow'", "'sampler2DArrayShadow'", + "'isampler1D'", "'isampler2D'", "'isampler2DRect'", "'isampler3D'", "'isampler1DArray'", + "'isampler2DArray'", "'usampler1D'", "'usampler2D'", "'usampler2DRect'", + "'usampler3D'", "'usampler1DArray'", "'usampler2DArray'", "'sampler2DMS'", + "'isampler2DMS'", "'usampler2DMS'", "'sampler2DMSArray'", "'isampler2DMSArray'", + "'usampler2DMSArray'", "'image2DRect'", "'image1DArray'", "'image2DArray'", + "'image2DMS'", "'image2DMSArray'", "'iimage2DRect'", "'iimage1DArray'", + "'iimage2DArray'", "'iimage2DMS'", "'iimage2DMSArray'", "'uimage2DRect'", + "'uimage1DArray'", "'uimage2DArray'", "'uimage2DMS'", "'uimage2DMSArray'", + "'samplerCubeShadow'", "'samplerCubeArrayShadow'", "'samplerCube'", "'isamplerCube'", + "'usamplerCube'", "'samplerBuffer'", "'isamplerBuffer'", "'usamplerBuffer'", + "'samplerCubeArray'", "'isamplerCubeArray'", "'usamplerCubeArray'", "'imageCube'", + "'uimageCube'", "'iimageCube'", "'imageBuffer'", "'iimageBuffer'", "'uimageBuffer'", + "'imageCubeArray'", "'iimageCubeArray'", "'uimageCubeArray'", "'++'", + "'--'", "'void'", "'<<'", "'>>'", "'<='", "'>='", "'=='", "'!='", "'&&'", + "'^^'", "'||'", "'*='", "'/='", "'%='", "'+='", "'-='", "'<<='", "'>>='", + "'&='", "'^='", "'|='", null, null, "'{'", "'}'", "';'", "'['", "']'", + "','", "'.'", "'+'", "'-'", "'!'", "'~'", "'*'", "'/'", "'%'", "'<'", + null, "'&'", "'|'", "'^'", "'?'", "'='", null, null, null, "'#'", null, + null, null, null, null, null, "'extension'", "'version'", null, "'include'", + "'pragma'", "'debug'", "'optimize'", null, "'on'", "'off'", "'all'", + "'require'", "'enable'", "'warn'", "'disable'", null, null, null, "'STDGL'", + "'core'", "'compatibility'", "'es'", "'110'", "'120'", "'100'", "'130'", + "'140'", "'150'", "'330'", "'300'", "'310'", "'320'", "'400'", "'410'", + "'420'", "'430'", "'440'", "'450'", "'460'", null, null, null, null, null, null, null, null, null, null, "'\"'" }; } private static final String[] _LITERAL_NAMES = makeLiteralNames(); private static String[] makeSymbolicNames() { return new String[] { - null, "COLON", "UNIFORM", "BUFFER", "IN", "OUT", "INOUT", "HIGHP", "MEDIUMP", - "LOWP", "PRECISION", "CONST", "PRECISE", "INVARIANT", "SMOOTH", "FLAT", - "CENTROID", "ATTRIBUTE", "VOLATILE", "VARYING", "SHARED", "LAYOUT", "DOT_LENGTH_METHOD_CALL", - "NOPERSPECTIVE", "SAMPLE", "PATCH", "COHERENT", "RESTRICT", "READONLY", - "WRITEONLY", "SUBROUTINE", "DEVICECOHERENT", "QUEUEFAMILYCOHERENT", "WORKGROUPCOHERENT", - "SUBGROUPCOHERENT", "NONPRIVATE", "RAY_PAYLOAD_EXT", "RAY_PAYLOAD_IN_EXT", - "HIT_ATTRIBUTE_EXT", "CALLABLE_DATA_EXT", "CALLABLE_DATA_IN_EXT", "IGNORE_INTERSECTION_EXT", - "TERMINATE_RAY_EXT", "ACCELERATION_STRUCTURE_EXT", "ATOMIC_UINT", "STRUCT", - "IF", "ELSE", "SWITCH", "CASE", "DEFAULT", "WHILE", "DO", "FOR", "CONTINUE", - "BREAK", "RETURN", "DISCARD", "DEMOTE", "UINT16CONSTANT", "INT16CONSTANT", - "UINT32CONSTANT", "INT32CONSTANT", "UINT64CONSTANT", "INT64CONSTANT", - "FLOAT16CONSTANT", "FLOAT32CONSTANT", "FLOAT64CONSTANT", "BOOLCONSTANT", - "BOOL", "BVEC2", "BVEC3", "BVEC4", "INT8", "I8VEC2", "I8VEC3", "I8VEC4", - "UINT8", "U8VEC2", "U8VEC3", "U8VEC4", "INT16", "I16VEC2", "I16VEC3", - "I16VEC4", "UINT16", "U16VEC2", "U16VEC3", "U16VEC4", "INT32", "I32VEC2", - "I32VEC3", "I32VEC4", "UINT32", "U32VEC2", "U32VEC3", "U32VEC4", "INT64", - "I64VEC2", "I64VEC3", "I64VEC4", "UINT64", "U64VEC2", "U64VEC3", "U64VEC4", - "FLOAT16", "F16VEC2", "F16VEC3", "F16VEC4", "F16MAT2X2", "F16MAT2X3", - "F16MAT2X4", "F16MAT3X2", "F16MAT3X3", "F16MAT3X4", "F16MAT4X2", "F16MAT4X3", - "F16MAT4X4", "FLOAT32", "F32VEC2", "F32VEC3", "F32VEC4", "F32MAT2X2", - "F32MAT2X3", "F32MAT2X4", "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", "F32MAT4X2", - "F32MAT4X3", "F32MAT4X4", "FLOAT64", "F64VEC2", "F64VEC3", "F64VEC4", - "F64MAT2X2", "F64MAT2X3", "F64MAT2X4", "F64MAT3X2", "F64MAT3X3", "F64MAT3X4", - "F64MAT4X2", "F64MAT4X3", "F64MAT4X4", "IMAGE1D", "IMAGE2D", "IMAGE3D", - "UIMAGE1D", "UIMAGE2D", "UIMAGE3D", "IIMAGE1D", "IIMAGE2D", "IIMAGE3D", - "SAMPLER1D", "SAMPLER2D", "SAMPLER3D", "SAMPLER2DRECT", "SAMPLER1DSHADOW", - "SAMPLER2DSHADOW", "SAMPLER2DRECTSHADOW", "SAMPLER1DARRAY", "SAMPLER2DARRAY", - "SAMPLER1DARRAYSHADOW", "SAMPLER2DARRAYSHADOW", "ISAMPLER1D", "ISAMPLER2D", - "ISAMPLER2DRECT", "ISAMPLER3D", "ISAMPLER1DARRAY", "ISAMPLER2DARRAY", - "USAMPLER1D", "USAMPLER2D", "USAMPLER2DRECT", "USAMPLER3D", "USAMPLER1DARRAY", - "USAMPLER2DARRAY", "SAMPLER2DMS", "ISAMPLER2DMS", "USAMPLER2DMS", "SAMPLER2DMSARRAY", - "ISAMPLER2DMSARRAY", "USAMPLER2DMSARRAY", "IMAGE2DRECT", "IMAGE1DARRAY", - "IMAGE2DARRAY", "IMAGE2DMS", "IMAGE2DMSARRAY", "IIMAGE2DRECT", "IIMAGE1DARRAY", - "IIMAGE2DARRAY", "IIMAGE2DMS", "IIMAGE2DMSARRAY", "UIMAGE2DRECT", "UIMAGE1DARRAY", - "UIMAGE2DARRAY", "UIMAGE2DMS", "UIMAGE2DMSARRAY", "SAMPLERCUBESHADOW", - "SAMPLERCUBEARRAYSHADOW", "SAMPLERCUBE", "ISAMPLERCUBE", "USAMPLERCUBE", - "SAMPLERBUFFER", "ISAMPLERBUFFER", "USAMPLERBUFFER", "SAMPLERCUBEARRAY", - "ISAMPLERCUBEARRAY", "USAMPLERCUBEARRAY", "IMAGECUBE", "UIMAGECUBE", - "IIMAGECUBE", "IMAGEBUFFER", "IIMAGEBUFFER", "UIMAGEBUFFER", "IMAGECUBEARRAY", - "IIMAGECUBEARRAY", "UIMAGECUBEARRAY", "INC_OP", "DEC_OP", "VOID", "LEFT_OP", - "RIGHT_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "LOGICAL_AND_OP", "LOGICAL_XOR_OP", - "LOGICAL_OR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "MOD_ASSIGN", "ADD_ASSIGN", - "SUB_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", - "OR_ASSIGN", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "SEMICOLON", "LBRACKET", - "RBRACKET", "COMMA", "DOT", "PLUS_OP", "MINUS_OP", "LOGICAL_NOT_OP", - "BITWISE_NEG_OP", "TIMES_OP", "DIV_OP", "MOD_OP", "LT_OP", "GT_OP", "BITWISE_AND_OP", - "BITWISE_OR_OP", "BITWISE_XOR_OP", "QUERY_OP", "ASSIGN_OP", "PP_ENTER_MODE", - "PP_EMPTY", "NR_LINE", "NR", "IDENTIFIER", "LINE_CONTINUE", "LINE_COMMENT", - "BLOCK_COMMENT", "WS", "EOL", "NR_EXTENSION", "NR_VERSION", "NR_CUSTOM", - "NR_INCLUDE", "NR_PRAGMA", "NR_PRAGMA_DEBUG", "NR_PRAGMA_OPTIMIZE", "NR_PRAGMA_INVARIANT", - "NR_ON", "NR_OFF", "NR_ALL", "NR_REQUIRE", "NR_ENABLE", "NR_WARN", "NR_DISABLE", - "NR_COLON", "NR_LPAREN", "NR_RPAREN", "NR_STDGL", "NR_CORE", "NR_COMPATIBILITY", - "NR_ES", "NR_GLSL_110", "NR_GLSL_120", "NR_GLSLES_100", "NR_GLSL_130", - "NR_GLSL_140", "NR_GLSL_150", "NR_GLSL_330", "NR_GLSLES_300", "NR_GLSLES_310", - "NR_GLSLES_320", "NR_GLSL_400", "NR_GLSL_410", "NR_GLSL_420", "NR_GLSL_430", - "NR_GLSL_440", "NR_GLSL_450", "NR_GLSL_460", "NR_STRING_START", "NR_STRING_START_ANGLE", - "NR_INTCONSTANT", "NR_IDENTIFIER", "NR_LINE_CONTINUE", "NR_LINE_COMMENT", - "NR_BLOCK_COMMENT", "NR_EOL", "NR_WS", "S_CONTENT", "S_STRING_END", "S_CONTENT_ANGLE", - "S_STRING_END_ANGLE", "C_LINE_COMMENT", "C_BLOCK_COMMENT", "C_EOL", "C_WS", - "C_CONTENT", "PP_LINE_CONTINUE", "PP_LINE_COMMENT", "PP_BLOCK_COMMENT", + null, "COLON", "UNIFORM", "BUFFER", "IN", "OUT", "INOUT", "HIGHP", "MEDIUMP", + "LOWP", "PRECISION", "CONST", "PRECISE", "INVARIANT", "SMOOTH", "FLAT", + "CENTROID", "ATTRIBUTE", "VOLATILE", "VARYING", "SHARED", "LAYOUT", "DOT_LENGTH_METHOD_CALL", + "NOPERSPECTIVE", "SAMPLE", "PATCH", "COHERENT", "RESTRICT", "READONLY", + "WRITEONLY", "SUBROUTINE", "DEVICECOHERENT", "QUEUEFAMILYCOHERENT", "WORKGROUPCOHERENT", + "SUBGROUPCOHERENT", "NONPRIVATE", "RAY_PAYLOAD_EXT", "RAY_PAYLOAD_IN_EXT", + "HIT_ATTRIBUTE_EXT", "CALLABLE_DATA_EXT", "CALLABLE_DATA_IN_EXT", "IGNORE_INTERSECTION_EXT", + "TERMINATE_RAY_EXT", "ACCELERATION_STRUCTURE_EXT", "ATOMIC_UINT", "STRUCT", + "IF", "ELSE", "SWITCH", "CASE", "DEFAULT", "WHILE", "DO", "FOR", "CONTINUE", + "BREAK", "RETURN", "DISCARD", "DEMOTE", "UINT16CONSTANT", "INT16CONSTANT", + "UINT32CONSTANT", "INT32CONSTANT", "UINT64CONSTANT", "INT64CONSTANT", + "FLOAT16CONSTANT", "FLOAT32CONSTANT", "FLOAT64CONSTANT", "BOOLCONSTANT", + "BOOL", "BVEC2", "BVEC3", "BVEC4", "INT8", "I8VEC2", "I8VEC3", "I8VEC4", + "UINT8", "U8VEC2", "U8VEC3", "U8VEC4", "INT16", "I16VEC2", "I16VEC3", + "I16VEC4", "UINT16", "U16VEC2", "U16VEC3", "U16VEC4", "INT32", "I32VEC2", + "I32VEC3", "I32VEC4", "UINT32", "U32VEC2", "U32VEC3", "U32VEC4", "INT64", + "I64VEC2", "I64VEC3", "I64VEC4", "UINT64", "U64VEC2", "U64VEC3", "U64VEC4", + "FLOAT16", "F16VEC2", "F16VEC3", "F16VEC4", "F16MAT2X2", "F16MAT2X3", + "F16MAT2X4", "F16MAT3X2", "F16MAT3X3", "F16MAT3X4", "F16MAT4X2", "F16MAT4X3", + "F16MAT4X4", "FLOAT32", "F32VEC2", "F32VEC3", "F32VEC4", "F32MAT2X2", + "F32MAT2X3", "F32MAT2X4", "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", "F32MAT4X2", + "F32MAT4X3", "F32MAT4X4", "FLOAT64", "F64VEC2", "F64VEC3", "F64VEC4", + "F64MAT2X2", "F64MAT2X3", "F64MAT2X4", "F64MAT3X2", "F64MAT3X3", "F64MAT3X4", + "F64MAT4X2", "F64MAT4X3", "F64MAT4X4", "IMAGE1D", "IMAGE2D", "IMAGE3D", + "UIMAGE1D", "UIMAGE2D", "UIMAGE3D", "IIMAGE1D", "IIMAGE2D", "IIMAGE3D", + "SAMPLER1D", "SAMPLER2D", "SAMPLER3D", "SAMPLER2DRECT", "SAMPLER1DSHADOW", + "SAMPLER2DSHADOW", "SAMPLER2DRECTSHADOW", "SAMPLER1DARRAY", "SAMPLER2DARRAY", + "SAMPLER1DARRAYSHADOW", "SAMPLER2DARRAYSHADOW", "ISAMPLER1D", "ISAMPLER2D", + "ISAMPLER2DRECT", "ISAMPLER3D", "ISAMPLER1DARRAY", "ISAMPLER2DARRAY", + "USAMPLER1D", "USAMPLER2D", "USAMPLER2DRECT", "USAMPLER3D", "USAMPLER1DARRAY", + "USAMPLER2DARRAY", "SAMPLER2DMS", "ISAMPLER2DMS", "USAMPLER2DMS", "SAMPLER2DMSARRAY", + "ISAMPLER2DMSARRAY", "USAMPLER2DMSARRAY", "IMAGE2DRECT", "IMAGE1DARRAY", + "IMAGE2DARRAY", "IMAGE2DMS", "IMAGE2DMSARRAY", "IIMAGE2DRECT", "IIMAGE1DARRAY", + "IIMAGE2DARRAY", "IIMAGE2DMS", "IIMAGE2DMSARRAY", "UIMAGE2DRECT", "UIMAGE1DARRAY", + "UIMAGE2DARRAY", "UIMAGE2DMS", "UIMAGE2DMSARRAY", "SAMPLERCUBESHADOW", + "SAMPLERCUBEARRAYSHADOW", "SAMPLERCUBE", "ISAMPLERCUBE", "USAMPLERCUBE", + "SAMPLERBUFFER", "ISAMPLERBUFFER", "USAMPLERBUFFER", "SAMPLERCUBEARRAY", + "ISAMPLERCUBEARRAY", "USAMPLERCUBEARRAY", "IMAGECUBE", "UIMAGECUBE", + "IIMAGECUBE", "IMAGEBUFFER", "IIMAGEBUFFER", "UIMAGEBUFFER", "IMAGECUBEARRAY", + "IIMAGECUBEARRAY", "UIMAGECUBEARRAY", "INC_OP", "DEC_OP", "VOID", "LEFT_OP", + "RIGHT_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "LOGICAL_AND_OP", "LOGICAL_XOR_OP", + "LOGICAL_OR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "MOD_ASSIGN", "ADD_ASSIGN", + "SUB_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", + "OR_ASSIGN", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "SEMICOLON", "LBRACKET", + "RBRACKET", "COMMA", "DOT", "PLUS_OP", "MINUS_OP", "LOGICAL_NOT_OP", + "BITWISE_NEG_OP", "TIMES_OP", "DIV_OP", "MOD_OP", "LT_OP", "GT_OP", "BITWISE_AND_OP", + "BITWISE_OR_OP", "BITWISE_XOR_OP", "QUERY_OP", "ASSIGN_OP", "PP_ENTER_MODE", + "PP_EMPTY", "NR_LINE", "NR", "IDENTIFIER", "LINE_CONTINUE", "LINE_COMMENT", + "BLOCK_COMMENT", "WS", "EOL", "NR_EXTENSION", "NR_VERSION", "NR_CUSTOM", + "NR_INCLUDE", "NR_PRAGMA", "NR_PRAGMA_DEBUG", "NR_PRAGMA_OPTIMIZE", "NR_PRAGMA_INVARIANT", + "NR_ON", "NR_OFF", "NR_ALL", "NR_REQUIRE", "NR_ENABLE", "NR_WARN", "NR_DISABLE", + "NR_COLON", "NR_LPAREN", "NR_RPAREN", "NR_STDGL", "NR_CORE", "NR_COMPATIBILITY", + "NR_ES", "NR_GLSL_110", "NR_GLSL_120", "NR_GLSLES_100", "NR_GLSL_130", + "NR_GLSL_140", "NR_GLSL_150", "NR_GLSL_330", "NR_GLSLES_300", "NR_GLSLES_310", + "NR_GLSLES_320", "NR_GLSL_400", "NR_GLSL_410", "NR_GLSL_420", "NR_GLSL_430", + "NR_GLSL_440", "NR_GLSL_450", "NR_GLSL_460", "NR_STRING_START", "NR_STRING_START_ANGLE", + "NR_INTCONSTANT", "NR_IDENTIFIER", "NR_LINE_CONTINUE", "NR_LINE_COMMENT", + "NR_BLOCK_COMMENT", "NR_EOL", "NR_WS", "S_CONTENT", "S_STRING_END", "S_CONTENT_ANGLE", + "S_STRING_END_ANGLE", "C_LINE_COMMENT", "C_BLOCK_COMMENT", "C_EOL", "C_WS", + "C_CONTENT", "PP_LINE_CONTINUE", "PP_LINE_COMMENT", "PP_BLOCK_COMMENT", "PP_EOL", "PP_CONTENT" }; } @@ -1132,7 +1135,7 @@ public FiniteExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_finiteExpression; } - + public FiniteExpressionContext() { } public void copyFrom(FiniteExpressionContext ctx) { super.copyFrom(ctx); @@ -2182,7 +2185,7 @@ private FiniteExpressionContext finiteExpression(int _p) throws RecognitionExcep } break; } - } + } } setState(279); _errHandler.sync(this); @@ -2257,7 +2260,7 @@ public final ExpressionContext expression() throws RecognitionException { ((ExpressionContext)_localctx).finiteExpression = finiteExpression(0); ((ExpressionContext)_localctx).items.add(((ExpressionContext)_localctx).finiteExpression); } - } + } } setState(287); _errHandler.sync(this); @@ -2282,7 +2285,7 @@ public DeclarationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_declaration; } - + public DeclarationContext() { } public void copyFrom(DeclarationContext ctx) { super.copyFrom(ctx); @@ -3533,7 +3536,7 @@ public LayoutQualifierIdContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_layoutQualifierId; } - + public LayoutQualifierIdContext() { } public void copyFrom(LayoutQualifierIdContext ctx) { super.copyFrom(ctx); @@ -3889,7 +3892,7 @@ public final TypeQualifierContext typeQualifier() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(477); + setState(477); _errHandler.sync(this); _la = _input.LA(1); do { @@ -3968,7 +3971,7 @@ public final TypeQualifierContext typeQualifier() throws RecognitionException { throw new NoViableAltException(this); } } - setState(479); + setState(479); _errHandler.sync(this); _la = _input.LA(1); } while ( ((_la) & ~0x3f) == 0 && ((1L << _la) & 2199019060220L) != 0 ); @@ -4262,7 +4265,7 @@ public final ArraySpecifierContext arraySpecifier() throws RecognitionException try { enterOuterAlt(_localctx, 1); { - setState(491); + setState(491); _errHandler.sync(this); _la = _input.LA(1); do { @@ -4272,7 +4275,7 @@ public final ArraySpecifierContext arraySpecifier() throws RecognitionException arraySpecifierSegment(); } } - setState(493); + setState(493); _errHandler.sync(this); _la = _input.LA(1); } while ( _la==LBRACKET ); @@ -4702,7 +4705,7 @@ public final StructBodyContext structBody() throws RecognitionException { { setState(511); match(LBRACE); - setState(513); + setState(513); _errHandler.sync(this); _la = _input.LA(1); do { @@ -4712,7 +4715,7 @@ public final StructBodyContext structBody() throws RecognitionException { structMember(); } } - setState(515); + setState(515); _errHandler.sync(this); _la = _input.LA(1); } while ( ((_la) & ~0x3f) == 0 && ((1L << _la) & 63771670215676L) != 0 || (((_la - 69)) & ~0x3f) == 0 && ((1L << (_la - 69)) & -1L) != 0 || (((_la - 133)) & ~0x3f) == 0 && ((1L << (_la - 133)) & -1L) != 0 || (((_la - 197)) & ~0x3f) == 0 && ((1L << (_la - 197)) & 5242879L) != 0 || _la==IDENTIFIER ); @@ -4873,8 +4876,8 @@ public final StructDeclaratorContext structDeclarator() throws RecognitionExcept public static class InitializerContext extends ParserRuleContext { public InitializerContext initializer; public List initializers = new ArrayList(); - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); + public FiniteExpressionContext finiteExpression() { + return getRuleContext(FiniteExpressionContext.class,0); } public TerminalNode LBRACE() { return getToken(GLSLParser.LBRACE, 0); } public TerminalNode RBRACE() { return getToken(GLSLParser.RBRACE, 0); } @@ -5089,7 +5092,7 @@ public final InitializerContext initializer() throws RecognitionException { enterOuterAlt(_localctx, 1); { setState(534); - expression(); + finiteExpression(0); } break; case LBRACE: @@ -5118,7 +5121,7 @@ public final InitializerContext initializer() throws RecognitionException { ((InitializerContext)_localctx).initializer = initializer(); ((InitializerContext)_localctx).initializers.add(((InitializerContext)_localctx).initializer); } - } + } } setState(543); _errHandler.sync(this); @@ -5749,7 +5752,7 @@ public CaseLabelContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_caseLabel; } - + public CaseLabelContext() { } public void copyFrom(CaseLabelContext ctx) { super.copyFrom(ctx); @@ -6162,7 +6165,7 @@ public JumpStatementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_jumpStatement; } - + public JumpStatementContext() { } public void copyFrom(JumpStatementContext ctx) { super.copyFrom(ctx); @@ -6854,7 +6857,7 @@ private boolean finiteExpression_sempred(FiniteExpressionContext _localctx, int "\u0000\u0000\u0210\u0211\u0005\u00f3\u0000\u0000\u0211G\u0001\u0000\u0000"+ "\u0000\u0212\u0214\u0005\u010a\u0000\u0000\u0213\u0215\u0003:\u001d\u0000"+ "\u0214\u0213\u0001\u0000\u0000\u0000\u0214\u0215\u0001\u0000\u0000\u0000"+ - "\u0215I\u0001\u0000\u0000\u0000\u0216\u0227\u0003\u0016\u000b\u0000\u0217"+ + "\u0215I\u0001\u0000\u0000\u0000\u0216\u0227\u0003\u0014\n\u0000\u0217"+ "\u0223\u0005\u00f1\u0000\u0000\u0218\u021d\u0003J%\u0000\u0219\u021a\u0005"+ "\u00f6\u0000\u0000\u021a\u021c\u0003J%\u0000\u021b\u0219\u0001\u0000\u0000"+ "\u0000\u021c\u021f\u0001\u0000\u0000\u0000\u021d\u021b\u0001\u0000\u0000"+ @@ -6952,4 +6955,4 @@ private boolean finiteExpression_sempred(FiniteExpressionContext _localctx, int _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); } } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/douira/glsl_transformer/GLSLParser.tokens b/src/main/java/io/github/douira/glsl_transformer/GLSLParser.tokens new file mode 100644 index 0000000000..c10b12e6b6 --- /dev/null +++ b/src/main/java/io/github/douira/glsl_transformer/GLSLParser.tokens @@ -0,0 +1,578 @@ +COLON=1 +UNIFORM=2 +BUFFER=3 +IN=4 +OUT=5 +INOUT=6 +HIGHP=7 +MEDIUMP=8 +LOWP=9 +PRECISION=10 +CONST=11 +PRECISE=12 +INVARIANT=13 +SMOOTH=14 +FLAT=15 +CENTROID=16 +ATTRIBUTE=17 +VOLATILE=18 +VARYING=19 +SHARED=20 +LAYOUT=21 +DOT_LENGTH_METHOD_CALL=22 +NOPERSPECTIVE=23 +SAMPLE=24 +PATCH=25 +COHERENT=26 +RESTRICT=27 +READONLY=28 +WRITEONLY=29 +SUBROUTINE=30 +DEVICECOHERENT=31 +QUEUEFAMILYCOHERENT=32 +WORKGROUPCOHERENT=33 +SUBGROUPCOHERENT=34 +NONPRIVATE=35 +RAY_PAYLOAD_EXT=36 +RAY_PAYLOAD_IN_EXT=37 +HIT_ATTRIBUTE_EXT=38 +CALLABLE_DATA_EXT=39 +CALLABLE_DATA_IN_EXT=40 +IGNORE_INTERSECTION_EXT=41 +TERMINATE_RAY_EXT=42 +ACCELERATION_STRUCTURE_EXT=43 +ATOMIC_UINT=44 +STRUCT=45 +IF=46 +ELSE=47 +SWITCH=48 +CASE=49 +DEFAULT=50 +WHILE=51 +DO=52 +FOR=53 +CONTINUE=54 +BREAK=55 +RETURN=56 +DISCARD=57 +DEMOTE=58 +UINT16CONSTANT=59 +INT16CONSTANT=60 +UINT32CONSTANT=61 +INT32CONSTANT=62 +UINT64CONSTANT=63 +INT64CONSTANT=64 +FLOAT16CONSTANT=65 +FLOAT32CONSTANT=66 +FLOAT64CONSTANT=67 +BOOLCONSTANT=68 +BOOL=69 +BVEC2=70 +BVEC3=71 +BVEC4=72 +INT8=73 +I8VEC2=74 +I8VEC3=75 +I8VEC4=76 +UINT8=77 +U8VEC2=78 +U8VEC3=79 +U8VEC4=80 +INT16=81 +I16VEC2=82 +I16VEC3=83 +I16VEC4=84 +UINT16=85 +U16VEC2=86 +U16VEC3=87 +U16VEC4=88 +INT32=89 +I32VEC2=90 +I32VEC3=91 +I32VEC4=92 +UINT32=93 +U32VEC2=94 +U32VEC3=95 +U32VEC4=96 +INT64=97 +I64VEC2=98 +I64VEC3=99 +I64VEC4=100 +UINT64=101 +U64VEC2=102 +U64VEC3=103 +U64VEC4=104 +FLOAT16=105 +F16VEC2=106 +F16VEC3=107 +F16VEC4=108 +F16MAT2X2=109 +F16MAT2X3=110 +F16MAT2X4=111 +F16MAT3X2=112 +F16MAT3X3=113 +F16MAT3X4=114 +F16MAT4X2=115 +F16MAT4X3=116 +F16MAT4X4=117 +FLOAT32=118 +F32VEC2=119 +F32VEC3=120 +F32VEC4=121 +F32MAT2X2=122 +F32MAT2X3=123 +F32MAT2X4=124 +F32MAT3X2=125 +F32MAT3X3=126 +F32MAT3X4=127 +F32MAT4X2=128 +F32MAT4X3=129 +F32MAT4X4=130 +FLOAT64=131 +F64VEC2=132 +F64VEC3=133 +F64VEC4=134 +F64MAT2X2=135 +F64MAT2X3=136 +F64MAT2X4=137 +F64MAT3X2=138 +F64MAT3X3=139 +F64MAT3X4=140 +F64MAT4X2=141 +F64MAT4X3=142 +F64MAT4X4=143 +IMAGE1D=144 +IMAGE2D=145 +IMAGE3D=146 +UIMAGE1D=147 +UIMAGE2D=148 +UIMAGE3D=149 +IIMAGE1D=150 +IIMAGE2D=151 +IIMAGE3D=152 +SAMPLER1D=153 +SAMPLER2D=154 +SAMPLER3D=155 +SAMPLER2DRECT=156 +SAMPLER1DSHADOW=157 +SAMPLER2DSHADOW=158 +SAMPLER2DRECTSHADOW=159 +SAMPLER1DARRAY=160 +SAMPLER2DARRAY=161 +SAMPLER1DARRAYSHADOW=162 +SAMPLER2DARRAYSHADOW=163 +ISAMPLER1D=164 +ISAMPLER2D=165 +ISAMPLER2DRECT=166 +ISAMPLER3D=167 +ISAMPLER1DARRAY=168 +ISAMPLER2DARRAY=169 +USAMPLER1D=170 +USAMPLER2D=171 +USAMPLER2DRECT=172 +USAMPLER3D=173 +USAMPLER1DARRAY=174 +USAMPLER2DARRAY=175 +SAMPLER2DMS=176 +ISAMPLER2DMS=177 +USAMPLER2DMS=178 +SAMPLER2DMSARRAY=179 +ISAMPLER2DMSARRAY=180 +USAMPLER2DMSARRAY=181 +IMAGE2DRECT=182 +IMAGE1DARRAY=183 +IMAGE2DARRAY=184 +IMAGE2DMS=185 +IMAGE2DMSARRAY=186 +IIMAGE2DRECT=187 +IIMAGE1DARRAY=188 +IIMAGE2DARRAY=189 +IIMAGE2DMS=190 +IIMAGE2DMSARRAY=191 +UIMAGE2DRECT=192 +UIMAGE1DARRAY=193 +UIMAGE2DARRAY=194 +UIMAGE2DMS=195 +UIMAGE2DMSARRAY=196 +SAMPLERCUBESHADOW=197 +SAMPLERCUBEARRAYSHADOW=198 +SAMPLERCUBE=199 +ISAMPLERCUBE=200 +USAMPLERCUBE=201 +SAMPLERBUFFER=202 +ISAMPLERBUFFER=203 +USAMPLERBUFFER=204 +SAMPLERCUBEARRAY=205 +ISAMPLERCUBEARRAY=206 +USAMPLERCUBEARRAY=207 +IMAGECUBE=208 +UIMAGECUBE=209 +IIMAGECUBE=210 +IMAGEBUFFER=211 +IIMAGEBUFFER=212 +UIMAGEBUFFER=213 +IMAGECUBEARRAY=214 +IIMAGECUBEARRAY=215 +UIMAGECUBEARRAY=216 +INC_OP=217 +DEC_OP=218 +VOID=219 +LEFT_OP=220 +RIGHT_OP=221 +LE_OP=222 +GE_OP=223 +EQ_OP=224 +NE_OP=225 +LOGICAL_AND_OP=226 +LOGICAL_XOR_OP=227 +LOGICAL_OR_OP=228 +MUL_ASSIGN=229 +DIV_ASSIGN=230 +MOD_ASSIGN=231 +ADD_ASSIGN=232 +SUB_ASSIGN=233 +LEFT_ASSIGN=234 +RIGHT_ASSIGN=235 +AND_ASSIGN=236 +XOR_ASSIGN=237 +OR_ASSIGN=238 +LPAREN=239 +RPAREN=240 +LBRACE=241 +RBRACE=242 +SEMICOLON=243 +LBRACKET=244 +RBRACKET=245 +COMMA=246 +DOT=247 +PLUS_OP=248 +MINUS_OP=249 +LOGICAL_NOT_OP=250 +BITWISE_NEG_OP=251 +TIMES_OP=252 +DIV_OP=253 +MOD_OP=254 +LT_OP=255 +GT_OP=256 +BITWISE_AND_OP=257 +BITWISE_OR_OP=258 +BITWISE_XOR_OP=259 +QUERY_OP=260 +ASSIGN_OP=261 +PP_ENTER_MODE=262 +PP_EMPTY=263 +NR_LINE=264 +NR=265 +IDENTIFIER=266 +LINE_CONTINUE=267 +LINE_COMMENT=268 +BLOCK_COMMENT=269 +WS=270 +EOL=271 +NR_EXTENSION=272 +NR_VERSION=273 +NR_CUSTOM=274 +NR_INCLUDE=275 +NR_PRAGMA=276 +NR_PRAGMA_DEBUG=277 +NR_PRAGMA_OPTIMIZE=278 +NR_PRAGMA_INVARIANT=279 +NR_ON=280 +NR_OFF=281 +NR_ALL=282 +NR_REQUIRE=283 +NR_ENABLE=284 +NR_WARN=285 +NR_DISABLE=286 +NR_COLON=287 +NR_LPAREN=288 +NR_RPAREN=289 +NR_STDGL=290 +NR_CORE=291 +NR_COMPATIBILITY=292 +NR_ES=293 +NR_GLSL_110=294 +NR_GLSL_120=295 +NR_GLSLES_100=296 +NR_GLSL_130=297 +NR_GLSL_140=298 +NR_GLSL_150=299 +NR_GLSL_330=300 +NR_GLSLES_300=301 +NR_GLSLES_310=302 +NR_GLSLES_320=303 +NR_GLSL_400=304 +NR_GLSL_410=305 +NR_GLSL_420=306 +NR_GLSL_430=307 +NR_GLSL_440=308 +NR_GLSL_450=309 +NR_GLSL_460=310 +NR_STRING_START=311 +NR_STRING_START_ANGLE=312 +NR_INTCONSTANT=313 +NR_IDENTIFIER=314 +NR_LINE_CONTINUE=315 +NR_LINE_COMMENT=316 +NR_BLOCK_COMMENT=317 +NR_EOL=318 +NR_WS=319 +S_CONTENT=320 +S_STRING_END=321 +S_CONTENT_ANGLE=322 +S_STRING_END_ANGLE=323 +C_LINE_COMMENT=324 +C_BLOCK_COMMENT=325 +C_EOL=326 +C_WS=327 +C_CONTENT=328 +PP_LINE_CONTINUE=329 +PP_LINE_COMMENT=330 +PP_BLOCK_COMMENT=331 +PP_EOL=332 +PP_CONTENT=333 +'uniform'=2 +'buffer'=3 +'in'=4 +'out'=5 +'inout'=6 +'highp'=7 +'mediump'=8 +'lowp'=9 +'precision'=10 +'const'=11 +'precise'=12 +'smooth'=14 +'flat'=15 +'centroid'=16 +'attribute'=17 +'volatile'=18 +'varying'=19 +'shared'=20 +'layout'=21 +'.length()'=22 +'noperspective'=23 +'sample'=24 +'patch'=25 +'coherent'=26 +'restrict'=27 +'readonly'=28 +'writeonly'=29 +'subroutine'=30 +'devicecoherent'=31 +'queuefamilycoherent'=32 +'workgroupcoherent'=33 +'subgroupcoherent'=34 +'nonprivate'=35 +'rayPayloadEXT'=36 +'rayPayloadInEXT'=37 +'hitAttributeEXT'=38 +'callableDataEXT'=39 +'callableDataInEXT'=40 +'ignoreIntersectionEXT'=41 +'terminateRayEXT'=42 +'accelerationStructureEXT'=43 +'atomic_uint'=44 +'struct'=45 +'if'=46 +'else'=47 +'switch'=48 +'case'=49 +'default'=50 +'while'=51 +'do'=52 +'for'=53 +'continue'=54 +'break'=55 +'return'=56 +'discard'=57 +'demote'=58 +'bool'=69 +'bvec2'=70 +'bvec3'=71 +'bvec4'=72 +'int8_t'=73 +'i8vec2'=74 +'i8vec3'=75 +'i8vec4'=76 +'uint8_t'=77 +'u8vec2'=78 +'u8vec3'=79 +'u8vec4'=80 +'int16_t'=81 +'i16vec2'=82 +'i16vec3'=83 +'i16vec4'=84 +'uint16_t'=85 +'u16vec2'=86 +'u16vec3'=87 +'u16vec4'=88 +'int64_t'=97 +'i64vec2'=98 +'i64vec3'=99 +'i64vec4'=100 +'uint64_t'=101 +'u64vec2'=102 +'u64vec3'=103 +'u64vec4'=104 +'float16_t'=105 +'f16vec2'=106 +'f16vec3'=107 +'f16vec4'=108 +'f16mat2x3'=110 +'f16mat2x4'=111 +'f16mat3x2'=112 +'f16mat3x4'=114 +'f16mat4x2'=115 +'f16mat4x3'=116 +'image1D'=144 +'image2D'=145 +'image3D'=146 +'uimage1D'=147 +'uimage2D'=148 +'uimage3D'=149 +'iimage1D'=150 +'iimage2D'=151 +'iimage3D'=152 +'sampler1D'=153 +'sampler2D'=154 +'sampler3D'=155 +'sampler2DRect'=156 +'sampler1DShadow'=157 +'sampler2DShadow'=158 +'sampler2DRectShadow'=159 +'sampler1DArray'=160 +'sampler2DArray'=161 +'sampler1DArrayShadow'=162 +'sampler2DArrayShadow'=163 +'isampler1D'=164 +'isampler2D'=165 +'isampler2DRect'=166 +'isampler3D'=167 +'isampler1DArray'=168 +'isampler2DArray'=169 +'usampler1D'=170 +'usampler2D'=171 +'usampler2DRect'=172 +'usampler3D'=173 +'usampler1DArray'=174 +'usampler2DArray'=175 +'sampler2DMS'=176 +'isampler2DMS'=177 +'usampler2DMS'=178 +'sampler2DMSArray'=179 +'isampler2DMSArray'=180 +'usampler2DMSArray'=181 +'image2DRect'=182 +'image1DArray'=183 +'image2DArray'=184 +'image2DMS'=185 +'image2DMSArray'=186 +'iimage2DRect'=187 +'iimage1DArray'=188 +'iimage2DArray'=189 +'iimage2DMS'=190 +'iimage2DMSArray'=191 +'uimage2DRect'=192 +'uimage1DArray'=193 +'uimage2DArray'=194 +'uimage2DMS'=195 +'uimage2DMSArray'=196 +'samplerCubeShadow'=197 +'samplerCubeArrayShadow'=198 +'samplerCube'=199 +'isamplerCube'=200 +'usamplerCube'=201 +'samplerBuffer'=202 +'isamplerBuffer'=203 +'usamplerBuffer'=204 +'samplerCubeArray'=205 +'isamplerCubeArray'=206 +'usamplerCubeArray'=207 +'imageCube'=208 +'uimageCube'=209 +'iimageCube'=210 +'imageBuffer'=211 +'iimageBuffer'=212 +'uimageBuffer'=213 +'imageCubeArray'=214 +'iimageCubeArray'=215 +'uimageCubeArray'=216 +'++'=217 +'--'=218 +'void'=219 +'<<'=220 +'>>'=221 +'<='=222 +'>='=223 +'=='=224 +'!='=225 +'&&'=226 +'^^'=227 +'||'=228 +'*='=229 +'/='=230 +'%='=231 +'+='=232 +'-='=233 +'<<='=234 +'>>='=235 +'&='=236 +'^='=237 +'|='=238 +'{'=241 +'}'=242 +';'=243 +'['=244 +']'=245 +','=246 +'.'=247 +'+'=248 +'-'=249 +'!'=250 +'~'=251 +'*'=252 +'/'=253 +'%'=254 +'<'=255 +'&'=257 +'|'=258 +'^'=259 +'?'=260 +'='=261 +'#'=265 +'extension'=272 +'version'=273 +'include'=275 +'pragma'=276 +'debug'=277 +'optimize'=278 +'on'=280 +'off'=281 +'all'=282 +'require'=283 +'enable'=284 +'warn'=285 +'disable'=286 +'STDGL'=290 +'core'=291 +'compatibility'=292 +'es'=293 +'110'=294 +'120'=295 +'100'=296 +'130'=297 +'140'=298 +'150'=299 +'330'=300 +'300'=301 +'310'=302 +'320'=303 +'400'=304 +'410'=305 +'420'=306 +'430'=307 +'440'=308 +'450'=309 +'460'=310 +'"'=321 diff --git a/src/main/java/io/github/douira/glsl_transformer/GLSLParserBaseListener.java b/src/main/java/io/github/douira/glsl_transformer/GLSLParserBaseListener.java index d32aebb49a..20e51b07b5 100644 --- a/src/main/java/io/github/douira/glsl_transformer/GLSLParserBaseListener.java +++ b/src/main/java/io/github/douira/glsl_transformer/GLSLParserBaseListener.java @@ -1,9 +1,6 @@ // Generated from java-escape by ANTLR 4.11.1 package io.github.douira.glsl_transformer; -import io.github.douira.glsl_transformer.parser.ExtendedParser; - - import repack.antlr.v4.runtime.ParserRuleContext; import repack.antlr.v4.runtime.tree.ErrorNode; import repack.antlr.v4.runtime.tree.TerminalNode; @@ -1048,4 +1045,4 @@ public class GLSLParserBaseListener implements GLSLParserListener { *

The default implementation does nothing.

*/ @Override public void visitErrorNode(ErrorNode node) { } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/douira/glsl_transformer/GLSLParserBaseVisitor.java b/src/main/java/io/github/douira/glsl_transformer/GLSLParserBaseVisitor.java index 1f58f92b8e..bcba876eb8 100644 --- a/src/main/java/io/github/douira/glsl_transformer/GLSLParserBaseVisitor.java +++ b/src/main/java/io/github/douira/glsl_transformer/GLSLParserBaseVisitor.java @@ -1,8 +1,6 @@ // Generated from java-escape by ANTLR 4.11.1 package io.github.douira.glsl_transformer; -import io.github.douira.glsl_transformer.parser.ExtendedParser; - import repack.antlr.v4.runtime.tree.AbstractParseTreeVisitor; /** @@ -603,4 +601,4 @@ public class GLSLParserBaseVisitor extends AbstractParseTreeVisitor implem * {@link #visitChildren} on {@code ctx}.

*/ @Override public T visitDemoteStatement(GLSLParser.DemoteStatementContext ctx) { return visitChildren(ctx); } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/douira/glsl_transformer/GLSLParserListener.java b/src/main/java/io/github/douira/glsl_transformer/GLSLParserListener.java index 92a1689e72..e04d7e196d 100644 --- a/src/main/java/io/github/douira/glsl_transformer/GLSLParserListener.java +++ b/src/main/java/io/github/douira/glsl_transformer/GLSLParserListener.java @@ -1,8 +1,6 @@ // Generated from java-escape by ANTLR 4.11.1 package io.github.douira.glsl_transformer; -import io.github.douira.glsl_transformer.parser.ExtendedParser; - import repack.antlr.v4.runtime.tree.ParseTreeListener; /** @@ -924,4 +922,4 @@ public interface GLSLParserListener extends ParseTreeListener { * @param ctx the parse tree */ void exitDemoteStatement(GLSLParser.DemoteStatementContext ctx); -} \ No newline at end of file +} diff --git a/src/main/java/io/github/douira/glsl_transformer/GLSLParserVisitor.java b/src/main/java/io/github/douira/glsl_transformer/GLSLParserVisitor.java index 7bc3b289de..6cc31c9978 100644 --- a/src/main/java/io/github/douira/glsl_transformer/GLSLParserVisitor.java +++ b/src/main/java/io/github/douira/glsl_transformer/GLSLParserVisitor.java @@ -1,8 +1,6 @@ // Generated from java-escape by ANTLR 4.11.1 package io.github.douira.glsl_transformer; -import io.github.douira.glsl_transformer.parser.ExtendedParser; - import repack.antlr.v4.runtime.tree.ParseTreeVisitor; /** @@ -554,4 +552,4 @@ public interface GLSLParserVisitor extends ParseTreeVisitor { * @return the visitor result */ T visitDemoteStatement(GLSLParser.DemoteStatementContext ctx); -} \ No newline at end of file +} diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/data/ChildNodeList.java b/src/main/java/io/github/douira/glsl_transformer/ast/data/ChildNodeList.java index 77f5f5d52f..8ff7496cba 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/data/ChildNodeList.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/data/ChildNodeList.java @@ -1,14 +1,15 @@ package io.github.douira.glsl_transformer.ast.data; +import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; +import io.github.douira.glsl_transformer.ast.node.abstract_node.InnerASTNode; + import java.util.Collection; import java.util.function.Consumer; import java.util.stream.Stream; -import io.github.douira.glsl_transformer.ast.node.abstract_node.*; - /** * A child list that notifies the given parent of child additions. - * + * * Implementation of the more complex RemovalProxyArray list isn't necessary * because each child notifies its previous parent of the parent change. */ @@ -44,6 +45,23 @@ protected void notifyRemoval(Child removed) { removed.detachParent(); } + /** + * Returns true if the list is empty or contains only null elements. + * + * @return true if the list is empty or contains only null elements + */ + public boolean isNullEmpty() { + if (isEmpty()) { + return true; + } + for (var child : this) { + if (child != null) { + return false; + } + } + return true; + } + protected static Consumer makeChildReplacer(ChildNodeList list, Child child) { return newNode -> { if (newNode == child) { diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/Identifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/Identifier.java index 083b36c69c..ac406f987d 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/Identifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/Identifier.java @@ -1,10 +1,9 @@ package io.github.douira.glsl_transformer.ast.node; -import repack.antlr.v4.runtime.Token; - import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; import io.github.douira.glsl_transformer.ast.query.Root; import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; +import repack.antlr.v4.runtime.Token; public class Identifier extends ASTNode { private String name; @@ -36,11 +35,13 @@ public void setName(String name) { * Sets the name of this identifier without performing validation or registering * this change in the index. This method should only be called internally. Using * it otherwise will lead to inconsistencies. - * + * * @param name The new name of this identifier. */ public void _setNameInternal(String name) { + getRoot().unregisterFastRename(this); this.name = name; + getRoot().registerFastRename(this); } public static final void validateContents(String str) { @@ -74,9 +75,4 @@ public Identifier clone() { public Identifier cloneInto(Root root) { return (Identifier) super.cloneInto(root); } - - @Override - public Identifier cloneSeparate() { - return (Identifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/IterationConditionInitializer.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/IterationConditionInitializer.java index 9ef60cab9c..551e6417c0 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/IterationConditionInitializer.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/IterationConditionInitializer.java @@ -68,9 +68,4 @@ public IterationConditionInitializer clone() { public IterationConditionInitializer cloneInto(Root root) { return (IterationConditionInitializer) super.cloneInto(root); } - - @Override - public IterationConditionInitializer cloneSeparate() { - return (IterationConditionInitializer) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/TranslationUnit.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/TranslationUnit.java index 028751a0c5..7690bb4796 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/TranslationUnit.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/TranslationUnit.java @@ -70,7 +70,7 @@ public void parseAndInjectNodes( ASTInjectionPoint injectionPoint, Stream externalDeclarations) { injectNodes(injectionPoint, - externalDeclarations.map(str -> t.parseExternalDeclaration(this, str))); + externalDeclarations.map(str -> t.parseExternalDeclaration(getRoot(), str))); } /** @@ -88,7 +88,7 @@ public void parseAndInjectNode( String externalDeclaration) { getChildren().add(injectionPoint.getInjectionIndex(this), t.parseExternalDeclaration( - this, + getRoot(), externalDeclaration)); } @@ -105,7 +105,7 @@ public void parseAndInjectNodes( ASTParser t, ASTInjectionPoint injectionPoint, String... externalDeclarations) { - injectNodes(injectionPoint, t.parseExternalDeclarations(this, externalDeclarations)); + injectNodes(injectionPoint, t.parseExternalDeclarations(getRoot(), externalDeclarations)); } public Optional getOneFunctionDefinitionBodyOptional(String functionName) { @@ -156,19 +156,19 @@ public void appendMainFunctionBody(Collection statements) { } public void prependMainFunctionBody(ASTParser t, String... statements) { - prependMainFunctionBody(t.parseStatements(this, statements)); + prependMainFunctionBody(t.parseStatements(getRoot(), statements)); } public void prependMainFunctionBody(ASTParser t, String statement) { - prependMainFunctionBody(t.parseStatement(this, statement)); + prependMainFunctionBody(t.parseStatement(getRoot(), statement)); } public void appendMainFunctionBody(ASTParser t, String... statements) { - appendMainFunctionBody(t.parseStatements(this, statements)); + appendMainFunctionBody(t.parseStatements(getRoot(), statements)); } public void appendMainFunctionBody(ASTParser t, String statement) { - appendMainFunctionBody(t.parseStatement(this, statement)); + appendMainFunctionBody(t.parseStatement(getRoot(), statement)); } public void ensureVersionStatement() { @@ -201,9 +201,4 @@ public TranslationUnit clone() { public TranslationUnit cloneInto(Root root) { return (TranslationUnit) super.cloneInto(root); } - - @Override - public TranslationUnit cloneSeparate() { - return (TranslationUnit) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/VersionStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/VersionStatement.java index 89a0d36d2c..8259e2f168 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/VersionStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/VersionStatement.java @@ -42,9 +42,4 @@ public VersionStatement clone() { public VersionStatement cloneInto(Root root) { return (VersionStatement) super.cloneInto(root); } - - @Override - public VersionStatement cloneSeparate() { - return (VersionStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/abstract_node/ASTNode.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/abstract_node/ASTNode.java index e2b093d269..ebcd116c69 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/abstract_node/ASTNode.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/abstract_node/ASTNode.java @@ -1,20 +1,25 @@ package io.github.douira.glsl_transformer.ast.node.abstract_node; -import java.util.Objects; -import java.util.function.*; -import java.util.stream.Stream; - import io.github.douira.glsl_transformer.ast.data.ChildNodeList; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.transform.*; -import io.github.douira.glsl_transformer.ast.traversal.*; -import io.github.douira.glsl_transformer.util.CompatUtil; +import io.github.douira.glsl_transformer.ast.transform.ASTBuilder; +import io.github.douira.glsl_transformer.ast.transform.SourceLocation; +import io.github.douira.glsl_transformer.ast.transform.Template; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; +import io.github.douira.glsl_transformer.ast.traversal.ASTVoidVisitor; + +import java.util.Objects; +import java.util.function.BiPredicate; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Stream; /** * The AST node represents a node in the abstract syntax tree. Each AST node has * a reference to the shared root object that contains the indexes for querying * the tree. - * + * * Invariants: * 1. The root must contain exactly the nodes that are accessible by * traversing the tree downwards at any time. @@ -26,14 +31,23 @@ * 5. An AST node may only ever be in a tree once. Attempting to insert it * multiple times will cause undefined behavior. Moving a node requires removing * it from one parent and then adding it to another. - * + * * While it is possible to have a single node appear multiple times throughout * the tree (at which point the tree becomes a DAG), this is discuraged since it * violates common expectations like the fact that removing a node doesn't also * affect other parts of the tree. + * + * The tree is constructed from the buttom up in the {@link ASTBuilder}. The + * roots are set on each of the nodes by getting the current active build root + * from the {@link Root}'s global method. */ public abstract class ASTNode { private ASTNode parent; + // the parent this node had before it was replaced, used for ensuring index + // consistency during replacement of this node with another one in the parent. + // In some cases, the index needs to look up the parent of this node even after + // it has been replaced. + private ASTNode lastParent; private Consumer selfReplacer; private Root root = Root.getActiveBuildRoot(); protected Template template = null; @@ -63,6 +77,10 @@ public ASTNode getParent() { return parent; } + public ASTNode getLastParent() { + return lastParent; + } + public boolean hasParent() { return parent != null; } @@ -74,7 +92,7 @@ public Consumer getParentSetter() { /** * Gets the nth parent of this node. The 0th parent is this node. The 1st parent * is the parent of this node. - * + * * @param n the number of parents to go up * @return the nth parent of this node */ @@ -93,7 +111,7 @@ public ASTNode getNthParent(int n) { * Checks if there is an ancestor of this node that fulfills the given * predicate within a limited nubmer of steps after a number of steps skipped. * If the limit is 0, it will only check the current node. - * + * * @param limit the number of parents to check in total * @param skip the number of parents to skip before checking the predicate * @param predicate the predicate to check @@ -117,7 +135,7 @@ public boolean hasAncestor(int limit, int skip, Predicate predicate) { /** * Checks if there is an ancestor of this node that fulfills the given * predicate. - * + * * @param predicate the predicate to check * @return true if there is an ancestor of this node that fulfills the predicate */ @@ -128,7 +146,7 @@ public boolean hasAncestor(Predicate predicate) { /** * Checks if there is an ancestor of this node that is an instance of the given * class. - * + * * @param ancestorType the class to check * @return true if there is an ancestor that is an instance of the given class */ @@ -138,7 +156,7 @@ public boolean hasAncestor(Class ancestorType) { /** * Checks if the given node is an ancestor of this node. - * + * * @param node the node to check * @return true if the given node is an ancestor of this node */ @@ -150,7 +168,7 @@ public boolean hasAncestor(ASTNode node) { * Returns the first ancestor that fulfills the given predicate, limited to a * certain number of steps. If the limit is 0, it will only check the current * node. - * + * * @param limit the number of parents to check in total * @param skip the number of steps to skip before checking the predicate * @param predicate the predicate to check @@ -173,7 +191,7 @@ public ASTNode getAncestor(int limit, int skip, Predicate predicate) { /** * Returns the first ancestor that fulfills the given predicate. - * + * * @param predicate the predicate to check * @return the first ancestor that fulfills the given predicate, or null * otherwise @@ -184,7 +202,7 @@ public ASTNode getAncestor(Predicate predicate) { /** * Returns the first ancestor that is an instance of the given class. - * + * * @param ancestorType the class to check * @return the first ancestor that is an instance of the given class, or null * otherwise @@ -233,67 +251,47 @@ public R getBranchAncestorContinue(Class< /** * Returns a lazy stream of all ancestors of this node. - * + * * @return a stream of the ancestors */ public Stream getAncestors() { - return CompatUtil.iterateStream(this, ASTNode::hasParent, ASTNode::getParent); + return Stream.iterate(this, ASTNode::hasParent, ASTNode::getParent); } /** * Returns the root of this node. - * + * * @return the root */ public Root getRoot() { return root; } - private static class ChangeRootVisitor extends ASTVoidVisitor { - private Root root; - - public ChangeRootVisitor(Root root) { - this.root = root; - } - - @Override - public void visitVoid(ASTNode node) { - node.setRoot(root); - } - } - - private static class UnregisterVisitor extends ASTVoidVisitor { - @Override - public void visitVoid(ASTNode node) { - node.unregister(); - } - } - - private void setRoot(Root root) { + private void setRoot(Root root, boolean isSubtreeRoot) { if (this.root == root) { return; } if (registered) { - unregister(); + unregister(isSubtreeRoot); } this.root = root; - register(); + register(isSubtreeRoot); } - private void unregister() { - root.unregisterNode(this); + private void unregister(boolean isSubtreeRoot) { + root.unregisterNode(this, isSubtreeRoot); registered = false; } - private void register() { - root.registerNode(this); + private void register(boolean isSubtreeRoot) { + root.registerNode(this, isSubtreeRoot); registered = true; } /** * Sets the parent of this node and handles registration and unregistration of * the subtree with the new parent. - * + * * @param parent The parent value to set, cannot be null. * @return {@code true} if the parent was changed, {@code false} otherwise. */ @@ -310,32 +308,52 @@ public boolean setParent(ASTNode parent, Consumer setter) { return false; } - // if the roots are the same nothing important happens + // if the roots are the same, no change in registration is necessary // this is the normal case for building the AST or moving nodes around if (root == parent.root) { + this.lastParent = this.parent; this.parent = parent; // when the root node of a newly built subtree that already has the same root // references is added to the main tree, only the root node isn't registered yet if (!registered) { - register(); + // this node is the root of a subtree if the parent is already registered + // otherwise its part of a construction process and isn't the root of a subtree + // as nodes are registered from the bottom up + register(parent.registered); } - return true; + } else { + // set the parent to the given parent and re-register the subtree in the new + // root by unregistering and registering in the new root + this.lastParent = this.parent; + this.parent = parent; + changeRootRecursive(parent.root); } - - this.parent = parent; - changeRootRecursive(parent.root); return true; } + private class ChangeRootVisitor extends ASTVoidVisitor { + private Root rootToSet; + + ChangeRootVisitor(Root rootToSet) { + this.rootToSet = rootToSet; + } + + @Override + public void visitVoid(ASTNode node) { + node.setRoot(rootToSet, node == ASTNode.this); + } + }; + private void changeRootRecursive(Root root) { new ChangeRootVisitor(root).visit(this); } /** * Uses the stored replacer function to remove this node from the parent and - * remove the parent from this node. It does not unregister the subtree. - * + * remove the parent from this node. It does not unregister the + * subtree but it does detach it. + * * @param replacement The node to replace this node with * @return {@code true} if the parent was changed, {@code false} otherwise. */ @@ -350,7 +368,7 @@ public boolean replaceBy(ASTNode replacement) { /** * Replaces this node in the parent by the given node and unregisters the * subtree. This fully removes the node from the tree. - * + * * @param replacement The node to replace this node with * @return {@code true} if the parent was changed, {@code false} otherwise. */ @@ -365,7 +383,7 @@ public boolean replaceByAndDelete(ASTNode replacement) { /** * Detaches a node from its parent by using the stored self replacer function * and also removes the parent from this node. Does not unregister the subtree. - * + * * @return {@code true} if the node was removed, {@code false} otherwise. */ public boolean detach() { @@ -375,7 +393,7 @@ public boolean detach() { /** * Removes this node in the parent and unregisters the subtree. - * + * * @return {@code true} if the parent was changed, {@code false} otherwise. */ public boolean detachAndDelete() { @@ -387,25 +405,31 @@ public boolean detachAndDelete() { * been (efficiently) removed from the parent. */ public void detachParent() { + lastParent = parent; parent = null; selfReplacer = null; } + private class UnregisterVisitor extends ASTVoidVisitor { + @Override + public void visitVoid(ASTNode node) { + node.unregister(node == ASTNode.this); + } + }; + /** - * This unregisters this node and all its children from its root. - * - * @return {@code true} if there was unregistering, {@code false} otherwise. + * Detaches the node from the parent, then unregisters this node and all its + * children from its root. */ - public boolean unregisterSubtree() { + public void unregisterSubtree() { detachParent(); new UnregisterVisitor().visit(this); - return true; } /** * Swaps two nodes in their parents. Throws if the nodes or their parents are * null in which case calling this method is pointless. - * + * * @param a The first node to swap * @param b The second node to swap * @return {@code true} if the nodes were swapped, {@code false} otherwise. @@ -430,15 +454,13 @@ public static boolean swap(ASTNode a, ASTNode b) { * Adds a newly constructed node to this node as the parent. The node will * already have a reference to the current root but will not be registered to it * yet. - * + * * @param Type of the node for passthrough * @param node The node to add * @param setter The setter to replace the node in this parent * @return The node itself */ - public N setup( - N node, - Consumer setter) { + public N setup(N node, Consumer setter) { if (node != null) { node.setParent(this, setter); } @@ -449,7 +471,7 @@ public N setup( * Updates the parents of two nodes where one is replacing the other in this * node. Both of them may be null if either the existing value is being removed * or a new value is being set. - * + * * @param The type of the nodes for pass-through * @param currentNode The current node * @param newNode The new node @@ -458,9 +480,7 @@ public N setup( * parent, this node) */ public void updateParents( - N currentNode, - N newNode, - Consumer setter) { + N currentNode, N newNode, Consumer setter) { if (currentNode == newNode && newNode.getParent() == this) { return; } @@ -482,15 +502,7 @@ public void markTemplate(Template template) { protected abstract ASTNode clone(); public ASTNode cloneInto(Root root) { - return Root.indexNodes(root, this::clone); - } - - public ASTNode cloneInto(ASTNode treeMember) { - return Root.indexNodes(treeMember, this::clone); - } - - public ASTNode cloneSeparate() { - return Root.indexNodes(this::clone); + return root.indexNodes(this::clone); } @SuppressWarnings("unchecked") // the nodes clone themselves correctly diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/abstract_node/InnerASTNode.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/abstract_node/InnerASTNode.java index 483450b71d..d0bb54d676 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/abstract_node/InnerASTNode.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/abstract_node/InnerASTNode.java @@ -15,9 +15,4 @@ public abstract class InnerASTNode extends ASTNode { public InnerASTNode cloneInto(Root root) { return (InnerASTNode) super.cloneInto(root); } - - @Override - public InnerASTNode cloneSeparate() { - return (InnerASTNode) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/abstract_node/ListASTNode.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/abstract_node/ListASTNode.java index 483b91fbd4..fd934c4b48 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/abstract_node/ListASTNode.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/abstract_node/ListASTNode.java @@ -1,6 +1,5 @@ package io.github.douira.glsl_transformer.ast.node.abstract_node; -import java.util.List; import java.util.stream.Stream; import io.github.douira.glsl_transformer.ast.data.ChildNodeList; @@ -16,7 +15,7 @@ public ListASTNode(Stream children) { } @Override - public List getChildren() { + public ChildNodeList getChildren() { return children; } @@ -26,12 +25,6 @@ public ListASTNode cloneInto(Root root) { return (ListASTNode) super.cloneInto(root); } - @Override - @SuppressWarnings("unchecked") - public ListASTNode cloneSeparate() { - return (ListASTNode) super.cloneSeparate(); - } - public Stream getClonedChildren() { return children.getClonedStream(); } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/Declaration.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/Declaration.java index cff2f5120b..6cdadc3c7a 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/Declaration.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/Declaration.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.abstract_node.InnerASTNode; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public abstract class Declaration extends InnerASTNode { public enum DeclarationType { @@ -41,9 +42,4 @@ public void exitNode(ASTListener listener) { public Declaration cloneInto(Root root) { return (Declaration) super.cloneInto(root); } - - @Override - public Declaration cloneSeparate() { - return (Declaration) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/DeclarationMember.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/DeclarationMember.java index 1612fb8e5c..419406fdae 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/DeclarationMember.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/DeclarationMember.java @@ -5,7 +5,8 @@ import io.github.douira.glsl_transformer.ast.node.type.initializer.Initializer; import io.github.douira.glsl_transformer.ast.node.type.specifier.ArraySpecifier; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class DeclarationMember extends InnerASTNode { protected Identifier name; @@ -83,9 +84,4 @@ public DeclarationMember clone() { public DeclarationMember cloneInto(Root root) { return (DeclarationMember) super.cloneInto(root); } - - @Override - public DeclarationMember cloneSeparate() { - return (DeclarationMember) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/FunctionDeclaration.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/FunctionDeclaration.java index 55e3656d12..506e63866e 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/FunctionDeclaration.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/FunctionDeclaration.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.type.specifier.FunctionPrototype; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class FunctionDeclaration extends Declaration { protected FunctionPrototype functionPrototype; @@ -51,9 +52,4 @@ public FunctionDeclaration clone() { public FunctionDeclaration cloneInto(Root root) { return (FunctionDeclaration) super.cloneInto(root); } - - @Override - public FunctionDeclaration cloneSeparate() { - return (FunctionDeclaration) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/FunctionParameter.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/FunctionParameter.java index f834c295bc..a6fc235774 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/FunctionParameter.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/FunctionParameter.java @@ -5,7 +5,8 @@ import io.github.douira.glsl_transformer.ast.node.type.FullySpecifiedType; import io.github.douira.glsl_transformer.ast.node.type.specifier.ArraySpecifier; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class FunctionParameter extends InnerASTNode { protected FullySpecifiedType type; @@ -81,9 +82,4 @@ public FunctionParameter clone() { public FunctionParameter cloneInto(Root root) { return (FunctionParameter) super.cloneInto(root); } - - @Override - public FunctionParameter cloneSeparate() { - return (FunctionParameter) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/InterfaceBlockDeclaration.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/InterfaceBlockDeclaration.java index 2f4ba7c551..894e81f976 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/InterfaceBlockDeclaration.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/InterfaceBlockDeclaration.java @@ -123,9 +123,4 @@ public InterfaceBlockDeclaration clone() { public InterfaceBlockDeclaration cloneInto(Root root) { return (InterfaceBlockDeclaration) super.cloneInto(root); } - - @Override - public InterfaceBlockDeclaration cloneSeparate() { - return (InterfaceBlockDeclaration) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/PrecisionDeclaration.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/PrecisionDeclaration.java index 37a498ac8d..a2eb0997cc 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/PrecisionDeclaration.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/PrecisionDeclaration.java @@ -65,9 +65,4 @@ public PrecisionDeclaration clone() { public PrecisionDeclaration cloneInto(Root root) { return (PrecisionDeclaration) super.cloneInto(root); } - - @Override - public PrecisionDeclaration cloneSeparate() { - return (PrecisionDeclaration) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/TypeAndInitDeclaration.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/TypeAndInitDeclaration.java index 31648ff47c..75e97918a2 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/TypeAndInitDeclaration.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/TypeAndInitDeclaration.java @@ -1,6 +1,5 @@ package io.github.douira.glsl_transformer.ast.node.declaration; -import java.util.List; import java.util.stream.Stream; import io.github.douira.glsl_transformer.ast.data.ChildNodeList; @@ -31,7 +30,7 @@ public void setType(FullySpecifiedType type) { this.type = type; } - public List getMembers() { + public ChildNodeList getMembers() { return members; } @@ -66,9 +65,4 @@ public TypeAndInitDeclaration clone() { public TypeAndInitDeclaration cloneInto(Root root) { return (TypeAndInitDeclaration) super.cloneInto(root); } - - @Override - public TypeAndInitDeclaration cloneSeparate() { - return (TypeAndInitDeclaration) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/VariableDeclaration.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/VariableDeclaration.java index 9867510eb9..d4f877d024 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/VariableDeclaration.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/declaration/VariableDeclaration.java @@ -1,6 +1,5 @@ package io.github.douira.glsl_transformer.ast.node.declaration; -import java.util.List; import java.util.stream.Stream; import io.github.douira.glsl_transformer.ast.data.ChildNodeList; @@ -31,7 +30,7 @@ public void setTypeQualifier(TypeQualifier typeQualifier) { this.typeQualifier = typeQualifier; } - public List getNames() { + public ChildNodeList getNames() { return names; } @@ -66,9 +65,4 @@ public VariableDeclaration clone() { public VariableDeclaration cloneInto(Root root) { return (VariableDeclaration) super.cloneInto(root); } - - @Override - public VariableDeclaration cloneSeparate() { - return (VariableDeclaration) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/ConditionExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/ConditionExpression.java index c4749161f7..0dce454505 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/ConditionExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/ConditionExpression.java @@ -1,7 +1,8 @@ package io.github.douira.glsl_transformer.ast.node.expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class ConditionExpression extends TernaryExpression { public ConditionExpression(Expression condition, Expression trueExpression, Expression falseExpression) { @@ -51,9 +52,4 @@ public ConditionExpression clone() { public ConditionExpression cloneInto(Root root) { return (ConditionExpression) super.cloneInto(root); } - - @Override - public ConditionExpression cloneSeparate() { - return (ConditionExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/Expression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/Expression.java index bc2e2f060b..8499717911 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/Expression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/Expression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.abstract_node.InnerASTNode; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public abstract class Expression extends InnerASTNode { public enum ExpressionType { @@ -115,9 +116,4 @@ public void exitNode(ASTListener listener) { public Expression cloneInto(Root root) { return (Expression) super.cloneInto(root); } - - @Override - public Expression cloneSeparate() { - return (Expression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/LiteralExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/LiteralExpression.java index b5a19e9cfd..5ea9375c32 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/LiteralExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/LiteralExpression.java @@ -285,9 +285,4 @@ public LiteralExpression clone() { public LiteralExpression cloneInto(Root root) { return (LiteralExpression) super.cloneInto(root); } - - @Override - public LiteralExpression cloneSeparate() { - return (LiteralExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/ManyExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/ManyExpression.java index cf24f3931a..4d1914d1e0 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/ManyExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/ManyExpression.java @@ -1,6 +1,5 @@ package io.github.douira.glsl_transformer.ast.node.expression; -import java.util.List; import java.util.stream.Stream; import io.github.douira.glsl_transformer.ast.data.ChildNodeList; @@ -16,11 +15,11 @@ public ManyExpression(Stream expressions) { } @Override - public List getChildren() { + public ChildNodeList getChildren() { return expressions; } - public List getExpressions() { + public ChildNodeList getExpressions() { return expressions; } @@ -51,9 +50,4 @@ public void exitNode(ASTListener listener) { public ManyExpression cloneInto(Root root) { return (ManyExpression) super.cloneInto(root); } - - @Override - public ManyExpression cloneSeparate() { - return (ManyExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/ReferenceExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/ReferenceExpression.java index 12c48e85a6..6025b0ce63 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/ReferenceExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/ReferenceExpression.java @@ -51,9 +51,4 @@ public ReferenceExpression clone() { public ReferenceExpression cloneInto(Root root) { return (ReferenceExpression) super.cloneInto(root); } - - @Override - public ReferenceExpression cloneSeparate() { - return (ReferenceExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/SequenceExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/SequenceExpression.java index 35aa7e616e..7b5af5c04f 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/SequenceExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/SequenceExpression.java @@ -41,9 +41,4 @@ public SequenceExpression clone() { public SequenceExpression cloneInto(Root root) { return (SequenceExpression) super.cloneInto(root); } - - @Override - public SequenceExpression cloneSeparate() { - return (SequenceExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/TerminalExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/TerminalExpression.java index aa74e25c0a..8902496fd4 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/TerminalExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/TerminalExpression.java @@ -31,9 +31,4 @@ public void exitNode(ASTListener listener) { public TerminalExpression cloneInto(Root root) { return (TerminalExpression) super.cloneInto(root); } - - @Override - public TerminalExpression cloneSeparate() { - return (TerminalExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/TernaryExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/TernaryExpression.java index e2a56f158c..98a2932bf5 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/TernaryExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/TernaryExpression.java @@ -68,9 +68,4 @@ public void exitNode(ASTListener listener) { public TernaryExpression cloneInto(Root root) { return (TernaryExpression) super.cloneInto(root); } - - @Override - public TernaryExpression cloneSeparate() { - return (TernaryExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/AdditionAssignmentExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/AdditionAssignmentExpression.java index c0f216f5e4..50e8494969 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/AdditionAssignmentExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/AdditionAssignmentExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class AdditionAssignmentExpression extends BinaryExpression { public AdditionAssignmentExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public AdditionAssignmentExpression clone() { public AdditionAssignmentExpression cloneInto(Root root) { return (AdditionAssignmentExpression) super.cloneInto(root); } - - @Override - public AdditionAssignmentExpression cloneSeparate() { - return (AdditionAssignmentExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/AdditionExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/AdditionExpression.java index 4a7eaa208d..9213b0cba9 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/AdditionExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/AdditionExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class AdditionExpression extends BinaryExpression { public AdditionExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public AdditionExpression clone() { public AdditionExpression cloneInto(Root root) { return (AdditionExpression) super.cloneInto(root); } - - @Override - public AdditionExpression cloneSeparate() { - return (AdditionExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/ArrayAccessExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/ArrayAccessExpression.java index 0c25923cbb..bafa7d9c98 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/ArrayAccessExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/ArrayAccessExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class ArrayAccessExpression extends BinaryExpression { public ArrayAccessExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public ArrayAccessExpression clone() { public ArrayAccessExpression cloneInto(Root root) { return (ArrayAccessExpression) super.cloneInto(root); } - - @Override - public ArrayAccessExpression cloneSeparate() { - return (ArrayAccessExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/AssignmentExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/AssignmentExpression.java index 46d77fdae7..feb49be802 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/AssignmentExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/AssignmentExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class AssignmentExpression extends BinaryExpression { public AssignmentExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public AssignmentExpression clone() { public AssignmentExpression cloneInto(Root root) { return (AssignmentExpression) super.cloneInto(root); } - - @Override - public AssignmentExpression cloneSeparate() { - return (AssignmentExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BinaryExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BinaryExpression.java index fca846093c..09d40b0848 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BinaryExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BinaryExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public abstract class BinaryExpression extends Expression { protected Expression left; @@ -58,9 +59,4 @@ public void exitNode(ASTListener listener) { public BinaryExpression cloneInto(Root root) { return (BinaryExpression) super.cloneInto(root); } - - @Override - public BinaryExpression cloneSeparate() { - return (BinaryExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseAndAssignmentExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseAndAssignmentExpression.java index b3b3d5e116..3f8e52df60 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseAndAssignmentExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseAndAssignmentExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class BitwiseAndAssignmentExpression extends BinaryExpression { public BitwiseAndAssignmentExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public BitwiseAndAssignmentExpression clone() { public BitwiseAndAssignmentExpression cloneInto(Root root) { return (BitwiseAndAssignmentExpression) super.cloneInto(root); } - - @Override - public BitwiseAndAssignmentExpression cloneSeparate() { - return (BitwiseAndAssignmentExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseAndExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseAndExpression.java index c93fea3c3d..a14a042319 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseAndExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseAndExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class BitwiseAndExpression extends BinaryExpression { public BitwiseAndExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public BitwiseAndExpression clone() { public BitwiseAndExpression cloneInto(Root root) { return (BitwiseAndExpression) super.cloneInto(root); } - - @Override - public BitwiseAndExpression cloneSeparate() { - return (BitwiseAndExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseOrAssignmentExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseOrAssignmentExpression.java index b7d47e5ad6..7f66ac2416 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseOrAssignmentExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseOrAssignmentExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class BitwiseOrAssignmentExpression extends BinaryExpression { public BitwiseOrAssignmentExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public BitwiseOrAssignmentExpression clone() { public BitwiseOrAssignmentExpression cloneInto(Root root) { return (BitwiseOrAssignmentExpression) super.cloneInto(root); } - - @Override - public BitwiseOrAssignmentExpression cloneSeparate() { - return (BitwiseOrAssignmentExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseOrExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseOrExpression.java index 6273c6e496..b9ba5f8af3 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseOrExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseOrExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class BitwiseOrExpression extends BinaryExpression { public BitwiseOrExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public BitwiseOrExpression clone() { public BitwiseOrExpression cloneInto(Root root) { return (BitwiseOrExpression) super.cloneInto(root); } - - @Override - public BitwiseOrExpression cloneSeparate() { - return (BitwiseOrExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseXorAssignmentExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseXorAssignmentExpression.java index 65fbfd1be7..e5c90a57fa 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseXorAssignmentExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseXorAssignmentExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class BitwiseXorAssignmentExpression extends BinaryExpression { public BitwiseXorAssignmentExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public BitwiseXorAssignmentExpression clone() { public BitwiseXorAssignmentExpression cloneInto(Root root) { return (BitwiseXorAssignmentExpression) super.cloneInto(root); } - - @Override - public BitwiseXorAssignmentExpression cloneSeparate() { - return (BitwiseXorAssignmentExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseXorExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseXorExpression.java index 2040bb0930..a1eecd13aa 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseXorExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BitwiseXorExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class BitwiseXorExpression extends BinaryExpression { public BitwiseXorExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public BitwiseXorExpression clone() { public BitwiseXorExpression cloneInto(Root root) { return (BitwiseXorExpression) super.cloneInto(root); } - - @Override - public BitwiseXorExpression cloneSeparate() { - return (BitwiseXorExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BooleanAndExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BooleanAndExpression.java index 01f4d0a0b5..e11fa8b167 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BooleanAndExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BooleanAndExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class BooleanAndExpression extends BinaryExpression { public BooleanAndExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public BooleanAndExpression clone() { public BooleanAndExpression cloneInto(Root root) { return (BooleanAndExpression) super.cloneInto(root); } - - @Override - public BooleanAndExpression cloneSeparate() { - return (BooleanAndExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BooleanOrExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BooleanOrExpression.java index d36530c104..00e0b918e6 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BooleanOrExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BooleanOrExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class BooleanOrExpression extends BinaryExpression { public BooleanOrExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public BooleanOrExpression clone() { public BooleanOrExpression cloneInto(Root root) { return (BooleanOrExpression) super.cloneInto(root); } - - @Override - public BooleanOrExpression cloneSeparate() { - return (BooleanOrExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BooleanXorExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BooleanXorExpression.java index 59790e78f4..7cc6f2380f 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BooleanXorExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/BooleanXorExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class BooleanXorExpression extends BinaryExpression { public BooleanXorExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public BooleanXorExpression clone() { public BooleanXorExpression cloneInto(Root root) { return (BooleanXorExpression) super.cloneInto(root); } - - @Override - public BooleanXorExpression cloneSeparate() { - return (BooleanXorExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/DivisionAssignmentExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/DivisionAssignmentExpression.java index 64c4009b82..1dce9a5972 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/DivisionAssignmentExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/DivisionAssignmentExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class DivisionAssignmentExpression extends BinaryExpression { public DivisionAssignmentExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public DivisionAssignmentExpression clone() { public DivisionAssignmentExpression cloneInto(Root root) { return (DivisionAssignmentExpression) super.cloneInto(root); } - - @Override - public DivisionAssignmentExpression cloneSeparate() { - return (DivisionAssignmentExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/DivisionExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/DivisionExpression.java index a2e3cfe8d4..cd8e745c88 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/DivisionExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/DivisionExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class DivisionExpression extends BinaryExpression { public DivisionExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public DivisionExpression clone() { public DivisionExpression cloneInto(Root root) { return (DivisionExpression) super.cloneInto(root); } - - @Override - public DivisionExpression cloneSeparate() { - return (DivisionExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/EqualityExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/EqualityExpression.java index ec0f9c9d79..5226a531cc 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/EqualityExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/EqualityExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class EqualityExpression extends BinaryExpression { public EqualityExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public EqualityExpression clone() { public EqualityExpression cloneInto(Root root) { return (EqualityExpression) super.cloneInto(root); } - - @Override - public EqualityExpression cloneSeparate() { - return (EqualityExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/GreaterThanEqualExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/GreaterThanEqualExpression.java index be55e30fd4..bb09a72f1c 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/GreaterThanEqualExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/GreaterThanEqualExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class GreaterThanEqualExpression extends BinaryExpression { public GreaterThanEqualExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public GreaterThanEqualExpression clone() { public GreaterThanEqualExpression cloneInto(Root root) { return (GreaterThanEqualExpression) super.cloneInto(root); } - - @Override - public GreaterThanEqualExpression cloneSeparate() { - return (GreaterThanEqualExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/GreaterThanExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/GreaterThanExpression.java index 9ee371fb66..835b84bb47 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/GreaterThanExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/GreaterThanExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class GreaterThanExpression extends BinaryExpression { public GreaterThanExpression(Expression left, Expression right) { @@ -40,9 +41,4 @@ public GreaterThanExpression clone() { public GreaterThanExpression cloneInto(Root root) { return (GreaterThanExpression) super.cloneInto(root); } - - @Override - public GreaterThanExpression cloneSeparate() { - return (GreaterThanExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/InequalityExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/InequalityExpression.java index f7c5a2fffa..395dd8fdb7 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/InequalityExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/InequalityExpression.java @@ -40,9 +40,4 @@ public InequalityExpression clone() { public InequalityExpression cloneInto(Root root) { return (InequalityExpression) super.cloneInto(root); } - - @Override - public InequalityExpression cloneSeparate() { - return (InequalityExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LeftShiftAssignmentExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LeftShiftAssignmentExpression.java index 7f29b0c0d5..8e712a55d8 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LeftShiftAssignmentExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LeftShiftAssignmentExpression.java @@ -40,9 +40,4 @@ public LeftShiftAssignmentExpression clone() { public LeftShiftAssignmentExpression cloneInto(Root root) { return (LeftShiftAssignmentExpression) super.cloneInto(root); } - - @Override - public LeftShiftAssignmentExpression cloneSeparate() { - return (LeftShiftAssignmentExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LeftShiftExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LeftShiftExpression.java index 4f41db6e20..b799bb93e7 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LeftShiftExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LeftShiftExpression.java @@ -40,9 +40,4 @@ public LeftShiftExpression clone() { public LeftShiftExpression cloneInto(Root root) { return (LeftShiftExpression) super.cloneInto(root); } - - @Override - public LeftShiftExpression cloneSeparate() { - return (LeftShiftExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LessThanEqualExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LessThanEqualExpression.java index 025deec418..68038ca815 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LessThanEqualExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LessThanEqualExpression.java @@ -40,9 +40,4 @@ public LessThanEqualExpression clone() { public LessThanEqualExpression cloneInto(Root root) { return (LessThanEqualExpression) super.cloneInto(root); } - - @Override - public LessThanEqualExpression cloneSeparate() { - return (LessThanEqualExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LessThanExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LessThanExpression.java index 0ca74a4f02..f798430d30 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LessThanExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/LessThanExpression.java @@ -40,9 +40,4 @@ public LessThanExpression clone() { public LessThanExpression cloneInto(Root root) { return (LessThanExpression) super.cloneInto(root); } - - @Override - public LessThanExpression cloneSeparate() { - return (LessThanExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/ModuloAssignmentExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/ModuloAssignmentExpression.java index 14a06739dd..d7f4338bff 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/ModuloAssignmentExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/ModuloAssignmentExpression.java @@ -40,9 +40,4 @@ public ModuloAssignmentExpression clone() { public ModuloAssignmentExpression cloneInto(Root root) { return (ModuloAssignmentExpression) super.cloneInto(root); } - - @Override - public ModuloAssignmentExpression cloneSeparate() { - return (ModuloAssignmentExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/ModuloExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/ModuloExpression.java index 55be79afa9..e68df6d59e 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/ModuloExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/ModuloExpression.java @@ -40,9 +40,4 @@ public ModuloExpression clone() { public ModuloExpression cloneInto(Root root) { return (ModuloExpression) super.cloneInto(root); } - - @Override - public ModuloExpression cloneSeparate() { - return (ModuloExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/MultiplicationAssignmentExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/MultiplicationAssignmentExpression.java index 304c8a4b16..8371a87141 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/MultiplicationAssignmentExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/MultiplicationAssignmentExpression.java @@ -40,9 +40,4 @@ public MultiplicationAssignmentExpression clone() { public MultiplicationAssignmentExpression cloneInto(Root root) { return (MultiplicationAssignmentExpression) super.cloneInto(root); } - - @Override - public MultiplicationAssignmentExpression cloneSeparate() { - return (MultiplicationAssignmentExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/MultiplicationExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/MultiplicationExpression.java index 03a7b77797..c539261f9a 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/MultiplicationExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/MultiplicationExpression.java @@ -40,9 +40,4 @@ public MultiplicationExpression clone() { public MultiplicationExpression cloneInto(Root root) { return (MultiplicationExpression) super.cloneInto(root); } - - @Override - public MultiplicationExpression cloneSeparate() { - return (MultiplicationExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/RightShiftAssignmentExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/RightShiftAssignmentExpression.java index dfa2cffcbd..096a0557c8 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/RightShiftAssignmentExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/RightShiftAssignmentExpression.java @@ -40,9 +40,4 @@ public RightShiftAssignmentExpression clone() { public RightShiftAssignmentExpression cloneInto(Root root) { return (RightShiftAssignmentExpression) super.cloneInto(root); } - - @Override - public RightShiftAssignmentExpression cloneSeparate() { - return (RightShiftAssignmentExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/RightShiftExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/RightShiftExpression.java index ffeca941fa..aa08ef3913 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/RightShiftExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/RightShiftExpression.java @@ -40,9 +40,4 @@ public RightShiftExpression clone() { public RightShiftExpression cloneInto(Root root) { return (RightShiftExpression) super.cloneInto(root); } - - @Override - public RightShiftExpression cloneSeparate() { - return (RightShiftExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/SubtractionAssignmentExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/SubtractionAssignmentExpression.java index c420c79671..38d52b5015 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/SubtractionAssignmentExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/SubtractionAssignmentExpression.java @@ -40,9 +40,4 @@ public SubtractionAssignmentExpression clone() { public SubtractionAssignmentExpression cloneInto(Root root) { return (SubtractionAssignmentExpression) super.cloneInto(root); } - - @Override - public SubtractionAssignmentExpression cloneSeparate() { - return (SubtractionAssignmentExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/SubtractionExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/SubtractionExpression.java index ae5f2f3008..fd6d9cd75e 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/SubtractionExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/binary/SubtractionExpression.java @@ -40,9 +40,4 @@ public SubtractionExpression clone() { public SubtractionExpression cloneInto(Root root) { return (SubtractionExpression) super.cloneInto(root); } - - @Override - public SubtractionExpression cloneSeparate() { - return (SubtractionExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/BitwiseNotExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/BitwiseNotExpression.java index 2b9ba3a2fe..ec42ea1007 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/BitwiseNotExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/BitwiseNotExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class BitwiseNotExpression extends UnaryExpression { public BitwiseNotExpression(Expression expression) { @@ -40,9 +41,4 @@ public BitwiseNotExpression clone() { public BitwiseNotExpression cloneInto(Root root) { return (BitwiseNotExpression) super.cloneInto(root); } - - @Override - public BitwiseNotExpression cloneSeparate() { - return (BitwiseNotExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/BooleanNotExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/BooleanNotExpression.java index aeaae14588..ef0bd7a7f3 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/BooleanNotExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/BooleanNotExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class BooleanNotExpression extends UnaryExpression { public BooleanNotExpression(Expression expression) { @@ -40,9 +41,4 @@ public BooleanNotExpression clone() { public BooleanNotExpression cloneInto(Root root) { return (BooleanNotExpression) super.cloneInto(root); } - - @Override - public BooleanNotExpression cloneSeparate() { - return (BooleanNotExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/DecrementPostfixExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/DecrementPostfixExpression.java index 6e5169f6d4..9aa5b8aced 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/DecrementPostfixExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/DecrementPostfixExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class DecrementPostfixExpression extends UnaryExpression { public DecrementPostfixExpression(Expression expression) { @@ -40,9 +41,4 @@ public DecrementPostfixExpression clone() { public DecrementPostfixExpression cloneInto(Root root) { return (DecrementPostfixExpression) super.cloneInto(root); } - - @Override - public DecrementPostfixExpression cloneSeparate() { - return (DecrementPostfixExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/DecrementPrefixExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/DecrementPrefixExpression.java index c37b3af048..8a76aeb323 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/DecrementPrefixExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/DecrementPrefixExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class DecrementPrefixExpression extends UnaryExpression { public DecrementPrefixExpression(Expression expression) { @@ -40,9 +41,4 @@ public DecrementPrefixExpression clone() { public DecrementPrefixExpression cloneInto(Root root) { return (DecrementPrefixExpression) super.cloneInto(root); } - - @Override - public DecrementPrefixExpression cloneSeparate() { - return (DecrementPrefixExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/FunctionCallExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/FunctionCallExpression.java index 1d393e38ab..010b3abfac 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/FunctionCallExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/FunctionCallExpression.java @@ -1,15 +1,16 @@ package io.github.douira.glsl_transformer.ast.node.expression.unary; -import java.util.List; -import java.util.stream.Stream; - import io.github.douira.glsl_transformer.ast.data.ChildNodeList; import io.github.douira.glsl_transformer.ast.node.Identifier; import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; -import io.github.douira.glsl_transformer.ast.node.expression.*; +import io.github.douira.glsl_transformer.ast.node.expression.Expression; +import io.github.douira.glsl_transformer.ast.node.expression.TerminalExpression; import io.github.douira.glsl_transformer.ast.node.type.specifier.TypeSpecifier; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; + +import java.util.stream.Stream; public class FunctionCallExpression extends TerminalExpression { public enum FunctionReferenceType { @@ -97,7 +98,7 @@ public ASTNode getReference() { return referenceType == FunctionReferenceType.NAME ? functionName : functionSpecifier; } - public List getParameters() { + public ChildNodeList getParameters() { return parameters; } @@ -132,9 +133,4 @@ public FunctionCallExpression clone() { public FunctionCallExpression cloneInto(Root root) { return (FunctionCallExpression) super.cloneInto(root); } - - @Override - public FunctionCallExpression cloneSeparate() { - return (FunctionCallExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/GroupingExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/GroupingExpression.java index 2d87718eac..ddf9729ae7 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/GroupingExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/GroupingExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class GroupingExpression extends UnaryExpression { public GroupingExpression(Expression expression) { @@ -40,9 +41,4 @@ public GroupingExpression clone() { public GroupingExpression cloneInto(Root root) { return (GroupingExpression) super.cloneInto(root); } - - @Override - public GroupingExpression cloneSeparate() { - return (GroupingExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/IdentityExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/IdentityExpression.java index 0a7d6b385b..97fc306bda 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/IdentityExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/IdentityExpression.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class IdentityExpression extends UnaryExpression { public IdentityExpression(Expression expression) { @@ -40,9 +41,4 @@ public IdentityExpression clone() { public IdentityExpression cloneInto(Root root) { return (IdentityExpression) super.cloneInto(root); } - - @Override - public IdentityExpression cloneSeparate() { - return (IdentityExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/IncrementPostfixExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/IncrementPostfixExpression.java index ac4b3c55a6..3aaf4d1906 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/IncrementPostfixExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/IncrementPostfixExpression.java @@ -40,9 +40,4 @@ public IncrementPostfixExpression clone() { public IncrementPostfixExpression cloneInto(Root root) { return (IncrementPostfixExpression) super.cloneInto(root); } - - @Override - public IncrementPostfixExpression cloneSeparate() { - return (IncrementPostfixExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/IncrementPrefixExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/IncrementPrefixExpression.java index f93eec0cd4..7854697c0f 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/IncrementPrefixExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/IncrementPrefixExpression.java @@ -40,9 +40,4 @@ public IncrementPrefixExpression clone() { public IncrementPrefixExpression cloneInto(Root root) { return (IncrementPrefixExpression) super.cloneInto(root); } - - @Override - public IncrementPrefixExpression cloneSeparate() { - return (IncrementPrefixExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/LengthAccessExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/LengthAccessExpression.java index edf73ce366..3fa983ab5a 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/LengthAccessExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/LengthAccessExpression.java @@ -40,9 +40,4 @@ public LengthAccessExpression clone() { public LengthAccessExpression cloneInto(Root root) { return (LengthAccessExpression) super.cloneInto(root); } - - @Override - public LengthAccessExpression cloneSeparate() { - return (LengthAccessExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/MemberAccessExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/MemberAccessExpression.java index 2f2882cb0d..77b3cd6983 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/MemberAccessExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/MemberAccessExpression.java @@ -53,9 +53,4 @@ public MemberAccessExpression clone() { public MemberAccessExpression cloneInto(Root root) { return (MemberAccessExpression) super.cloneInto(root); } - - @Override - public MemberAccessExpression cloneSeparate() { - return (MemberAccessExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/NegationExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/NegationExpression.java index be67452ac6..eea067e3e1 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/NegationExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/NegationExpression.java @@ -40,9 +40,4 @@ public NegationExpression clone() { public NegationExpression cloneInto(Root root) { return (NegationExpression) super.cloneInto(root); } - - @Override - public NegationExpression cloneSeparate() { - return (NegationExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/UnaryExpression.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/UnaryExpression.java index a8621c558f..152dd30438 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/UnaryExpression.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/expression/unary/UnaryExpression.java @@ -47,9 +47,4 @@ public void exitNode(ASTListener listener) { public UnaryExpression cloneInto(Root root) { return (UnaryExpression) super.cloneInto(root); } - - @Override - public UnaryExpression cloneSeparate() { - return (UnaryExpression) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/CustomDirective.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/CustomDirective.java index b7aa41f354..5d877303d6 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/CustomDirective.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/CustomDirective.java @@ -1,18 +1,29 @@ package io.github.douira.glsl_transformer.ast.node.external_declaration; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class CustomDirective extends ExternalDeclaration { - public String content; + private String content; public CustomDirective(String content) { this.content = content; } + public String getContent() { + return content; + } + + public void setContent(String content) { + getRoot().unregisterFastRename(this); + this.content = content; + getRoot().registerFastRename(this); + } + @Override public ExternalDeclarationType getExternalDeclarationType() { - return ExternalDeclarationType.CUSTOM_DIRECTIVE_STATEMENT; + return ExternalDeclarationType.CUSTOM_DIRECTIVE; } @Override @@ -41,9 +52,4 @@ public CustomDirective clone() { public CustomDirective cloneInto(Root root) { return (CustomDirective) super.cloneInto(root); } - - @Override - public CustomDirective cloneSeparate() { - return (CustomDirective) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/DeclarationExternalDeclaration.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/DeclarationExternalDeclaration.java index 6e26c28489..146dd397d4 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/DeclarationExternalDeclaration.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/DeclarationExternalDeclaration.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.declaration.Declaration; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class DeclarationExternalDeclaration extends ExternalDeclaration { protected Declaration declaration; @@ -51,9 +52,4 @@ public DeclarationExternalDeclaration clone() { public DeclarationExternalDeclaration cloneInto(Root root) { return (DeclarationExternalDeclaration) super.cloneInto(root); } - - @Override - public DeclarationExternalDeclaration cloneSeparate() { - return (DeclarationExternalDeclaration) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/EmptyDeclaration.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/EmptyDeclaration.java index 6dc9f49a95..b7a836c29f 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/EmptyDeclaration.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/EmptyDeclaration.java @@ -1,7 +1,8 @@ package io.github.douira.glsl_transformer.ast.node.external_declaration; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class EmptyDeclaration extends ExternalDeclaration { @Override @@ -35,9 +36,4 @@ public EmptyDeclaration clone() { public EmptyDeclaration cloneInto(Root root) { return (EmptyDeclaration) super.cloneInto(root); } - - @Override - public EmptyDeclaration cloneSeparate() { - return (EmptyDeclaration) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/ExtensionDirective.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/ExtensionDirective.java index 04b9531a16..011165d834 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/ExtensionDirective.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/ExtensionDirective.java @@ -1,11 +1,12 @@ package io.github.douira.glsl_transformer.ast.node.external_declaration; -import repack.antlr.v4.runtime.Token; - import io.github.douira.glsl_transformer.GLSLLexer; -import io.github.douira.glsl_transformer.ast.data.*; +import io.github.douira.glsl_transformer.ast.data.TokenTyped; +import io.github.douira.glsl_transformer.ast.data.TypeUtil; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; +import repack.antlr.v4.runtime.Token; public class ExtensionDirective extends ExternalDeclaration { public enum ExtensionBehavior implements TokenTyped { @@ -30,7 +31,7 @@ public static ExtensionBehavior fromToken(Token token) { } } - public String name; + private String name; public ExtensionBehavior behavior; // TODO: nullable public ExtensionDirective(String name, ExtensionBehavior behavior) { @@ -42,9 +43,19 @@ public ExtensionDirective(String name) { this.name = name; } + public String getName() { + return name; + } + + public void setName(String name) { + getRoot().unregisterFastRename(this); + this.name = name; + getRoot().registerFastRename(this); + } + @Override public ExternalDeclarationType getExternalDeclarationType() { - return ExternalDeclarationType.EXTENSION_STATEMENT; + return ExternalDeclarationType.EXTENSION_DIRECTIVE; } @Override @@ -73,9 +84,4 @@ public ExtensionDirective clone() { public ExtensionDirective cloneInto(Root root) { return (ExtensionDirective) super.cloneInto(root); } - - @Override - public ExtensionDirective cloneSeparate() { - return (ExtensionDirective) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/ExternalDeclaration.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/ExternalDeclaration.java index e969376e11..75861c76f3 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/ExternalDeclaration.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/ExternalDeclaration.java @@ -3,7 +3,8 @@ import io.github.douira.glsl_transformer.ast.node.abstract_node.InnerASTNode; import io.github.douira.glsl_transformer.ast.query.Root; import io.github.douira.glsl_transformer.ast.transform.ASTBuilder; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public abstract class ExternalDeclaration extends InnerASTNode { public ExternalDeclaration() { @@ -13,10 +14,10 @@ public ExternalDeclaration() { public enum ExternalDeclarationType { FUNCTION_DEFINITION, DECLARATION, - PRAGMA_STATEMENT, - EXTENSION_STATEMENT, - CUSTOM_DIRECTIVE_STATEMENT, - INCLUDE_STATEMENT, + PRAGMA_DIRECTIVE, + EXTENSION_DIRECTIVE, + CUSTOM_DIRECTIVE, + INCLUDE_DIRECTIVE, LAYOUT_DEFAULTS, EMPTY_DECLARATION } @@ -49,9 +50,4 @@ public void exitNode(ASTListener listener) { public ExternalDeclaration cloneInto(Root root) { return (ExternalDeclaration) super.cloneInto(root); } - - @Override - public ExternalDeclaration cloneSeparate() { - return (ExternalDeclaration) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/FunctionDefinition.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/FunctionDefinition.java index 9c3c29fa09..6fff0b4c41 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/FunctionDefinition.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/FunctionDefinition.java @@ -3,7 +3,8 @@ import io.github.douira.glsl_transformer.ast.node.statement.CompoundStatement; import io.github.douira.glsl_transformer.ast.node.type.specifier.FunctionPrototype; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class FunctionDefinition extends ExternalDeclaration { protected FunctionPrototype functionPrototype; @@ -63,9 +64,4 @@ public FunctionDefinition clone() { public FunctionDefinition cloneInto(Root root) { return (FunctionDefinition) super.cloneInto(root); } - - @Override - public FunctionDefinition cloneSeparate() { - return (FunctionDefinition) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/IncludeDirective.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/IncludeDirective.java index 8d99f19ab9..fe97a0633a 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/IncludeDirective.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/IncludeDirective.java @@ -4,7 +4,7 @@ import io.github.douira.glsl_transformer.ast.traversal.*; public class IncludeDirective extends ExternalDeclaration { - public String content; + private String content; public boolean isAngleBrackets; public IncludeDirective(String content, boolean isAngleBrackets) { @@ -16,9 +16,19 @@ public IncludeDirective(String content) { this(content, false); } + public String getContent() { + return content; + } + + public void setContent(String content) { + getRoot().unregisterFastRename(this); + this.content = content; + getRoot().registerFastRename(this); + } + @Override public ExternalDeclarationType getExternalDeclarationType() { - return ExternalDeclarationType.INCLUDE_STATEMENT; + return ExternalDeclarationType.INCLUDE_DIRECTIVE; } @Override @@ -47,9 +57,4 @@ public IncludeDirective clone() { public IncludeDirective cloneInto(Root root) { return (IncludeDirective) super.cloneInto(root); } - - @Override - public IncludeDirective cloneSeparate() { - return (IncludeDirective) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/LayoutDefaults.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/LayoutDefaults.java index 2da0aba765..c940f1caa9 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/LayoutDefaults.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/LayoutDefaults.java @@ -79,9 +79,4 @@ public LayoutDefaults clone() { public LayoutDefaults cloneInto(Root root) { return (LayoutDefaults) super.cloneInto(root); } - - @Override - public LayoutDefaults cloneSeparate() { - return (LayoutDefaults) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/PragmaDirective.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/PragmaDirective.java index 25602effdd..702c85835c 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/PragmaDirective.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/external_declaration/PragmaDirective.java @@ -53,7 +53,7 @@ public static PragmaState fromToken(Token token) { public boolean stdGL; public PragmaType type; - public String customName; + private String customName; public PragmaState state; private PragmaDirective(boolean stdGL, PragmaType type, String customName, PragmaState state) { @@ -75,9 +75,19 @@ public PragmaDirective(boolean stdGL, PragmaType type, PragmaState state) { this.state = state; } + public String getCustomName() { + return customName; + } + + public void setCustomName(String customName) { + // since pragma directives aren't indexed by the external declaration index, no + // registering is needed + this.customName = customName; + } + @Override public ExternalDeclarationType getExternalDeclarationType() { - return ExternalDeclarationType.PRAGMA_STATEMENT; + return ExternalDeclarationType.PRAGMA_DIRECTIVE; } @Override @@ -106,9 +116,4 @@ public PragmaDirective clone() { public PragmaDirective cloneInto(Root root) { return (PragmaDirective) super.cloneInto(root); } - - @Override - public PragmaDirective cloneSeparate() { - return (PragmaDirective) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/CompoundStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/CompoundStatement.java index fe3eb57cd9..c8f2bbbf37 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/CompoundStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/CompoundStatement.java @@ -1,9 +1,10 @@ package io.github.douira.glsl_transformer.ast.node.statement; -import java.util.stream.Stream; - import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; + +import java.util.stream.Stream; public class CompoundStatement extends ManyStatement { public CompoundStatement(Stream statements) { @@ -41,9 +42,4 @@ public CompoundStatement clone() { public CompoundStatement cloneInto(Root root) { return (CompoundStatement) super.cloneInto(root); } - - @Override - public CompoundStatement cloneSeparate() { - return (CompoundStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/ManyStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/ManyStatement.java index 1e3b45355a..6eeed75ced 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/ManyStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/ManyStatement.java @@ -1,6 +1,5 @@ package io.github.douira.glsl_transformer.ast.node.statement; -import java.util.List; import java.util.stream.Stream; import io.github.douira.glsl_transformer.ast.data.ChildNodeList; @@ -16,11 +15,11 @@ public ManyStatement(Stream statements) { } @Override - public List getChildren() { + public ChildNodeList getChildren() { return statements; } - public List getStatements() { + public ChildNodeList getStatements() { return statements; } @@ -51,9 +50,4 @@ public void exitNode(ASTListener listener) { public ManyStatement cloneInto(Root root) { return (ManyStatement) super.cloneInto(root); } - - @Override - public ManyStatement cloneSeparate() { - return (ManyStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/Statement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/Statement.java index 22f5b6f9d4..52df128ded 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/Statement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/Statement.java @@ -70,9 +70,4 @@ public void exitNode(ASTListener listener) { public Statement cloneInto(Root root) { return (Statement) super.cloneInto(root); } - - @Override - public Statement cloneSeparate() { - return (Statement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/ConditionLoopStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/ConditionLoopStatement.java index e3154a5a2a..5ffa46bbb7 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/ConditionLoopStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/ConditionLoopStatement.java @@ -28,9 +28,4 @@ public void setCondition(Expression condition) { public ConditionLoopStatement cloneInto(Root root) { return (ConditionLoopStatement) super.cloneInto(root); } - - @Override - public ConditionLoopStatement cloneSeparate() { - return (ConditionLoopStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/DoWhileLoopStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/DoWhileLoopStatement.java index 665da3221d..c0c3ff665d 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/DoWhileLoopStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/DoWhileLoopStatement.java @@ -3,7 +3,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.node.statement.Statement; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class DoWhileLoopStatement extends ConditionLoopStatement { public DoWhileLoopStatement(Statement statement, Expression condition) { @@ -41,9 +42,4 @@ public DoWhileLoopStatement clone() { public DoWhileLoopStatement cloneInto(Root root) { return (DoWhileLoopStatement) super.cloneInto(root); } - - @Override - public DoWhileLoopStatement cloneSeparate() { - return (DoWhileLoopStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/ForLoopStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/ForLoopStatement.java index 2902c7a779..5a7da5ff41 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/ForLoopStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/ForLoopStatement.java @@ -5,7 +5,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.node.statement.Statement; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class ForLoopStatement extends LoopStatement { protected Expression initExpression; // TODO: nullable @@ -160,9 +161,4 @@ public ForLoopStatement clone() { public ForLoopStatement cloneInto(Root root) { return (ForLoopStatement) super.cloneInto(root); } - - @Override - public ForLoopStatement cloneSeparate() { - return (ForLoopStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/LoopStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/LoopStatement.java index 7829dc28a0..89dfbfa1ae 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/LoopStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/LoopStatement.java @@ -47,9 +47,4 @@ public void exitNode(ASTListener listener) { public LoopStatement cloneInto(Root root) { return (LoopStatement) super.cloneInto(root); } - - @Override - public LoopStatement cloneSeparate() { - return (LoopStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/WhileLoopStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/WhileLoopStatement.java index a71ac6569b..2c17d4698b 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/WhileLoopStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/loop/WhileLoopStatement.java @@ -69,9 +69,4 @@ public WhileLoopStatement clone() { public WhileLoopStatement cloneInto(Root root) { return (WhileLoopStatement) super.cloneInto(root); } - - @Override - public WhileLoopStatement cloneSeparate() { - return (WhileLoopStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/selection/SelectionStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/selection/SelectionStatement.java index 7394df23dd..c8177c3a82 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/selection/SelectionStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/selection/SelectionStatement.java @@ -84,9 +84,4 @@ public SelectionStatement clone() { public SelectionStatement cloneInto(Root root) { return (SelectionStatement) super.cloneInto(root); } - - @Override - public SelectionStatement cloneSeparate() { - return (SelectionStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/selection/SwitchStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/selection/SwitchStatement.java index 0d4704bc20..c90dcad816 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/selection/SwitchStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/selection/SwitchStatement.java @@ -70,9 +70,4 @@ public SwitchStatement clone() { public SwitchStatement cloneInto(Root root) { return (SwitchStatement) super.cloneInto(root); } - - @Override - public SwitchStatement cloneSeparate() { - return (SwitchStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/BreakStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/BreakStatement.java index 78c1423240..146c58c8d6 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/BreakStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/BreakStatement.java @@ -26,9 +26,4 @@ public BreakStatement clone() { public BreakStatement cloneInto(Root root) { return (BreakStatement) super.cloneInto(root); } - - @Override - public BreakStatement cloneSeparate() { - return (BreakStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/CaseLabelStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/CaseLabelStatement.java index c4f8da8021..add0a88ea0 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/CaseLabelStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/CaseLabelStatement.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.statement.Statement; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public abstract class CaseLabelStatement extends Statement { public enum CaseLabelType { @@ -39,9 +40,4 @@ public void exitNode(ASTListener listener) { public CaseLabelStatement cloneInto(Root root) { return (CaseLabelStatement) super.cloneInto(root); } - - @Override - public CaseLabelStatement cloneSeparate() { - return (CaseLabelStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/CaseStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/CaseStatement.java index f6471298f2..1bcd50e636 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/CaseStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/CaseStatement.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class CaseStatement extends CaseLabelStatement { protected Expression expression; @@ -56,9 +57,4 @@ public CaseStatement clone() { public CaseStatement cloneInto(Root root) { return (CaseStatement) super.cloneInto(root); } - - @Override - public CaseStatement cloneSeparate() { - return (CaseStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/ContinueStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/ContinueStatement.java index 6d68db4586..9dffe5a865 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/ContinueStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/ContinueStatement.java @@ -26,9 +26,4 @@ public ContinueStatement clone() { public ContinueStatement cloneInto(Root root) { return (ContinueStatement) super.cloneInto(root); } - - @Override - public ContinueStatement cloneSeparate() { - return (ContinueStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DeclarationStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DeclarationStatement.java index 70739bbc39..c3346c6fa8 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DeclarationStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DeclarationStatement.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.declaration.Declaration; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class DeclarationStatement extends SemiTerminalStatement { protected Declaration declaration; @@ -51,9 +52,4 @@ public DeclarationStatement clone() { public DeclarationStatement cloneInto(Root root) { return (DeclarationStatement) super.cloneInto(root); } - - @Override - public DeclarationStatement cloneSeparate() { - return (DeclarationStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DefaultStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DefaultStatement.java index 36fc13fb21..fd05951f6b 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DefaultStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DefaultStatement.java @@ -28,9 +28,4 @@ public DefaultStatement clone() { public DefaultStatement cloneInto(Root root) { return (DefaultStatement) super.cloneInto(root); } - - @Override - public DefaultStatement cloneSeparate() { - return (DefaultStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DemoteStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DemoteStatement.java index 94b1e9c1bb..198715ab4b 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DemoteStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DemoteStatement.java @@ -26,9 +26,4 @@ public DemoteStatement clone() { public DemoteStatement cloneInto(Root root) { return (DemoteStatement) super.cloneInto(root); } - - @Override - public DemoteStatement cloneSeparate() { - return (DemoteStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DiscardStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DiscardStatement.java index 39aa930fdb..5cbb25c622 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DiscardStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/DiscardStatement.java @@ -26,9 +26,4 @@ public DiscardStatement clone() { public DiscardStatement cloneInto(Root root) { return (DiscardStatement) super.cloneInto(root); } - - @Override - public DiscardStatement cloneSeparate() { - return (DiscardStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/EmptyStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/EmptyStatement.java index 1614652400..0a10bae612 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/EmptyStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/EmptyStatement.java @@ -26,9 +26,4 @@ public EmptyStatement clone() { public EmptyStatement cloneInto(Root root) { return (EmptyStatement) super.cloneInto(root); } - - @Override - public EmptyStatement cloneSeparate() { - return (EmptyStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/ExpressionStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/ExpressionStatement.java index 5a58d7a41a..0d83ee342e 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/ExpressionStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/ExpressionStatement.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class ExpressionStatement extends SemiTerminalStatement { protected Expression expression; @@ -51,9 +52,4 @@ public ExpressionStatement clone() { public ExpressionStatement cloneInto(Root root) { return (ExpressionStatement) super.cloneInto(root); } - - @Override - public ExpressionStatement cloneSeparate() { - return (ExpressionStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/IgnoreIntersectionStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/IgnoreIntersectionStatement.java index 598df3591b..1ad9da1b91 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/IgnoreIntersectionStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/IgnoreIntersectionStatement.java @@ -26,9 +26,4 @@ public IgnoreIntersectionStatement clone() { public IgnoreIntersectionStatement cloneInto(Root root) { return (IgnoreIntersectionStatement) super.cloneInto(root); } - - @Override - public IgnoreIntersectionStatement cloneSeparate() { - return (IgnoreIntersectionStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/ReturnStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/ReturnStatement.java index 09932158aa..90e7d9513d 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/ReturnStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/ReturnStatement.java @@ -42,9 +42,4 @@ public ReturnStatement clone() { public ReturnStatement cloneInto(Root root) { return (ReturnStatement) super.cloneInto(root); } - - @Override - public ReturnStatement cloneSeparate() { - return (ReturnStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/SemiTerminalStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/SemiTerminalStatement.java index 57e2e28a5f..654befd776 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/SemiTerminalStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/SemiTerminalStatement.java @@ -35,9 +35,4 @@ public void exitNode(ASTListener listener) { public SemiTerminalStatement cloneInto(Root root) { return (SemiTerminalStatement) super.cloneInto(root); } - - @Override - public SemiTerminalStatement cloneSeparate() { - return (SemiTerminalStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/TerminalStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/TerminalStatement.java index 397ef7d570..86f036beb2 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/TerminalStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/TerminalStatement.java @@ -32,9 +32,4 @@ public void exitNode(ASTListener listener) { public TerminalStatement cloneInto(Root root) { return (TerminalStatement) super.cloneInto(root); } - - @Override - public TerminalStatement cloneSeparate() { - return (TerminalStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/TerminateRayStatement.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/TerminateRayStatement.java index 65e0c09afc..647e4a4c45 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/TerminateRayStatement.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/statement/terminal/TerminateRayStatement.java @@ -26,9 +26,4 @@ public TerminateRayStatement clone() { public TerminateRayStatement cloneInto(Root root) { return (TerminateRayStatement) super.cloneInto(root); } - - @Override - public TerminateRayStatement cloneSeparate() { - return (TerminateRayStatement) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/FullySpecifiedType.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/FullySpecifiedType.java index a4afcaffb4..7b7d793dce 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/FullySpecifiedType.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/FullySpecifiedType.java @@ -4,7 +4,8 @@ import io.github.douira.glsl_transformer.ast.node.type.qualifier.TypeQualifier; import io.github.douira.glsl_transformer.ast.node.type.specifier.TypeSpecifier; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class FullySpecifiedType extends InnerASTNode { protected TypeQualifier typeQualifier; // TODO: nullable @@ -61,9 +62,4 @@ public FullySpecifiedType clone() { public FullySpecifiedType cloneInto(Root root) { return (FullySpecifiedType) super.cloneInto(root); } - - @Override - public FullySpecifiedType cloneSeparate() { - return (FullySpecifiedType) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/initializer/ExpressionInitializer.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/initializer/ExpressionInitializer.java index 0b81faebcc..b4a90d736e 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/initializer/ExpressionInitializer.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/initializer/ExpressionInitializer.java @@ -2,7 +2,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; public class ExpressionInitializer extends Initializer { protected Expression expression; @@ -51,9 +52,4 @@ public ExpressionInitializer clone() { public ExpressionInitializer cloneInto(Root root) { return (ExpressionInitializer) super.cloneInto(root); } - - @Override - public ExpressionInitializer cloneSeparate() { - return (ExpressionInitializer) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/initializer/Initializer.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/initializer/Initializer.java index a18820e23a..7bf9b908f1 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/initializer/Initializer.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/initializer/Initializer.java @@ -38,9 +38,4 @@ public void exitNode(ASTListener listener) { public Initializer cloneInto(Root root) { return (Initializer) super.cloneInto(root); } - - @Override - public Initializer cloneSeparate() { - return (Initializer) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/initializer/NestedInitializer.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/initializer/NestedInitializer.java index 59a382236a..b7b446dc5a 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/initializer/NestedInitializer.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/initializer/NestedInitializer.java @@ -1,6 +1,5 @@ package io.github.douira.glsl_transformer.ast.node.type.initializer; -import java.util.List; import java.util.stream.Stream; import io.github.douira.glsl_transformer.ast.data.ChildNodeList; @@ -18,7 +17,7 @@ public NestedInitializer() { this.initializers = new ChildNodeList<>(this); } - public List getInitializers() { + public ChildNodeList getInitializers() { return initializers; } @@ -53,9 +52,4 @@ public NestedInitializer clone() { public NestedInitializer cloneInto(Root root) { return (NestedInitializer) super.cloneInto(root); } - - @Override - public NestedInitializer cloneSeparate() { - return (NestedInitializer) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/InterpolationQualifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/InterpolationQualifier.java index 198fa2ab5d..464d63b908 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/InterpolationQualifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/InterpolationQualifier.java @@ -66,9 +66,4 @@ public InterpolationQualifier clone() { public InterpolationQualifier cloneInto(Root root) { return (InterpolationQualifier) super.cloneInto(root); } - - @Override - public InterpolationQualifier cloneSeparate() { - return (InterpolationQualifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/InvariantQualifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/InvariantQualifier.java index 5234e666f8..593401b796 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/InvariantQualifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/InvariantQualifier.java @@ -35,9 +35,4 @@ public InvariantQualifier clone() { public InvariantQualifier cloneInto(Root root) { return (InvariantQualifier) super.cloneInto(root); } - - @Override - public InvariantQualifier cloneSeparate() { - return (InvariantQualifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/LayoutQualifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/LayoutQualifier.java index 82731c5ab6..4616ceec69 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/LayoutQualifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/LayoutQualifier.java @@ -1,6 +1,5 @@ package io.github.douira.glsl_transformer.ast.node.type.qualifier; -import java.util.List; import java.util.stream.Stream; import io.github.douira.glsl_transformer.ast.data.ChildNodeList; @@ -14,7 +13,7 @@ public LayoutQualifier(Stream parts) { this.parts = ChildNodeList.collect(parts, this); } - public List getParts() { + public ChildNodeList getParts() { return parts; } @@ -49,9 +48,4 @@ public LayoutQualifier clone() { public LayoutQualifier cloneInto(Root root) { return (LayoutQualifier) super.cloneInto(root); } - - @Override - public LayoutQualifier cloneSeparate() { - return (LayoutQualifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/LayoutQualifierPart.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/LayoutQualifierPart.java index 0eebb22b86..de7f3b051d 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/LayoutQualifierPart.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/LayoutQualifierPart.java @@ -38,9 +38,4 @@ public void exitNode(ASTListener listener) { public LayoutQualifierPart cloneInto(Root root) { return (LayoutQualifierPart) super.cloneInto(root); } - - @Override - public LayoutQualifierPart cloneSeparate() { - return (LayoutQualifierPart) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/NamedLayoutQualifierPart.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/NamedLayoutQualifierPart.java index 447813862d..8352f52dbf 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/NamedLayoutQualifierPart.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/NamedLayoutQualifierPart.java @@ -67,9 +67,4 @@ public NamedLayoutQualifierPart clone() { public NamedLayoutQualifierPart cloneInto(Root root) { return (NamedLayoutQualifierPart) super.cloneInto(root); } - - @Override - public NamedLayoutQualifierPart cloneSeparate() { - return (NamedLayoutQualifierPart) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/PreciseQualifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/PreciseQualifier.java index 1b60d41d24..64b7eef17d 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/PreciseQualifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/PreciseQualifier.java @@ -35,9 +35,4 @@ public PreciseQualifier clone() { public PreciseQualifier cloneInto(Root root) { return (PreciseQualifier) super.cloneInto(root); } - - @Override - public PreciseQualifier cloneSeparate() { - return (PreciseQualifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/PrecisionQualifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/PrecisionQualifier.java index 4188b0be9d..fced23bd0c 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/PrecisionQualifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/PrecisionQualifier.java @@ -66,9 +66,4 @@ public PrecisionQualifier clone() { public PrecisionQualifier cloneInto(Root root) { return (PrecisionQualifier) super.cloneInto(root); } - - @Override - public PrecisionQualifier cloneSeparate() { - return (PrecisionQualifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/SharedLayoutQualifierPart.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/SharedLayoutQualifierPart.java index 808baa746b..8be28ce7d1 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/SharedLayoutQualifierPart.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/SharedLayoutQualifierPart.java @@ -35,9 +35,4 @@ public SharedLayoutQualifierPart clone() { public SharedLayoutQualifierPart cloneInto(Root root) { return (SharedLayoutQualifierPart) super.cloneInto(root); } - - @Override - public SharedLayoutQualifierPart cloneSeparate() { - return (SharedLayoutQualifierPart) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/StorageQualifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/StorageQualifier.java index 9d081abd96..38e7d88c2e 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/StorageQualifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/StorageQualifier.java @@ -1,6 +1,5 @@ package io.github.douira.glsl_transformer.ast.node.type.qualifier; -import java.util.List; import java.util.stream.Stream; import repack.antlr.v4.runtime.Token; @@ -76,7 +75,7 @@ public StorageQualifier(StorageType storageType) { this.storageType = storageType; } - public List getTypeNames() { + public ChildNodeList getTypeNames() { return typeNames; } @@ -111,9 +110,4 @@ public StorageQualifier clone() { public StorageQualifier cloneInto(Root root) { return (StorageQualifier) super.cloneInto(root); } - - @Override - public StorageQualifier cloneSeparate() { - return (StorageQualifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/TypeQualifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/TypeQualifier.java index 81f7f20a63..0f63a82e6e 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/TypeQualifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/TypeQualifier.java @@ -40,9 +40,4 @@ public TypeQualifier clone() { public TypeQualifier cloneInto(Root root) { return (TypeQualifier) super.cloneInto(root); } - - @Override - public TypeQualifier cloneSeparate() { - return (TypeQualifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/TypeQualifierPart.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/TypeQualifierPart.java index 8e1671ffba..732eadf956 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/TypeQualifierPart.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/qualifier/TypeQualifierPart.java @@ -42,9 +42,4 @@ public void exitNode(ASTListener listener) { public TypeQualifierPart cloneInto(Root root) { return (TypeQualifierPart) super.cloneInto(root); } - - @Override - public TypeQualifierPart cloneSeparate() { - return (TypeQualifierPart) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/ArraySpecifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/ArraySpecifier.java index cec8e8e779..b0a78860cd 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/ArraySpecifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/ArraySpecifier.java @@ -1,12 +1,13 @@ package io.github.douira.glsl_transformer.ast.node.type.specifier; -import java.util.List; -import java.util.stream.Stream; - import io.github.douira.glsl_transformer.ast.node.abstract_node.ListASTNode; import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; + +import java.util.List; +import java.util.stream.Stream; //TODO: any of these expressions can be null public class ArraySpecifier extends ListASTNode { @@ -42,9 +43,4 @@ public ArraySpecifier clone() { public ArraySpecifier cloneInto(Root root) { return (ArraySpecifier) super.cloneInto(root); } - - @Override - public ArraySpecifier cloneSeparate() { - return (ArraySpecifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/BuiltinFixedTypeSpecifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/BuiltinFixedTypeSpecifier.java index 04b781a376..f388ece751 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/BuiltinFixedTypeSpecifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/BuiltinFixedTypeSpecifier.java @@ -1,11 +1,12 @@ package io.github.douira.glsl_transformer.ast.node.type.specifier; -import repack.antlr.v4.runtime.Token; - import io.github.douira.glsl_transformer.GLSLLexer; -import io.github.douira.glsl_transformer.ast.data.*; +import io.github.douira.glsl_transformer.ast.data.TokenTyped; +import io.github.douira.glsl_transformer.ast.data.TypeUtil; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; +import repack.antlr.v4.runtime.Token; public class BuiltinFixedTypeSpecifier extends TypeSpecifier { public enum BuiltinType implements TokenTyped { @@ -166,9 +167,4 @@ public BuiltinFixedTypeSpecifier clone() { public BuiltinFixedTypeSpecifier cloneInto(Root root) { return (BuiltinFixedTypeSpecifier) super.cloneInto(root); } - - @Override - public BuiltinFixedTypeSpecifier cloneSeparate() { - return (BuiltinFixedTypeSpecifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/BuiltinNumericTypeSpecifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/BuiltinNumericTypeSpecifier.java index 98409d31b8..d6328b62f5 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/BuiltinNumericTypeSpecifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/BuiltinNumericTypeSpecifier.java @@ -1,7 +1,8 @@ package io.github.douira.glsl_transformer.ast.node.type.specifier; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; import io.github.douira.glsl_transformer.util.Type; public class BuiltinNumericTypeSpecifier extends TypeSpecifier { @@ -47,9 +48,4 @@ public BuiltinNumericTypeSpecifier clone() { public BuiltinNumericTypeSpecifier cloneInto(Root root) { return (BuiltinNumericTypeSpecifier) super.cloneInto(root); } - - @Override - public BuiltinNumericTypeSpecifier cloneSeparate() { - return (BuiltinNumericTypeSpecifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/FunctionPrototype.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/FunctionPrototype.java index 11758baac2..d228b29874 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/FunctionPrototype.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/FunctionPrototype.java @@ -1,14 +1,15 @@ package io.github.douira.glsl_transformer.ast.node.type.specifier; -import java.util.List; -import java.util.stream.Stream; - import io.github.douira.glsl_transformer.ast.node.Identifier; import io.github.douira.glsl_transformer.ast.node.abstract_node.ListASTNode; import io.github.douira.glsl_transformer.ast.node.declaration.FunctionParameter; import io.github.douira.glsl_transformer.ast.node.type.FullySpecifiedType; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.traversal.*; +import io.github.douira.glsl_transformer.ast.traversal.ASTListener; +import io.github.douira.glsl_transformer.ast.traversal.ASTVisitor; + +import java.util.List; +import java.util.stream.Stream; public class FunctionPrototype extends ListASTNode { protected FullySpecifiedType returnType; @@ -69,9 +70,4 @@ public FunctionPrototype clone() { public FunctionPrototype cloneInto(Root root) { return (FunctionPrototype) super.cloneInto(root); } - - @Override - public FunctionPrototype cloneSeparate() { - return (FunctionPrototype) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/TypeReference.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/TypeReference.java index f6beca72d0..54df2749e4 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/TypeReference.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/TypeReference.java @@ -56,9 +56,4 @@ public TypeReference clone() { public TypeReference cloneInto(Root root) { return (TypeReference) super.cloneInto(root); } - - @Override - public TypeReference cloneSeparate() { - return (TypeReference) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/TypeSpecifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/TypeSpecifier.java index 90012bee26..90f1efb38a 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/TypeSpecifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/specifier/TypeSpecifier.java @@ -58,9 +58,4 @@ public void exitNode(ASTListener listener) { public TypeSpecifier cloneInto(Root root) { return (TypeSpecifier) super.cloneInto(root); } - - @Override - public TypeSpecifier cloneSeparate() { - return (TypeSpecifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructBody.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructBody.java index fed67ad0c0..41060c9afb 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructBody.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructBody.java @@ -40,9 +40,4 @@ public StructBody clone() { public StructBody cloneInto(Root root) { return (StructBody) super.cloneInto(root); } - - @Override - public StructBody cloneSeparate() { - return (StructBody) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructDeclarator.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructDeclarator.java index 18b13f4609..470e40e4f1 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructDeclarator.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructDeclarator.java @@ -61,9 +61,4 @@ public StructDeclarator clone() { public StructDeclarator cloneInto(Root root) { return (StructDeclarator) super.cloneInto(root); } - - @Override - public StructDeclarator cloneSeparate() { - return (StructDeclarator) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructMember.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructMember.java index c41ed39354..1a4ce6d8d7 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructMember.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructMember.java @@ -1,6 +1,5 @@ package io.github.douira.glsl_transformer.ast.node.type.struct; -import java.util.List; import java.util.stream.Stream; import io.github.douira.glsl_transformer.ast.data.ChildNodeList; @@ -27,7 +26,7 @@ public void setType(FullySpecifiedType type) { this.type = type; } - public List getDeclarators() { + public ChildNodeList getDeclarators() { return declarators; } @@ -55,9 +54,4 @@ public StructMember clone() { public StructMember cloneInto(Root root) { return (StructMember) super.cloneInto(root); } - - @Override - public StructMember cloneSeparate() { - return (StructMember) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructSpecifier.java b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructSpecifier.java index a479787f7d..91f07598ab 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructSpecifier.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/node/type/struct/StructSpecifier.java @@ -81,9 +81,4 @@ public StructSpecifier clone() { public StructSpecifier cloneInto(Root root) { return (StructSpecifier) super.cloneInto(root); } - - @Override - public StructSpecifier cloneSeparate() { - return (StructSpecifier) super.cloneSeparate(); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/print/ASTPrinter.java b/src/main/java/io/github/douira/glsl_transformer/ast/print/ASTPrinter.java index 2eeb397a92..a3c5b91d5c 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/print/ASTPrinter.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/print/ASTPrinter.java @@ -1,30 +1,44 @@ package io.github.douira.glsl_transformer.ast.print; -import java.util.*; - import io.github.douira.glsl_transformer.GLSLLexer; -import io.github.douira.glsl_transformer.ast.node.*; +import io.github.douira.glsl_transformer.ast.node.Identifier; +import io.github.douira.glsl_transformer.ast.node.IterationConditionInitializer; +import io.github.douira.glsl_transformer.ast.node.TranslationUnit; +import io.github.douira.glsl_transformer.ast.node.VersionStatement; import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; import io.github.douira.glsl_transformer.ast.node.declaration.*; -import io.github.douira.glsl_transformer.ast.node.expression.*; +import io.github.douira.glsl_transformer.ast.node.expression.ConditionExpression; +import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.node.expression.Expression.ExpressionType; import io.github.douira.glsl_transformer.ast.node.expression.Expression.ExpressionType.OperandStructure; +import io.github.douira.glsl_transformer.ast.node.expression.LiteralExpression; +import io.github.douira.glsl_transformer.ast.node.expression.SequenceExpression; import io.github.douira.glsl_transformer.ast.node.expression.binary.*; import io.github.douira.glsl_transformer.ast.node.expression.unary.*; import io.github.douira.glsl_transformer.ast.node.external_declaration.*; import io.github.douira.glsl_transformer.ast.node.external_declaration.PragmaDirective.PragmaType; -import io.github.douira.glsl_transformer.ast.node.statement.*; -import io.github.douira.glsl_transformer.ast.node.statement.loop.*; -import io.github.douira.glsl_transformer.ast.node.statement.selection.*; +import io.github.douira.glsl_transformer.ast.node.statement.CompoundStatement; +import io.github.douira.glsl_transformer.ast.node.statement.Statement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.DoWhileLoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.ForLoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.WhileLoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.selection.SelectionStatement; +import io.github.douira.glsl_transformer.ast.node.statement.selection.SwitchStatement; import io.github.douira.glsl_transformer.ast.node.statement.terminal.*; import io.github.douira.glsl_transformer.ast.node.type.FullySpecifiedType; import io.github.douira.glsl_transformer.ast.node.type.initializer.NestedInitializer; import io.github.douira.glsl_transformer.ast.node.type.qualifier.*; import io.github.douira.glsl_transformer.ast.node.type.specifier.*; -import io.github.douira.glsl_transformer.ast.node.type.struct.*; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructBody; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructDeclarator; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructMember; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructSpecifier; import io.github.douira.glsl_transformer.ast.print.token.EOFToken; import io.github.douira.glsl_transformer.util.Type.NumberType; +import java.util.ArrayDeque; +import java.util.Deque; + /** * The AST printer emits tokens to convert an AST node into a string with the * help of a few other utility classes. Information encoded about the string @@ -127,7 +141,7 @@ public Void visitPragmaDirective(PragmaDirective node) { emitExtendableSpace(); } if (node.type == PragmaType.CUSTOM) { - emitLiteral(node.customName); + emitLiteral(node.getCustomName()); } else { emitType( node.type.tokenType, @@ -143,7 +157,7 @@ public Void visitPragmaDirective(PragmaDirective node) { public Void visitExtensionDirective(ExtensionDirective node) { emitType(GLSLLexer.NR, GLSLLexer.NR_EXTENSION); emitExtendableSpace(); - emitLiteral(node.name); + emitLiteral(node.getName()); if (node.behavior != null) { emitType(GLSLLexer.NR_COLON); emitExtendableSpace(); @@ -161,9 +175,10 @@ public Void visitCustomDirective(CustomDirective node) { return null; } emitType(GLSLLexer.NR, GLSLLexer.NR_CUSTOM); - if (node.content != null) { + var content = node.getContent(); + if (content != null) { emitExtendableSpace(); - emitLiteral(node.content); + emitLiteral(content); } emitExactNewline(); return null; @@ -174,8 +189,9 @@ public Void visitIncludeDirective(IncludeDirective node) { emitType(GLSLLexer.NR, GLSLLexer.NR_INCLUDE); emitExtendableSpace(); emitType(node.isAngleBrackets ? GLSLLexer.NR_STRING_START_ANGLE : GLSLLexer.NR_STRING_START); - if (node.content != null) { - emitLiteral(node.content); + var content = node.getContent(); + if (content != null) { + emitLiteral(content); } emitType(node.isAngleBrackets ? GLSLLexer.S_STRING_END_ANGLE : GLSLLexer.S_STRING_END); emitExactNewline(); @@ -819,7 +835,7 @@ private void visitLoopBody(Statement statement) { * * iterationCondition: * expression * | fullySpecifiedType IDENTIFIER ASSIGN_OP initializer; - * + * * forStatement: * attribute? FOR LPAREN ( * emptyStatement @@ -827,7 +843,7 @@ private void visitLoopBody(Statement statement) { * | declarationStatement * ) condition = iterationCondition? SEMICOLON incrementer = expression? RPAREN * loopBody = statement; - * + * */ @Override public Void visitForLoopStatement(ForLoopStatement node) { diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/print/ASTPrinterBase.java b/src/main/java/io/github/douira/glsl_transformer/ast/print/ASTPrinterBase.java index 74c7902e30..20b3111d09 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/print/ASTPrinterBase.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/print/ASTPrinterBase.java @@ -1,7 +1,5 @@ package io.github.douira.glsl_transformer.ast.print; -import java.util.List; - import io.github.douira.glsl_transformer.GLSLLexer; import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; import io.github.douira.glsl_transformer.ast.print.token.*; @@ -9,6 +7,8 @@ import io.github.douira.glsl_transformer.ast.traversal.ASTListenerVisitor; import io.github.douira.glsl_transformer.token_filter.TokenChannel; +import java.util.List; + public abstract class ASTPrinterBase extends ASTListenerVisitor { private PrintToken lastToken; private ASTNode currentNode; diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/print/CompactPrinter.java b/src/main/java/io/github/douira/glsl_transformer/ast/print/CompactPrinter.java index af5064f822..d5d43e96f1 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/print/CompactPrinter.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/print/CompactPrinter.java @@ -1,6 +1,7 @@ package io.github.douira.glsl_transformer.ast.print; -import io.github.douira.glsl_transformer.ast.print.token.*; +import io.github.douira.glsl_transformer.ast.print.token.LiteralToken; +import io.github.douira.glsl_transformer.ast.print.token.PrintToken; import io.github.douira.glsl_transformer.token_filter.TokenChannel; public class CompactPrinter extends DelegateTokenProcessor { diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/EmptyRoot.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/EmptyRoot.java deleted file mode 100644 index e3135abece..0000000000 --- a/src/main/java/io/github/douira/glsl_transformer/ast/query/EmptyRoot.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.douira.glsl_transformer.ast.query; - -import io.github.douira.glsl_transformer.ast.node.Identifier; -import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; - -/** - * The empty root overrides a normal root just to do nothing. This allows a root - * stub to exist without the performance cost of registering and unregistering - * nodes. - */ -public class EmptyRoot extends Root { - public EmptyRoot() { - super(null, null); - } - - @Override - public void registerIdentifierRename(Identifier identifier) { - } - - @Override - public void registerNode(ASTNode node) { - } - - @Override - public void unregisterIdentifierRename(Identifier identifier) { - } - - @Override - public void unregisterNode(ASTNode node) { - } -} diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/Root.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/Root.java index dfabb73611..3e3be2d9fe 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/query/Root.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/Root.java @@ -4,9 +4,10 @@ import java.util.function.*; import java.util.stream.Stream; -import io.github.douira.glsl_transformer.ast.node.Identifier; +import io.github.douira.glsl_transformer.ast.node.*; import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; import io.github.douira.glsl_transformer.ast.node.expression.*; +import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration; import io.github.douira.glsl_transformer.ast.query.index.*; import io.github.douira.glsl_transformer.ast.query.match.*; import io.github.douira.glsl_transformer.ast.transform.ASTParser; @@ -34,10 +35,12 @@ public class Root { */ public final IdentifierIndex identifierIndex; - public static final Supplier> nodeIndexFactoryDefault = NodeIndex::withUnordered; - public static final Supplier> identifierIndexFactoryDefault = IdentifierIndex::withOnlyExact; - public static Supplier> nodeIndexFactory = nodeIndexFactoryDefault; - public static Supplier> identifierIndexFactory = identifierIndexFactoryDefault; + /** + * The external declaration index indexes the external declarations by their + * name. Each node may appear multiple times if it contains multiple members + * with different names. + */ + public final ExternalDeclarationIndex externalDeclarationIndex; // internal utility state private static Deque activeBuildRoots = new ArrayDeque<>(); @@ -47,49 +50,118 @@ public class Root { /** * Constructs a new root with the given node and identifier indexes. * - * @param nodeIndex The node index - * @param identifierIndex The identifier index + * @param nodeIndex The node index + * @param identifierIndex The identifier index + * @param externalDeclarationIndex The external declaration index */ - public Root(NodeIndex nodeIndex, IdentifierIndex identifierIndex) { + public Root(NodeIndex nodeIndex, + IdentifierIndex identifierIndex, + ExternalDeclarationIndex externalDeclarationIndex) { this.nodeIndex = nodeIndex; this.identifierIndex = identifierIndex; + this.externalDeclarationIndex = externalDeclarationIndex; + } + + /** + * Returns the identifier index as a prefix identifier index if it is one. + * Otherwise, it throws. + * + * @return The prefix identifier index + */ + public PrefixIdentifierIndex getPrefixIdentifierIndex() { + if (identifierIndex instanceof PrefixIdentifierIndex index) { + return index; + } else { + throw new IllegalStateException("The identifier index is not a prefix index"); + } } - public Root() { - this(nodeIndexFactory.get(), identifierIndexFactory.get()); + public PrefixExternalDeclarationIndex getPrefixExternalDeclarationIndex() { + if (externalDeclarationIndex instanceof PrefixExternalDeclarationIndex index) { + return index; + } else { + throw new IllegalStateException("The external declaration index is not a prefix index"); + } } /** - * Constructs a new root with the default node and identifier indexes which have - * the least amount of functionality but are also the most efficient. + * Registers the given node with this root. + * + * @param node The node to register + * @param isSubtreeRoot Whether the node is the root of a subtree that is being + * added */ - public static Root withExactUnordered() { - return new Root(NodeIndex.withUnordered(), IdentifierIndex.withOnlyExact()); + public void registerNode(ASTNode node, boolean isSubtreeRoot) { + if (nodeIndex != null) { + nodeIndex.add(node); + } + if (identifierIndex != null && node instanceof Identifier identifier) { + identifierIndex.add(identifier); + } + if (externalDeclarationIndex != null) { + if (node instanceof ExternalDeclaration externalDeclaration) { + externalDeclarationIndex.add(externalDeclaration); + } else if (isSubtreeRoot && !(node instanceof TranslationUnit)) { + externalDeclarationIndex.notifySubtreeAdd(node); + } + } } - public static Root withExactOrdered() { - return new Root(NodeIndex.withOrdered(), IdentifierIndex.withOnlyExact()); + /** + * Unregisters the given node from this root. + * + * @param node The node to unregister + * @param isSubtreeRoot Whether the node is the root of a subtree that is being + * removed + */ + public void unregisterNode(ASTNode node, boolean isSubtreeRoot) { + if (nodeIndex != null) { + nodeIndex.remove(node); + } + if (identifierIndex != null && node instanceof Identifier identifier) { + identifierIndex.remove(identifier); + } + if (externalDeclarationIndex != null) { + if (node instanceof ExternalDeclaration externalDeclaration) { + externalDeclarationIndex.remove(externalDeclaration); + } else if (isSubtreeRoot && !(node instanceof TranslationUnit)) { + externalDeclarationIndex.notifySubtreeRemove(node); + } + } } - public static Root withExactOrderedBoth() { - return new Root(NodeIndex.withOrdered(), IdentifierIndex.withOnlyExact(LinkedHashSet::new)); + public void unregisterIdentifierRename(Identifier identifier) { + if (identifierIndex != null) { + identifierIndex.remove(identifier); + } + unregisterFastRename(identifier); } - public static Root withPrefixUnordered() { - return new Root(NodeIndex.withUnordered(), PrefixIdentifierIndex.withPrefix()); + public void unregisterFastRename(ASTNode identifier) { + if (externalDeclarationIndex != null) { + externalDeclarationIndex.notifySubtreeRemove(identifier); + } } - public static Root withPrefixOrdered() { - return new Root(NodeIndex.withOrdered(), PrefixIdentifierIndex.withPrefix()); + public void registerIdentifierRename(Identifier identifier) { + if (identifierIndex != null) { + identifierIndex.add(identifier); + } + registerFastRename(identifier); } - public static Root withPrefixOrderedBoth() { - return new Root(NodeIndex.withOrdered(), PrefixIdentifierIndex.withPrefix(LinkedHashSet::new)); + public void registerFastRename(ASTNode identifier) { + if (externalDeclarationIndex != null) { + externalDeclarationIndex.notifySubtreeAdd(identifier); + } } - public static void resetRootFactories() { - nodeIndexFactory = nodeIndexFactoryDefault; - identifierIndexFactory = identifierIndexFactoryDefault; + private void ensureEmptyNodeList() { + if (nodeList == null) { + nodeList = new ArrayList<>(); + } else { + nodeList.clear(); + } } /** @@ -108,16 +180,14 @@ public static Root getActiveBuildRoot() { * Runs the given consumer with the given root as the active build root. * * @param The return type of the consumer - * @param instance The root to run the consumer with * @param rootConsumer The consumer to run * @return The return value of the consumer */ - protected static final synchronized R withActiveBuildRoot( - Root instance, + protected final R withActiveBuildRoot( Function rootConsumer) { - activeBuildRoots.push(instance); + activeBuildRoots.push(this); try { - return rootConsumer.apply(instance); + return rootConsumer.apply(this); } finally { activeBuildRoots.pop(); } @@ -131,78 +201,36 @@ protected static final synchronized R withActiveBuildRoot( * another node with the root. * * @param The type of the node to build - * @param instance The root to run the builder with * @param builder The builder to run * @return The built and registered node */ - public static synchronized N indexNodes( - Root instance, Supplier builder) { - return withActiveBuildRoot(instance, root -> { + public N indexNodes(Supplier builder) { + return withActiveBuildRoot(root -> { var result = builder.get(); - root.registerNode(result); + root.registerNode(result, true); return result; }); } - /** - * Runs the given builder supplier with a new root as the active build root. - * - * @param The type of the node to build - * @param builder The builder to run - * @return The built and registered node - */ - public static N indexNodes( - Supplier builder) { - return indexNodes(new Root(), builder); - } - - /** - * Runs the given builder supplier with the same root as a given tree node as - * the active build root. - * - * @param The type of the node to build - * @param parentTreeMember The tree member to get the root from - * @param builder The builder to run - * @return The built and registered node - */ - public static N indexNodes( - ASTNode parentTreeMember, Supplier builder) { - return indexNodes(parentTreeMember.getRoot(), builder); - } - /** * Runs a given runnable with the given root as the active build root. This is * used for constructing nodes with children without registering the constructed * root node with the root or for registering it manually. * - * @param instance The root to use as the active build root * @param session The runnable to run */ - public static synchronized void indexBuildSession(Root instance, Runnable session) { - withActiveBuildRoot(instance, root -> { + public void indexBuildSession(Runnable session) { + withActiveBuildRoot(root -> { session.run(); return null; }); } - /** - * Runs the given runnable with a new root as the active build root. - * - * @param session The runnable to run - */ - public static void indexBuildSession(Runnable session) { - indexBuildSession(new Root(), session); - } - - /** - * Runs the given runnable with the same root as a given tree node as the active - * build root. - * - * @param treeMember The tree member to get the root from - * @param session The runnable to run - */ - public static void indexBuildSession(ASTNode treeMember, Runnable session) { - indexBuildSession(treeMember.getRoot(), session); + public void indexBuildSession(Consumer session) { + withActiveBuildRoot(root -> { + session.accept(root); + return null; + }); } /** @@ -212,96 +240,18 @@ public static void indexBuildSession(ASTNode treeMember, Runnable session) { * is helpful for constructing trees manually and registering them inline. * * @param The type of the nodes to register - * @param instance the root to register the nodes with * @param registererConsumer The consumer to run */ - public static synchronized void indexSeparateTrees( - Root instance, Consumer> registererConsumer) { - withActiveBuildRoot(instance, root -> { - registererConsumer.accept(Passthrough.of(root::registerNode)); + public void indexSeparateTrees(Consumer> registererConsumer) { + withActiveBuildRoot(root -> { + registererConsumer.accept(node -> { + root.registerNode(node, true); + return node; + }); return null; }); } - /** - * Runs the given consumer of a registration pass-through function with a new - * root as the active build root. - * - * @param The type of the nodes to register - * @param registerer The consumer to run - */ - public static void indexSeparateTrees( - Consumer> registerer) { - indexSeparateTrees(new Root(), registerer); - } - - /** - * Runs the given consumer of a registration pass-through function with the same - * root as a given tree node as the active build root. - * - * @param The type of the nodes to register - * @param treeMember The tree member to get the root from - * @param registerer The consumer to run - */ - public static void indexSeparateTrees( - ASTNode treeMember, Consumer> registerer) { - indexSeparateTrees(treeMember.getRoot(), registerer); - } - - /** - * Returns the identifier index as a prefix identifier index if it is one. - * Otherwise, it throws. - * - * @return The prefix identifier index - */ - public PrefixIdentifierIndex getPrefixIdentifierIndex() { - if (identifierIndex instanceof PrefixIdentifierIndex index) { - return index; - } else { - throw new IllegalStateException("The identifier index is not a prefix index"); - } - } - - /** - * Registers the given node with this root. - * - * @param node The node to register - */ - public void registerNode(ASTNode node) { - nodeIndex.add(node); - if (node instanceof Identifier identifier) { - identifierIndex.add(identifier); - } - } - - /** - * Unregisters the given node from this root. - * - * @param node The node to unregister - */ - public void unregisterNode(ASTNode node) { - nodeIndex.remove(node); - if (node instanceof Identifier identifier) { - identifierIndex.remove(identifier); - } - } - - public void unregisterIdentifierRename(Identifier identifier) { - identifierIndex.remove(identifier); - } - - public void registerIdentifierRename(Identifier identifier) { - identifierIndex.add(identifier); - } - - private void ensureEmptyNodeList() { - if (nodeList == null) { - nodeList = new ArrayList<>(); - } else { - nodeList.clear(); - } - } - /** * Renames all identifiers with the given old name to the given new name. * @@ -411,7 +361,7 @@ public void replaceReferenceExpressions( return; } parent.replaceByAndDelete( - t.parseExpression(identifier, expression)); + t.parseExpression(identifier.getRoot(), expression)); }); } @@ -435,7 +385,7 @@ public boolean replaceReferenceExpressionsReport( return; } parent.replaceByAndDelete( - t.parseExpression(identifier, expression)); + t.parseExpression(identifier.getRoot(), expression)); activity = true; }); return activity; @@ -456,7 +406,7 @@ public boolean replaceExpressions( String expression) { return process(targets, node -> { node.replaceByAndDelete( - t.parseExpression(node, expression)); + t.parseExpression(node.getRoot(), expression)); }); } @@ -476,7 +426,7 @@ public static boolean replaceExpressionsConcurrent( String expression) { for (var node : targets) { node.replaceByAndDelete( - t.parseExpression(node, expression)); + t.parseExpression(node.getRoot(), expression)); } return !targets.isEmpty(); } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/RootSupplier.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/RootSupplier.java new file mode 100644 index 0000000000..3f0262cd54 --- /dev/null +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/RootSupplier.java @@ -0,0 +1,82 @@ +package io.github.douira.glsl_transformer.ast.query; + +import io.github.douira.glsl_transformer.ast.query.index.*; + +import java.util.function.Supplier; + +/** + * Supplies root instances with specific pre-configured indexes. There are a + * number of presets which are the most common, but custom instances of this + * class can specify their own index suppliers. + */ +public class RootSupplier implements Supplier { + public static final RootSupplier EXACT_UNORDERED = new RootSupplier( + NodeIndex::withUnordered, IdentifierIndex::withOnlyExact); + public static final RootSupplier PREFIX_UNORDERED = new RootSupplier( + NodeIndex::withUnordered, PrefixIdentifierIndex::withPrefix); + + public static final RootSupplier EXACT_UNORDERED_ED_EXACT = new RootSupplier( + NodeIndex::withUnordered, + IdentifierIndex::withOnlyExact, + ExternalDeclarationIndex::withOnlyExact); + public static final RootSupplier PREFIX_UNORDERED_ED_EXACT = new RootSupplier( + NodeIndex::withUnordered, + PrefixIdentifierIndex::withPrefix, + ExternalDeclarationIndex::withOnlyExact); + public static final RootSupplier PREFIX_UNORDERED_ED_PREFIX = new RootSupplier( + NodeIndex::withUnordered, + PrefixIdentifierIndex::withPrefix, + PrefixExternalDeclarationIndex::withPrefix); + + public static final RootSupplier EMPTY = new RootSupplier(supplier(null), supplier(null)); + public static final RootSupplier ONLY_NODE_INDEX = new RootSupplier( + NodeIndex::withUnordered, supplier(null)); + public static final RootSupplier ONLY_IDENTIFIER_INDEX = new RootSupplier( + supplier(null), IdentifierIndex::withOnlyExact); + + public static final RootSupplier DEFAULT = EXACT_UNORDERED; + + private static final Supplier supplier(V value) { + return () -> value; + } + + public static Root supplyDefault() { + return DEFAULT.get(); + } + + private final Supplier> nodeIndexSupplier; + private final Supplier> identifierIndexSupplier; + private final Supplier> externalDeclarationIndexSupplier; + + public RootSupplier( + Supplier> nodeIndexSupplier, + Supplier> identifierIndexSupplier, + Supplier> externalDeclarationIndexSupplier) { + this.nodeIndexSupplier = nodeIndexSupplier; + this.identifierIndexSupplier = identifierIndexSupplier; + this.externalDeclarationIndexSupplier = externalDeclarationIndexSupplier; + } + + public RootSupplier( + Supplier> nodeIndexSupplier, + Supplier> identifierIndexSupplier) { + this(nodeIndexSupplier, identifierIndexSupplier, supplier(null)); + } + + @Override + public Root get() { + return new Root( + nodeIndexSupplier.get(), + identifierIndexSupplier.get(), + externalDeclarationIndexSupplier.get()); + } + + public RootSupplier setNodeIndex(Supplier> nodeIndexSupplier) { + return new RootSupplier(nodeIndexSupplier, identifierIndexSupplier); + } + + public RootSupplier setIdentifierIndex( + Supplier> identifierIndexSupplier) { + return new RootSupplier(nodeIndexSupplier, identifierIndexSupplier); + } +} diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/DuplicatorTrie.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/DuplicatorTrie.java index 82cef096ce..0fcb40be36 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/DuplicatorTrie.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/DuplicatorTrie.java @@ -1,11 +1,12 @@ package io.github.douira.glsl_transformer.ast.query.index; -import java.util.*; +import repack.apache.commons.collections4.trie.PatriciaTrie; + +import java.util.Map; +import java.util.SortedMap; import java.util.function.Consumer; import java.util.stream.Stream; -import repack.apache.commons.collections4.trie.PatriciaTrie; - /** * Base class for trie variants that insert more than one entry per key. */ diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/ExternalDeclarationIndex.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/ExternalDeclarationIndex.java new file mode 100644 index 0000000000..780db856e1 --- /dev/null +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/ExternalDeclarationIndex.java @@ -0,0 +1,213 @@ +package io.github.douira.glsl_transformer.ast.query.index; + +import io.github.douira.glsl_transformer.ast.node.Identifier; +import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; +import io.github.douira.glsl_transformer.ast.node.declaration.*; +import io.github.douira.glsl_transformer.ast.node.external_declaration.*; +import io.github.douira.glsl_transformer.ast.node.type.specifier.FunctionPrototype; +import io.github.douira.glsl_transformer.ast.query.index.ExternalDeclarationIndex.DeclarationEntry; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +public class ExternalDeclarationIndex, I extends Map> + extends StringKeyedIndex { + public ExternalDeclarationIndex(I index, Supplier setFactory) { + super(index, setFactory); + } + + public static record DeclarationEntry(ExternalDeclaration declaration, ASTNode keyMember) { + } + + @Override + protected ExternalDeclaration getNode(DeclarationEntry entry) { + return entry.declaration; + } + + private void iterateKeyMembers(ExternalDeclaration node, BiConsumer memberConsumer) { + if (node instanceof DeclarationExternalDeclaration declarationExternalDeclaration) { + Declaration declaration = declarationExternalDeclaration.getDeclaration(); + if (declaration instanceof TypeAndInitDeclaration typeAndInitDeclaration) { + for (var member : typeAndInitDeclaration.getMembers()) { + memberConsumer.accept(member, member.getName().getName()); + } + } else if (declaration instanceof FunctionDeclaration functionDeclaration) { + memberConsumer.accept(node, functionDeclaration.getFunctionPrototype().getName().getName()); + } else if (declaration instanceof InterfaceBlockDeclaration interfaceBlockDeclaration) { + memberConsumer.accept(node, interfaceBlockDeclaration.getBlockName().getName()); + } else if (declaration instanceof VariableDeclaration variableDeclaration) { + for (var name : variableDeclaration.getNames()) { + memberConsumer.accept(name, name.getName()); + } + } + + // skips PrecisionDeclaration + } else if (node instanceof FunctionDefinition functionDefinition) { + memberConsumer.accept(node, functionDefinition.getFunctionPrototype().getName().getName()); + } else if (node instanceof ExtensionDirective extensionDirective) { + memberConsumer.accept(node, extensionDirective.getName()); + } else if (node instanceof CustomDirective customDirective) { + memberConsumer.accept(node, customDirective.getContent()); + } else if (node instanceof IncludeDirective includeDirective) { + memberConsumer.accept(node, includeDirective.getContent()); + } + + // skips PragmaDirective, LayoutDefaults, EmptyDeclaration + } + + private void addEntry(ExternalDeclaration node, ASTNode keyMember, String key) { + var set = index.get(key); + if (set == null) { + set = setFactory.get(); + index.put(key, set); + } + set.add(new DeclarationEntry(node, keyMember)); + } + + private void removeEntry(ExternalDeclaration node, ASTNode keyMember, String key) { + var set = index.get(key); + if (set == null) { + return; + } + set.remove(new DeclarationEntry(node, keyMember)); + if (set.isEmpty()) { + index.remove(key); + } + } + + @Override + public void add(ExternalDeclaration node) { + iterateKeyMembers(node, (keyMember, key) -> { + addEntry(node, keyMember, key); + }); + } + + @Override + public void remove(ExternalDeclaration node) { + iterateKeyMembers(node, (keyMember, key) -> { + removeEntry(node, keyMember, key); + }); + } + + private void iterateSubtreeEntries( + ASTNode node, + ASTNode nodeParent, + BiConsumer memberConsumer) { + // only some nodes are interesting since most other types of nodes don't + // influence the key of an external declaration entry + if (node == null) { + return; + } + + // if the modified node is a parent that can have children, they need to be + // iterated + if (node instanceof TypeAndInitDeclaration typeAndInitDeclaration) { + for (var member : typeAndInitDeclaration.getMembers()) { + memberConsumer.accept(member, member.getName().getName()); + } + return; + } + if (node instanceof VariableDeclaration variableDeclaration) { + for (var name : variableDeclaration.getNames()) { + memberConsumer.accept(name, name.getName()); + } + return; + } + + // from this point on, only a singe key member will be generated + + // the key member needs to be tracked separately since in the case of + // identifiers and declaration members changing the parent isn't the key member + // that's stored in the index since they're part of declarations that can have + // multiple entries, one for each member + String singleKey = null; + ASTNode keyMember = node; + if (node instanceof Identifier identifier) { + singleKey = identifier.getName(); + keyMember = node; + node = node.getParent(); + } + + // step up through the various admissable node types + if (node instanceof DeclarationMember) { + keyMember = node; + node = node.getParent(); + } + if (node instanceof FunctionPrototype) { + node = node.getParent(); + } + if (node instanceof FunctionDefinition) { + memberConsumer.accept(node, singleKey); + return; + } + if (node instanceof VariableDeclaration + || node instanceof TypeAndInitDeclaration) { + node = node.getParent(); + } else if (node instanceof FunctionDeclaration + || node instanceof InterfaceBlockDeclaration) { + node = node.getParent(); + + // set the parent back to the parent because for these types of declarations + // there are no specific key members and the ED is the key member itself + keyMember = node; + } + if (node instanceof DeclarationExternalDeclaration) { + memberConsumer.accept(keyMember, singleKey); + return; + } + } + + /** + * Run when some other node is added. This is necessary to keep track + * of the key members since their names determine the keys of the external + * declarations stored in this index. + * + * This method should only be called on the root node of the subtree being + * registered to avoid complication of repeatedly adding parts of the same + * subtree. + * + * @param subtreeRoot the node that was added, not an external declaration + */ + public void notifySubtreeAdd(ASTNode subtreeRoot) { + if (subtreeRoot instanceof ExternalDeclaration externalDeclaration) { + add(externalDeclaration); + } + + iterateSubtreeEntries(subtreeRoot, subtreeRoot.getParent(), (keyMember, key) -> { + addEntry(keyMember.getAncestor(ExternalDeclaration.class), keyMember, key); + }); + } + + /** + * Method to notify of a node being removed. For notification of a subtree + * change so that the external declaration index can be updated, see + * {@link #notifySubtreeAdd(ASTNode)}. + * + * @param subtreeRoot the node that was removed, not an external declaration + */ + public void notifySubtreeRemove(ASTNode subtreeRoot) { + if (subtreeRoot instanceof ExternalDeclaration externalDeclaration) { + remove(externalDeclaration); + } + + // when the node is unregistered, the parent has already been removed. The last + // parent (the one that was just removed) must be used instead. + iterateSubtreeEntries(subtreeRoot, subtreeRoot.getLastParent(), (keyMember, key) -> { + removeEntry(keyMember.getAncestor(ExternalDeclaration.class), keyMember, key); + }); + } + + public static ExternalDeclarationIndex, HashMap>> withOnlyExact() { + return new ExternalDeclarationIndex<>(new HashMap<>(), HashSet::new); + } + + public static ExternalDeclarationIndex, HashMap>> withOnlyExactOrdered() { + return new ExternalDeclarationIndex<>(new HashMap<>(), LinkedHashSet::new); + } + + public static > ExternalDeclarationIndex> withOnlyExact( + Supplier setFactory) { + return new ExternalDeclarationIndex<>(new HashMap<>(), setFactory); + } +} diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/IdentifierIndex.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/IdentifierIndex.java index b511f2f886..54fcfc748f 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/IdentifierIndex.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/IdentifierIndex.java @@ -1,99 +1,50 @@ package io.github.douira.glsl_transformer.ast.query.index; -import java.util.*; -import java.util.function.Supplier; -import java.util.stream.Stream; - import io.github.douira.glsl_transformer.ast.node.Identifier; -import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; -import io.github.douira.glsl_transformer.ast.node.expression.ReferenceExpression; -/** - * Indexes identifiers based on their content and enabled fast string queries. - */ -public class IdentifierIndex, I extends Map> implements Index { - public final I index; - public final Supplier setFactory; +import java.util.*; +import java.util.function.Supplier; +public class IdentifierIndex, I extends Map> + extends StringKeyedIndex { public IdentifierIndex(I index, Supplier setFactory) { - this.index = index; - this.setFactory = setFactory; + super(index, setFactory); + } + + @Override + protected Identifier getNode(Identifier entry) { + return entry; } @Override public void add(Identifier node) { - var name = node.getName(); - var set = index.get(name); + var key = node.getName(); + var set = index.get(key); if (set == null) { set = setFactory.get(); - index.put(name, set); + index.put(key, set); } set.add(node); } @Override public void remove(Identifier node) { - var name = node.getName(); - var set = index.get(name); + var key = node.getName(); + var set = index.get(key); if (set == null) { return; } set.remove(node); if (set.isEmpty()) { - index.remove(name); - } - } - - public Set get(String key) { - var result = index.get(key); - return result == null ? Collections.emptySet() : result; - } - - public Stream getStream(String key) { - var result = index.get(key); - return result == null ? Stream.empty() : result.stream(); - } - - public Stream getAncestors(String key, Class ancestorType) { - return getStream(key) - .map(id -> id.getAncestor(ancestorType)) - .filter(Objects::nonNull); - } - - public Stream getReferenceExpressions(String key) { - return getStream(key) - .map(id -> id.getAncestor(ReferenceExpression.class)) - .filter(Objects::nonNull); - } - - public ReferenceExpression getOneReferenceExpression(String key) { - return getReferenceExpressions(key).findFirst().orElse(null); - } - - public Identifier getOne(String key) { - var iterator = index.get(key).iterator(); - return iterator.hasNext() ? iterator.next() : null; - } - - public Identifier getUnique(String key) { - var set = index.get(key); - var resultSize = set == null ? 0 : set.size(); - if (resultSize != 1) { - throw new IllegalStateException("Expected exactly one identifier for key " + key + ", but got " + resultSize); + index.remove(key); } - return set.iterator().next(); - } - - public boolean has(String key) { - var result = index.get(key); - return result != null && !result.isEmpty(); } /** * Renames all identifiers with one name to have a new name. Since this deals * only with identifiers, this can be done by moving the set of identifiers * around as a whole. - * + * * @param oldName the old name * @param newName the new name * @return Whether anything was renamed @@ -124,6 +75,10 @@ public static IdentifierIndex, HashMap(new HashMap<>(), HashSet::new); } + public static IdentifierIndex, HashMap>> withOnlyExactOrdered() { + return new IdentifierIndex<>(new HashMap<>(), LinkedHashSet::new); + } + public static > IdentifierIndex> withOnlyExact( Supplier setFactory) { return new IdentifierIndex<>(new HashMap<>(), setFactory); diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/Index.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/Index.java index e602248f90..7058fabe1c 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/Index.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/Index.java @@ -1,21 +1,9 @@ package io.github.douira.glsl_transformer.ast.query.index; -import java.util.Set; -import java.util.function.*; -import java.util.stream.Stream; - import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; public interface Index { void add(N node); void remove(N node); - - public static Consumer> iterate(Consumer consumer) { - return set -> set.stream().forEach(consumer); - } - - public static Function, Stream> iterate(Function mapper) { - return set -> set.stream().map(mapper); - } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/PrefixExternalDeclarationIndex.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/PrefixExternalDeclarationIndex.java new file mode 100644 index 0000000000..91468b8d6e --- /dev/null +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/PrefixExternalDeclarationIndex.java @@ -0,0 +1,62 @@ +package io.github.douira.glsl_transformer.ast.query.index; + +import io.github.douira.glsl_transformer.ast.query.index.ExternalDeclarationIndex.DeclarationEntry; +import repack.apache.commons.collections4.trie.PatriciaTrie; + +import java.util.HashSet; +import java.util.Set; +import java.util.SortedMap; +import java.util.function.Supplier; +import java.util.stream.Stream; + +public class PrefixExternalDeclarationIndex, I extends PatriciaTrie> + extends ExternalDeclarationIndex implements PrefixQueryable { + + public PrefixExternalDeclarationIndex(I index, Supplier setFactory) { + super(index, setFactory); + } + + /** + * Returns a map of all entries with keys that start with the given key. Note + * that if the index is a special type of suffix/infix trie (like permuterm) + * then this won't make any sense. + * + * @param key the key to search for + * @return a map of all entries with keys that start with the given key + */ + public SortedMap prefixMap(String key) { + return index.prefixMap(key); + } + + @Override + public Stream prefixQuery(String key) { + return index.prefixMap(key).values().stream(); + } + + public static PrefixExternalDeclarationIndex, PrefixTrie, DeclarationEntry>> withPrefix() { + return new PrefixExternalDeclarationIndex<>(new PrefixTrie<>(), HashSet::new); + } + + public static PrefixExternalDeclarationIndex, PrefixSuffixTrie, DeclarationEntry>> withPrefixSuffix() { + return new PrefixExternalDeclarationIndex<>(new PrefixSuffixTrie<>(), HashSet::new); + } + + public static PrefixExternalDeclarationIndex, PermutermTrie, DeclarationEntry>> withPermuterm() { + return new PrefixExternalDeclarationIndex<>(new PermutermTrie<>(), HashSet::new); + } + + public static > PrefixExternalDeclarationIndex> withPrefix( + Supplier setFactory) { + return new PrefixExternalDeclarationIndex<>(new PrefixTrie<>(), setFactory); + } + + public static > PrefixExternalDeclarationIndex> withPrefixSuffix( + Supplier setFactory) { + return new PrefixExternalDeclarationIndex<>(new PrefixSuffixTrie<>(), setFactory); + } + + public static > PrefixExternalDeclarationIndex> withPermuterm( + Supplier setFactory) { + return new PrefixExternalDeclarationIndex<>(new PermutermTrie<>(), setFactory); + } +} diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/PrefixIdentifierIndex.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/PrefixIdentifierIndex.java index ed2af6182d..b083c10c3c 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/PrefixIdentifierIndex.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/PrefixIdentifierIndex.java @@ -24,11 +24,6 @@ public Stream prefixQuery(String key) { return index.prefixMap(key).values().stream(); } - @Override - public Stream prefixQueryFlat(String key) { - return prefixQuery(key).flatMap(Set::stream); - } - public static PrefixIdentifierIndex, PrefixTrie, Identifier>> withPrefix() { return new PrefixIdentifierIndex<>(new PrefixTrie<>(), HashSet::new); } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/PrefixQueryable.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/PrefixQueryable.java index 0cd1656812..db238e33e0 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/PrefixQueryable.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/PrefixQueryable.java @@ -4,8 +4,24 @@ import java.util.stream.Stream; public interface PrefixQueryable, E> { + /** + * Returns a stream of all results that are keyed with the given prefix. Note + * that if the index is a special type of suffix/infix trie (like permuterm) + * then this won't make any sense. + * + * @param prefix the prefix to search for + * @return a map of all entries with keys that start with the given key + */ Stream prefixQuery(String prefix); + /** + * Returns a stream of all results, but unwrapped from their sets, that are + * keyed with the given prefix. Note that if the index is a special type of + * suffix/infix trie (like permuterm) then this won't make any sense. + * + * @param prefix the prefix to search for + * @return a map of all entries with keys that start with the given key + */ default Stream prefixQueryFlat(String prefix) { return prefixQuery(prefix).flatMap(Set::stream); } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/index/StringKeyedIndex.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/StringKeyedIndex.java new file mode 100644 index 0000000000..6a925102e7 --- /dev/null +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/index/StringKeyedIndex.java @@ -0,0 +1,77 @@ +package io.github.douira.glsl_transformer.ast.query.index; + +import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; +import io.github.douira.glsl_transformer.ast.node.expression.ReferenceExpression; + +import java.util.Collections; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Stream; + +/** + * Indexes nodes based on their content and provides some utilities for querying them. + * + * @param The entry type stored in the index, the "value". + * @param The node type of the entry. + * @param The set type used to store entries. + * @param The index type used to store sets. + */ +public abstract class StringKeyedIndex, I extends Map> + implements Index { + public final I index; + public final Supplier setFactory; + + public StringKeyedIndex(I index, Supplier setFactory) { + this.index = index; + this.setFactory = setFactory; + } + + protected abstract N getNode(V entry); + + public Set get(String key) { + var result = index.get(key); + return result == null ? Collections.emptySet() : result; + } + + public Stream getStream(String key) { + var result = index.get(key); + return result == null ? Stream.empty() : result.stream(); + } + + public Stream getAncestors(String key, Class ancestorType) { + return getStream(key) + .map(value -> getNode(value).getAncestor(ancestorType)) + .filter(Objects::nonNull); + } + + public Stream getReferenceExpressions(String key) { + return getStream(key) + .map(value -> getNode(value).getAncestor(ReferenceExpression.class)) + .filter(Objects::nonNull); + } + + public ReferenceExpression getOneReferenceExpression(String key) { + return getReferenceExpressions(key).findFirst().orElse(null); + } + + public V getOne(String key) { + var iterator = index.get(key).iterator(); + return iterator.hasNext() ? iterator.next() : null; + } + + public V getUnique(String key) { + var set = index.get(key); + var resultSize = set == null ? 0 : set.size(); + if (resultSize != 1) { + throw new IllegalStateException("Expected exactly one result for key " + key + ", but got " + resultSize); + } + return set.iterator().next(); + } + + public boolean has(String key) { + var result = index.get(key); + return result != null && !result.isEmpty(); + } +} diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/match/AutoHintedMatcher.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/match/AutoHintedMatcher.java index 8fd47c9f18..9b622315c9 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/query/match/AutoHintedMatcher.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/match/AutoHintedMatcher.java @@ -1,13 +1,8 @@ package io.github.douira.glsl_transformer.ast.query.match; -import java.util.function.*; - -import repack.antlr.v4.runtime.ParserRuleContext; - -import io.github.douira.glsl_transformer.GLSLParser; import io.github.douira.glsl_transformer.ast.node.Identifier; import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; -import io.github.douira.glsl_transformer.ast.transform.ASTBuilder; +import io.github.douira.glsl_transformer.parser.ParseShape; /** * The auto-hinted matcher is a matcher that automatically determines the hint @@ -16,12 +11,6 @@ * {@link HintedMatcher} should be used instead. */ public class AutoHintedMatcher extends HintedMatcher { - public AutoHintedMatcher(String input, - Function parseMethod, - BiFunction visitMethod, String wildcardPrefix) { - super(input, parseMethod, visitMethod, wildcardPrefix, null); - } - public AutoHintedMatcher(N pattern, String wildcardPrefix) { super(pattern, wildcardPrefix, null); } @@ -30,18 +19,12 @@ public AutoHintedMatcher(N pattern) { super(pattern, null); } - public AutoHintedMatcher(String input, - Function parseMethod, - BiFunction visitMethod) { - super(input, parseMethod, visitMethod, null); - } - - public AutoHintedMatcher(String input, Function patternParser, String wildcardPrefix) { - super(input, patternParser, wildcardPrefix, null); + public AutoHintedMatcher(String input, ParseShape parseShape, String wildcardPrefix) { + super(input, parseShape, wildcardPrefix, null); } - public AutoHintedMatcher(String input, Function patternParser) { - super(input, patternParser, null); + public AutoHintedMatcher(String input, ParseShape parseShape) { + super(input, parseShape, null); } private void determineHint() { diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/match/HintedMatcher.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/match/HintedMatcher.java index 3f85485fa1..ce6219d57c 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/query/match/HintedMatcher.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/match/HintedMatcher.java @@ -1,12 +1,7 @@ package io.github.douira.glsl_transformer.ast.query.match; -import java.util.function.*; - -import repack.antlr.v4.runtime.ParserRuleContext; - -import io.github.douira.glsl_transformer.GLSLParser; import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; -import io.github.douira.glsl_transformer.ast.transform.ASTBuilder; +import io.github.douira.glsl_transformer.parser.ParseShape; /** * A hinted matcher contains an additional string that can be used to find @@ -16,12 +11,6 @@ public class HintedMatcher extends Matcher { protected String hint; - public HintedMatcher(String input, Function parseMethod, - BiFunction visitMethod, String wildcardPrefix, String hint) { - super(input, parseMethod, visitMethod, wildcardPrefix); - this.hint = hint; - } - public HintedMatcher(N pattern, String wildcardPrefix, String hint) { super(pattern, wildcardPrefix); this.hint = hint; @@ -32,19 +21,13 @@ public HintedMatcher(N pattern, String hint) { this.hint = hint; } - public HintedMatcher(String input, Function parseMethod, - BiFunction visitMethod, String hint) { - super(input, parseMethod, visitMethod); - this.hint = hint; - } - - public HintedMatcher(String input, Function patternParser, String wildcardPrefix, String hint) { - super(input, patternParser, wildcardPrefix); + public HintedMatcher(String input, ParseShape parseShape, String wildcardPrefix, String hint) { + super(input, parseShape, wildcardPrefix); this.hint = hint; } - public HintedMatcher(String input, Function patternParser, String hint) { - super(input, patternParser); + public HintedMatcher(String input, ParseShape parseShape, String hint) { + super(input, parseShape); this.hint = hint; } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/query/match/Matcher.java b/src/main/java/io/github/douira/glsl_transformer/ast/query/match/Matcher.java index f21667a7fe..fa976039fa 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/query/match/Matcher.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/query/match/Matcher.java @@ -1,20 +1,11 @@ package io.github.douira.glsl_transformer.ast.query.match; import java.util.*; -import java.util.function.*; +import java.util.function.Predicate; -import repack.antlr.v4.runtime.ParserRuleContext; - -import io.github.douira.glsl_transformer.GLSLParser; -import io.github.douira.glsl_transformer.GLSLParser.*; -import io.github.douira.glsl_transformer.ast.node.TranslationUnit; import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; -import io.github.douira.glsl_transformer.ast.node.expression.Expression; -import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration; -import io.github.douira.glsl_transformer.ast.node.statement.Statement; -import io.github.douira.glsl_transformer.ast.transform.*; import io.github.douira.glsl_transformer.ast.traversal.*; -import io.github.douira.glsl_transformer.parser.EnhancedParser; +import io.github.douira.glsl_transformer.parser.ParseShape; /** * Instances of the matcher can match a node against a stored pattern. This @@ -57,72 +48,14 @@ public Matcher(N pattern) { this(pattern, null); } - /** - * Creates a new matcher that matches the pattern parsed from the given string, - * parser method and visitor method. There is also a given wildcard prefix. - * - * @param The type of the parser rule context - * @param input The string to parse - * @param parseMethod The parser method to use - * @param visitMethod The build visitor method to use - * @param wildcardPrefix The wildcard prefix - */ - public Matcher(String input, - Function parseMethod, - BiFunction visitMethod, - String wildcardPrefix) { - this(ASTBuilder.build( - EnhancedParser.getInternalInstance().parse(input, parseMethod), - visitMethod), - wildcardPrefix); - } - - /** - * Creates a new matcher that matches the pattern parsed from the given string, - * parser method and visitor method. There is no wildcard prefix. - * - * @param The type of the parser rule context - * @param input The string to parse - * @param parseMethod The parser method to use - * @param visitMethod The build visitor method to use - */ - public Matcher(String input, - Function parseMethod, - BiFunction visitMethod) { - this(input, parseMethod, visitMethod, null); + public Matcher(String input, ParseShape parseShape, String wildcardPrefix) { + this(parseShape._parseNodeSeparateInternal(input), wildcardPrefix); } - public Matcher(String input, Function patternParser, String wildcardPrefix) { - this(patternParser.apply(input), wildcardPrefix); + public Matcher(String input, ParseShape parseShape) { + this(input, parseShape, null); } - public Matcher(String input, Function patternParser) { - this(input, patternParser, null); - } - - private static Function makePatternParser( - Class ruleType, - Function parseMethod, - BiFunction visitMethod) { - return input -> ASTParser.getInternalInstance().parseNodeSeparate(input, ruleType, parseMethod, visitMethod); - } - - public static final Function translationUnitPattern = makePatternParser( - TranslationUnitContext.class, - GLSLParser::translationUnit, ASTBuilder::visitTranslationUnit); - - public static final Function externalDeclarationPattern = makePatternParser( - ExternalDeclarationContext.class, - GLSLParser::externalDeclaration, ASTBuilder::visitExternalDeclaration); - - public static final Function expressionPattern = makePatternParser( - ExpressionContext.class, - GLSLParser::expression, ASTBuilder::visitExpression); - - public static final Function statementPattern = makePatternParser( - StatementContext.class, - GLSLParser::statement, ASTBuilder::visitStatement); - private ASTVisitor matchVisitor = new ASTVoidVisitor() { @Override public Void visit(ASTNode node) { diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTBuilder.java b/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTBuilder.java index 7f733343d9..ffcdeae6d0 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTBuilder.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTBuilder.java @@ -1,14 +1,9 @@ package io.github.douira.glsl_transformer.ast.transform; -import java.util.*; -import java.util.function.*; -import java.util.regex.*; - -import repack.antlr.v4.runtime.*; -import repack.antlr.v4.runtime.tree.*; - -import io.github.douira.glsl_transformer.*; +import io.github.douira.glsl_transformer.GLSLLexer; +import io.github.douira.glsl_transformer.GLSLParser; import io.github.douira.glsl_transformer.GLSLParser.*; +import io.github.douira.glsl_transformer.GLSLParserBaseVisitor; import io.github.douira.glsl_transformer.ast.node.*; import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; import io.github.douira.glsl_transformer.ast.node.declaration.*; @@ -19,23 +14,46 @@ import io.github.douira.glsl_transformer.ast.node.external_declaration.*; import io.github.douira.glsl_transformer.ast.node.external_declaration.ExtensionDirective.ExtensionBehavior; import io.github.douira.glsl_transformer.ast.node.external_declaration.LayoutDefaults.LayoutMode; -import io.github.douira.glsl_transformer.ast.node.external_declaration.PragmaDirective.*; -import io.github.douira.glsl_transformer.ast.node.statement.*; -import io.github.douira.glsl_transformer.ast.node.statement.loop.*; -import io.github.douira.glsl_transformer.ast.node.statement.selection.*; +import io.github.douira.glsl_transformer.ast.node.external_declaration.PragmaDirective.PragmaState; +import io.github.douira.glsl_transformer.ast.node.external_declaration.PragmaDirective.PragmaType; +import io.github.douira.glsl_transformer.ast.node.statement.CompoundStatement; +import io.github.douira.glsl_transformer.ast.node.statement.Statement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.DoWhileLoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.ForLoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.WhileLoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.selection.SelectionStatement; +import io.github.douira.glsl_transformer.ast.node.statement.selection.SwitchStatement; import io.github.douira.glsl_transformer.ast.node.statement.terminal.*; import io.github.douira.glsl_transformer.ast.node.type.FullySpecifiedType; -import io.github.douira.glsl_transformer.ast.node.type.initializer.*; +import io.github.douira.glsl_transformer.ast.node.type.initializer.ExpressionInitializer; +import io.github.douira.glsl_transformer.ast.node.type.initializer.Initializer; +import io.github.douira.glsl_transformer.ast.node.type.initializer.NestedInitializer; import io.github.douira.glsl_transformer.ast.node.type.qualifier.*; import io.github.douira.glsl_transformer.ast.node.type.qualifier.InterpolationQualifier.InterpolationType; import io.github.douira.glsl_transformer.ast.node.type.qualifier.PrecisionQualifier.PrecisionLevel; import io.github.douira.glsl_transformer.ast.node.type.qualifier.StorageQualifier.StorageType; import io.github.douira.glsl_transformer.ast.node.type.specifier.*; import io.github.douira.glsl_transformer.ast.node.type.specifier.BuiltinFixedTypeSpecifier.BuiltinType; -import io.github.douira.glsl_transformer.ast.node.type.struct.*; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructBody; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructDeclarator; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructMember; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructSpecifier; import io.github.douira.glsl_transformer.ast.query.Root; import io.github.douira.glsl_transformer.util.Type; import io.github.douira.glsl_transformer.util.Type.NumberType; +import repack.antlr.v4.runtime.BufferedTokenStream; +import repack.antlr.v4.runtime.ParserRuleContext; +import repack.antlr.v4.runtime.Token; +import repack.antlr.v4.runtime.tree.ParseTree; +import repack.antlr.v4.runtime.tree.TerminalNode; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.LinkedList; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * The AST builder is a visitor of the parse tree (not an AST visitor) that @@ -57,76 +75,60 @@ public static void unsetTokenStream() { ASTBuilder.tokenStream = null; } - /** - * Builds an AST from the given parse tree with a new root. - * - * @param ctx The parse tree - * @return The built AST - */ - public static ASTNode build(ParseTree ctx) { - return Root.indexNodes(() -> buildInternal(ctx)); - } - /** * Builds an AST from the given parse tree with the given root. - * + * * @param rootInstance The root instance * @param ctx The parse tree * @return The built AST */ public static ASTNode build(Root rootInstance, ParseTree ctx) { - return Root.indexNodes(rootInstance, () -> buildInternal(ctx)); + return rootInstance.indexNodes(() -> buildInternal(ctx)); } /** - * Builds an AST of a specific type from the given parse tree with a new root. - * - * @param The type of the parse tree - * @param The type of the AST node - * @param ctx The parse tree - * @param visitMethod The build method reference to this class + * Builds an AST of a specific type from the given parse tree with a given root. + * + * @param The type of the parse tree + * @param The type of the AST node + * @param rootInstance The root instance + * @param ctx The parse tree + * @param visitMethod The build method reference to this class * @return The built AST */ - public static N build( - T ctx, - BiFunction visitMethod) { - return Root.indexNodes(() -> buildInternal(ctx, visitMethod)); - } - public static N build( Root rootInstance, T ctx, BiFunction visitMethod) { - return Root.indexNodes(rootInstance, () -> buildInternal(ctx, visitMethod)); + return rootInstance.indexNodes(() -> buildInternal(ctx, visitMethod)); } /** - * Builds a subtree that has the same root as the given AST node. - * - * @param parentTreeMember The parent tree member - * @param ctx The parse tree + * Builds a subtree with the given root. + * + * @param rootInstance The root instance + * @param ctx The parse tree * @return The built AST */ - public static ASTNode buildSubtree(ASTNode parentTreeMember, ParseTree ctx) { - return Root.indexNodes(parentTreeMember, () -> buildInternal(ctx)); + public static ASTNode buildSubtree(Root rootInstance, ParseTree ctx) { + return rootInstance.indexNodes(() -> buildInternal(ctx)); } /** - * Builds a subtree of a specific type that has the same root as the given AST - * node. - * - * @param The type of the parse tree - * @param The type of the AST node - * @param parentTreeMember The parent tree member - * @param ctx The parse tree - * @param visitMethod The build method reference to this class + * Builds a subtree of a specific type with a given root instance. + * + * @param The type of the parse tree + * @param The type of the AST node + * @param rootInstance The root instance + * @param ctx The parse tree + * @param visitMethod The build method reference to this class * @return The built AST */ public static N buildSubtree( - ASTNode parentTreeMember, + Root rootInstance, T ctx, BiFunction visitMethod) { - return Root.indexNodes(parentTreeMember, () -> buildInternal(ctx, visitMethod)); + return rootInstance.indexNodes(() -> buildInternal(ctx, visitMethod)); } private static ASTNode buildInternal(ParseTree ctx) { @@ -779,7 +781,7 @@ public VariableDeclaration visitVariableDeclaration(VariableDeclarationContext c @Override public Initializer visitInitializer(InitializerContext ctx) { - var expressionContext = ctx.expression(); + var expressionContext = ctx.finiteExpression(); if (expressionContext != null) { return new ExpressionInitializer(visitExpression(expressionContext)); } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTInjectionPoint.java b/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTInjectionPoint.java index 24bb1515a7..e2f5fcc21f 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTInjectionPoint.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTInjectionPoint.java @@ -1,11 +1,14 @@ package io.github.douira.glsl_transformer.ast.transform; -import java.util.function.Predicate; - import io.github.douira.glsl_transformer.ast.node.TranslationUnit; -import io.github.douira.glsl_transformer.ast.node.external_declaration.*; +import io.github.douira.glsl_transformer.ast.node.external_declaration.DeclarationExternalDeclaration; +import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration; +import io.github.douira.glsl_transformer.ast.node.external_declaration.FunctionDefinition; +import io.github.douira.glsl_transformer.ast.node.external_declaration.LayoutDefaults; import io.github.douira.glsl_transformer.util.ExcludeFromJacocoGeneratedReport; +import java.util.function.Predicate; + public enum ASTInjectionPoint { /** * The first index. diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTParser.java b/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTParser.java index 5b1f816b4f..f780c10729 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTParser.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTParser.java @@ -1,27 +1,32 @@ package io.github.douira.glsl_transformer.ast.transform; -import java.util.*; -import java.util.function.*; - -import repack.antlr.v4.runtime.*; - -import io.github.douira.glsl_transformer.*; -import io.github.douira.glsl_transformer.GLSLParser.*; +import io.github.douira.glsl_transformer.GLSLLexer; +import io.github.douira.glsl_transformer.GLSLParser; +import io.github.douira.glsl_transformer.GLSLParser.TranslationUnitContext; import io.github.douira.glsl_transformer.ast.data.TypedTreeCache; +import io.github.douira.glsl_transformer.ast.node.Identifier; import io.github.douira.glsl_transformer.ast.node.TranslationUnit; import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration; import io.github.douira.glsl_transformer.ast.node.statement.Statement; -import io.github.douira.glsl_transformer.ast.query.EmptyRoot; -import io.github.douira.glsl_transformer.parser.*; +import io.github.douira.glsl_transformer.ast.query.Root; +import io.github.douira.glsl_transformer.ast.query.RootSupplier; +import io.github.douira.glsl_transformer.parser.CachingParser; +import io.github.douira.glsl_transformer.parser.EnhancedParser; import io.github.douira.glsl_transformer.parser.EnhancedParser.ParsingStrategy; +import io.github.douira.glsl_transformer.parser.ParseShape; +import io.github.douira.glsl_transformer.parser.ParserInterface; import io.github.douira.glsl_transformer.token_filter.TokenFilter; +import repack.antlr.v4.runtime.ParserRuleContext; + +import java.util.ArrayList; +import java.util.List; public class ASTParser implements ParserInterface { private static ASTParser INSTANCE; - public static ASTParser getInternalInstance() { + public static ASTParser _getInternalInstance() { if (INSTANCE == null) { INSTANCE = new ASTParser(); } @@ -59,7 +64,7 @@ public void setParseCacheSizeAndClear(int size) { * generated ASTs. If set to ALL_EXCLUDING_TRANSLATION_UNIT, the parser will * cache all generated ASTs except for the TranslationUnit. If set to NONE, the * parser will cache nothing. - * + * * @param astCacheStrategy the AST cache strategy */ public void setASTCacheStrategy(ASTCacheStrategy astCacheStrategy) { @@ -70,7 +75,7 @@ public void setASTCacheStrategy(ASTCacheStrategy astCacheStrategy) { * Sets the parsing cache strategy. If set to ALL, the parser will cache all * parsed strings. If set to NONE, the parser will cache nothing. Only * influences how the CST is parsed from the input and not the AST. - * + * * @param parsingCacheStrategy the parsing cache strategy */ public void setParsingCacheStrategy(ParsingCacheStrategy parsingCacheStrategy) { @@ -81,7 +86,7 @@ public void setParsingCacheStrategy(ParsingCacheStrategy parsingCacheStrategy) { * Sets whether the AST parser should handle line directives. If set to true, * the parser will parse line directives and add them to the AST. If set to * false, the parser will ignore line directives and not add them to the AST. - * + * * @param parseLineDirectives whether the parser should parse line directives */ public void setParseLineDirectives(boolean parseLineDirectives) { @@ -135,16 +140,38 @@ private void unsetBuilderTokenStream() { } } + private class EmptyRoot extends Root { + public EmptyRoot() { + super(null, null, null); + } + + @Override + public void registerIdentifierRename(Identifier identifier) { + } + + @Override + public void registerNode(ASTNode node, boolean isSubtreeRoot) { + } + + @Override + public void unregisterIdentifierRename(Identifier identifier) { + } + + @Override + public void unregisterNode(ASTNode node, boolean isSubtreeRoot) { + } + } + @SuppressWarnings("unchecked") - private N parseNodeCachedUncloned(String input, - Class ruleType, - Function parseMethod, - BiFunction visitMethod) { - return (N) buildCache.cachedGet(input, ruleType, + private N parseNodeCachedUncloned( + String input, ParseShape parseShape) { + return (N) buildCache.cachedGet(input, + parseShape.ruleType, () -> { try { setBuilderTokenStream(); - return ASTBuilder.build(new EmptyRoot(), parser.parse(input, ruleType, parseMethod), visitMethod); + return ASTBuilder.build(new EmptyRoot(), + parser.parse(input, parseShape), parseShape.visitMethod); } finally { unsetBuilderTokenStream(); } @@ -153,120 +180,84 @@ private N parseNodeCachedUnclon @SuppressWarnings("unchecked") // consistent use of the cache results in the same type public N parseNode( - String input, - ASTNode parentTreeMember, - Class ruleType, - Function parseMethod, - BiFunction visitMethod) throws RecognitionException { - if (ruleType == TranslationUnitContext.class) { - throw new IllegalArgumentException("Translation units may not be parsed into another node, that makes no sense."); - } - - if (astCacheStrategy == ASTCacheStrategy.NONE) { + Root rootInstance, + ParseShape parseShape, + String input) { + if (astCacheStrategy == ASTCacheStrategy.NONE + || astCacheStrategy == ASTCacheStrategy.ALL_EXCLUDING_TRANSLATION_UNIT + && parseShape.ruleType == TranslationUnitContext.class) { try { setBuilderTokenStream(); - return ASTBuilder.buildSubtree(parentTreeMember, parser.parse(input, ruleType, parseMethod), visitMethod); + return ASTBuilder.buildSubtree( + rootInstance, parser.parse(input, parseShape), parseShape.visitMethod); } finally { unsetBuilderTokenStream(); } } else { // cache and possibly build, always clone to return new trees - return (N) parseNodeCachedUncloned(input, ruleType, parseMethod, visitMethod) - .cloneInto(parentTreeMember); + return (N) parseNodeCachedUncloned(input, parseShape).cloneInto(rootInstance); } } - @SuppressWarnings("unchecked") // consistent use of the cache results in the same type public N parseNodeSeparate( - String input, - Class ruleType, - Function parseMethod, - BiFunction visitMethod) throws RecognitionException { - if (astCacheStrategy == ASTCacheStrategy.NONE - || astCacheStrategy == ASTCacheStrategy.ALL_EXCLUDING_TRANSLATION_UNIT - && ruleType == TranslationUnitContext.class) { - try { - setBuilderTokenStream(); - return ASTBuilder.build(parser.parse(input, ruleType, parseMethod), visitMethod); - } finally { - unsetBuilderTokenStream(); - } - } else { - return (N) parseNodeCachedUncloned(input, ruleType, parseMethod, visitMethod) - .cloneSeparate(); - } + RootSupplier rootSupplier, + ParseShape parseShape, + String input) { + return parseNode(rootSupplier.get(), parseShape, input); + } + + public TranslationUnit parseTranslationUnit(Root rootInstance, String input) { + return parseNode(rootInstance, ParseShape.TRANSLATION_UNIT, input); } - public TranslationUnit parseTranslationUnit(String input) throws RecognitionException { - return parseNodeSeparate(input, - TranslationUnitContext.class, - GLSLParser::translationUnit, - ASTBuilder::visitTranslationUnit); + public ExternalDeclaration parseExternalDeclaration(Root rootInstance, String input) { + return parseNode(rootInstance, ParseShape.EXTERNAL_DECLARATION, input); } - public ExternalDeclaration parseExternalDeclaration(ASTNode treeMember, String input) - throws RecognitionException { - return parseNode(input, treeMember, - ExternalDeclarationContext.class, - GLSLParser::externalDeclaration, - ASTBuilder::visitExternalDeclaration); + public Expression parseExpression(Root rootInstance, String input) { + return parseNode(rootInstance, ParseShape.EXPRESSION, input); } - public Expression parseExpression(ASTNode treeMember, String input) throws RecognitionException { - return parseNode(input, treeMember, - ExpressionContext.class, - GLSLParser::expression, - ASTBuilder::visitExpression); + public Statement parseStatement(Root rootInstance, String input) { + return parseNode(rootInstance, ParseShape.STATEMENT, input); } - public Statement parseStatement(ASTNode treeMember, String input) throws RecognitionException { - return parseNode(input, treeMember, - StatementContext.class, - GLSLParser::statement, - ASTBuilder::visitStatement); + public TranslationUnit parseTranslationUnit(RootSupplier rootSupplier, String input) { + return parseTranslationUnit(rootSupplier.get(), input); } - public ExternalDeclaration parseSeparateExternalDeclaration(String input) throws RecognitionException { - return parseNodeSeparate(input, - ExternalDeclarationContext.class, - GLSLParser::externalDeclaration, - ASTBuilder::visitExternalDeclaration); + public ExternalDeclaration parseExternalDeclaration(RootSupplier rootSupplier, String input) { + return parseExternalDeclaration(rootSupplier.get(), input); } - public Expression parseSeparateExpression(String input) throws RecognitionException { - return parseNodeSeparate(input, - ExpressionContext.class, - GLSLParser::expression, - ASTBuilder::visitExpression); + public Expression parseExpression(RootSupplier rootSupplier, String input) { + return parseExpression(rootSupplier.get(), input); } - public Statement parseSeparateStatement(String input) throws RecognitionException { - return parseNodeSeparate(input, - StatementContext.class, - GLSLParser::statement, - ASTBuilder::visitStatement); + public Statement parseStatement(RootSupplier rootSupplier, String input) { + return parseStatement(rootSupplier.get(), input); } - public List parseExternalDeclarations(ASTNode treeMember, String... inputs) { + public List parseExternalDeclarations(Root rootInstance, String... inputs) { var nodes = new ArrayList(inputs.length); for (var input : inputs) { - nodes.add(parseExternalDeclaration(treeMember, input)); + nodes.add(parseExternalDeclaration(rootInstance, input)); } return nodes; } - public List parseExpression(ASTNode treeMember, String... inputs) { + public List parseExpression(Root rootInstance, String... inputs) { var nodes = new ArrayList(inputs.length); for (var input : inputs) { - nodes.add(parseExpression(treeMember, input)); + nodes.add(parseExpression(rootInstance, input)); } return nodes; } - public List parseStatements(ASTNode treeMember, String... inputs) { + public List parseStatements(Root rootInstance, String... inputs) { var nodes = new ArrayList(inputs.length); for (var input : inputs) { - nodes.add(parseStatement(treeMember, input)); + nodes.add(parseStatement(rootInstance, input)); } return nodes; } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTTransformer.java b/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTTransformer.java index 36cce1bf84..feb281cc7e 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTTransformer.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTTransformer.java @@ -1,8 +1,16 @@ package io.github.douira.glsl_transformer.ast.transform; +import io.github.douira.glsl_transformer.ast.node.TranslationUnit; +import io.github.douira.glsl_transformer.ast.node.expression.Expression; +import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration; +import io.github.douira.glsl_transformer.ast.node.statement.Statement; import io.github.douira.glsl_transformer.ast.print.PrintType; +import io.github.douira.glsl_transformer.ast.query.Root; +import io.github.douira.glsl_transformer.ast.query.RootSupplier; import io.github.douira.glsl_transformer.token_filter.TokenFilter; +import java.util.Objects; + /** * The ast transformer transforms some representation of an input and returns * the same kind of output. The implementations of this class determine how it @@ -11,8 +19,8 @@ public abstract class ASTTransformer extends ASTParser implements ParameterizedTransformer { private J jobParameters; - private static final PrintType defaultPrintType = PrintType.COMPACT; - private PrintType printType = defaultPrintType; + private PrintType printType = PrintType.COMPACT; + private RootSupplier rootSupplier = RootSupplier.DEFAULT; @Override public J getJobParameters() { @@ -24,6 +32,14 @@ public void setJobParameters(J parameters) { jobParameters = parameters; } + public PrintType getPrintType() { + return printType; + } + + public void setPrintType(PrintType printType) { + this.printType = printType; + } + @Override @SuppressWarnings("unchecked") public void setTokenFilter(TokenFilter tokenFilter) { @@ -31,11 +47,49 @@ public void setTokenFilter(TokenFilter tokenFilter) { ((TokenFilter) tokenFilter).setJobParametersSupplier(this::getJobParameters); } - public void setPrintType(PrintType printType) { - this.printType = printType; + public RootSupplier getRootSupplier() { + return rootSupplier; } - public PrintType getPrintType() { - return printType; + public void setRootSupplier(RootSupplier rootSupplier) { + Objects.requireNonNull(rootSupplier); + this.rootSupplier = rootSupplier; + } + + public Root supplyRoot() { + return rootSupplier.get(); + } + + @Override + public V transform(V input) { + return transform(rootSupplier, input); + } + + /** + * Transforms the given input and returns the result using a root supplier. This + * method adds the root supplier parameter so that downstream transformers can + * pass it on to the parser. This class implements the generic version of this + * method by calling this method with the stored root supplier. + * + * @param rootSupplier The root supplier to use + * @param input The input to transform + * @return The transformed input + */ + public abstract V transform(RootSupplier rootSupplier, V input); + + public TranslationUnit parseSeparateTranslationUnit(String input) { + return parseTranslationUnit(rootSupplier, input); + } + + public ExternalDeclaration parseSeparateExternalDeclaration(String input) { + return parseExternalDeclaration(rootSupplier, input); + } + + public Expression parseSeparateExpression(String input) { + return parseExpression(rootSupplier, input); + } + + public Statement parseSeparateStatement(String input) { + return parseStatement(rootSupplier, input); } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/transform/EnumASTTransformer.java b/src/main/java/io/github/douira/glsl_transformer/ast/transform/EnumASTTransformer.java index 2e44ab6b43..aac5ed555c 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/transform/EnumASTTransformer.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/transform/EnumASTTransformer.java @@ -1,10 +1,11 @@ package io.github.douira.glsl_transformer.ast.transform; -import java.util.EnumMap; -import java.util.function.*; - import io.github.douira.glsl_transformer.ast.node.TranslationUnit; +import java.util.EnumMap; +import java.util.function.Consumer; +import java.util.function.Supplier; + public class EnumASTTransformer> extends GroupedASTTransformer, EnumMap> { public EnumASTTransformer(Consumer> transformation, Class enumClass) { diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/transform/GroupedASTTransformer.java b/src/main/java/io/github/douira/glsl_transformer/ast/transform/GroupedASTTransformer.java index 4d0dc103f1..9cac55ed09 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/transform/GroupedASTTransformer.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/transform/GroupedASTTransformer.java @@ -1,12 +1,13 @@ package io.github.douira.glsl_transformer.ast.transform; -import java.util.Map; -import java.util.function.*; - -import repack.antlr.v4.runtime.RecognitionException; - import io.github.douira.glsl_transformer.ast.node.TranslationUnit; import io.github.douira.glsl_transformer.ast.print.ASTPrinter; +import io.github.douira.glsl_transformer.ast.query.RootSupplier; + +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Supplier; /** * The grouped AST transformer parses multiple strings stored in an arbitrarily @@ -66,12 +67,12 @@ public void setResultMapSupplier(Supplier resultMapSupplier) { } @Override - public M transform(Map items) throws RecognitionException { + public M transform(RootSupplier rootSupplier, Map items) { // parse all items var translationUnits = tuMapSupplier.get(); for (var entry : items.entrySet()) { var value = entry.getValue(); - translationUnits.put(entry.getKey(), value == null ? null : parseTranslationUnit(value)); + translationUnits.put(entry.getKey(), value == null ? null : parseTranslationUnit(rootSupplier, value)); } // transform them all at once diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/transform/ParameterizedTransformer.java b/src/main/java/io/github/douira/glsl_transformer/ast/transform/ParameterizedTransformer.java index b59d45c5e9..2efa32b27c 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/transform/ParameterizedTransformer.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/transform/ParameterizedTransformer.java @@ -1,9 +1,7 @@ package io.github.douira.glsl_transformer.ast.transform; -import repack.antlr.v4.runtime.RecognitionException; - public interface ParameterizedTransformer extends ParameterHolder, Transformer { - default V transform(V str, J parameters) throws RecognitionException { - return withJobParameters(parameters, () -> transform(str)); + default V transform(V input, J parameters) { + return withJobParameters(parameters, () -> transform(input)); } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/transform/SingleASTTransformer.java b/src/main/java/io/github/douira/glsl_transformer/ast/transform/SingleASTTransformer.java index ca9bc75842..1fcd307154 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/transform/SingleASTTransformer.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/transform/SingleASTTransformer.java @@ -2,11 +2,9 @@ import java.util.function.*; -import repack.antlr.v4.runtime.RecognitionException; - import io.github.douira.glsl_transformer.ast.node.TranslationUnit; import io.github.douira.glsl_transformer.ast.print.ASTPrinter; -import io.github.douira.glsl_transformer.ast.query.Root; +import io.github.douira.glsl_transformer.ast.query.*; import io.github.douira.glsl_transformer.util.TriConsumer; /** @@ -66,8 +64,8 @@ public static Consumer wrapTransformation( } @Override - public String transform(String str) throws RecognitionException { - var translationUnit = parseTranslationUnit(str); + public String transform(RootSupplier rootSupplier, String str) { + var translationUnit = parseTranslationUnit(rootSupplier, str); transformation.accept(translationUnit); return ASTPrinter.print(getPrintType(), translationUnit); } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/transform/Template.java b/src/main/java/io/github/douira/glsl_transformer/ast/transform/Template.java index 5f1c602737..8a1348f357 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/transform/Template.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/transform/Template.java @@ -7,7 +7,8 @@ import io.github.douira.glsl_transformer.ast.node.expression.Expression; import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration; import io.github.douira.glsl_transformer.ast.node.statement.Statement; -import io.github.douira.glsl_transformer.ast.query.Root; +import io.github.douira.glsl_transformer.ast.query.*; +import io.github.douira.glsl_transformer.parser.ParseShape; public class Template { private final Map> replacements = new HashMap<>(); @@ -34,21 +35,11 @@ public R getReplacement(R original) { return replacementSupplier == null ? null : (R) replacementSupplier.get(); } - @SuppressWarnings("unchecked") // all ASTNodes clone themselves with the right type - public N getSeparateInstance() { - return (N) source.cloneSeparate(); - } - @SuppressWarnings("unchecked") // all ASTNodes clone themselves with the right type public N getInstanceFor(Root root) { return (N) source.cloneInto(root); } - @SuppressWarnings("unchecked") // all ASTNodes clone themselves with the right type - public N getInstanceFor(ASTNode treeMember) { - return (N) source.cloneInto(treeMember); - } - public void supplyLocalReplacements(List replacements) { Objects.requireNonNull(replacements); if (replacements.size() < localReplacementsMarked) { @@ -68,51 +59,21 @@ public void supplyLocalReplacements(ASTNode... replacements) { supplyLocalReplacements(Arrays.asList(replacements)); } - public N getSeparateInstance(List localReplacements) { - supplyLocalReplacements(localReplacements); - return getSeparateInstance(); - } - public N getInstanceFor(Root root, List localReplacements) { supplyLocalReplacements(localReplacements); return getInstanceFor(root); } - public N getInstanceFor(ASTNode treeMember, List localReplacements) { - supplyLocalReplacements(localReplacements); - return getInstanceFor(treeMember); - } - - public N getSeparateInstance(ASTNode localReplacement) { - supplyLocalReplacements(localReplacement); - return getSeparateInstance(); - } - public N getInstanceFor(Root root, ASTNode localReplacement) { supplyLocalReplacements(localReplacement); return getInstanceFor(root); } - public N getInstanceFor(ASTNode treeMember, ASTNode localReplacement) { - supplyLocalReplacements(localReplacement); - return getInstanceFor(treeMember); - } - - public N getSeparateInstance(ASTNode... localReplacements) { - supplyLocalReplacements(localReplacements); - return getSeparateInstance(); - } - public N getInstanceFor(Root root, ASTNode... localReplacements) { supplyLocalReplacements(localReplacements); return getInstanceFor(root); } - public N getInstanceFor(ASTNode treeMember, ASTNode... localReplacements) { - supplyLocalReplacements(localReplacements); - return getInstanceFor(treeMember); - } - public void markLocalReplacement(ASTNode original) { final var index = localReplacementsMarked++; markReplacement(original, () -> localReplacements.get(index)); @@ -144,18 +105,18 @@ public void markReplacement(String tag, Class type, Sup @SuppressWarnings("unchecked") // all ASTNodes clone themselves with the right type public static Template ofCloned(N source) { - return new Template((N) source.cloneSeparate()); + return new Template((N) source.cloneInto(RootSupplier.supplyDefault())); } public static Template withExternalDeclaration(String input) { - return new Template<>(ASTParser.getInternalInstance().parseSeparateExternalDeclaration(input)); + return new Template<>(ParseShape.EXTERNAL_DECLARATION._parseNodeSeparateInternal(input)); } public static Template withStatement(String input) { - return new Template<>(ASTParser.getInternalInstance().parseSeparateStatement(input)); + return new Template<>(ParseShape.STATEMENT._parseNodeSeparateInternal(input)); } public static Template withExpression(String input) { - return new Template<>(ASTParser.getInternalInstance().parseSeparateExpression(input)); + return new Template<>(ParseShape.EXPRESSION._parseNodeSeparateInternal(input)); } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/transform/Transformer.java b/src/main/java/io/github/douira/glsl_transformer/ast/transform/Transformer.java index a2e7b822ec..db518ec289 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/transform/Transformer.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/transform/Transformer.java @@ -1,11 +1,9 @@ package io.github.douira.glsl_transformer.ast.transform; -import repack.antlr.v4.runtime.RecognitionException; - /** * A transformer takes a value, does something with it and returns a value of * the same type. It's similar to a {@code Passthrough}. */ public interface Transformer { - V transform(V str) throws RecognitionException; + V transform(V input); } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/transform/TriASTTransformer.java b/src/main/java/io/github/douira/glsl_transformer/ast/transform/TriASTTransformer.java index 9a634401f7..06a9d467e7 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/transform/TriASTTransformer.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/transform/TriASTTransformer.java @@ -3,8 +3,6 @@ import java.util.EnumMap; import java.util.function.Consumer; -import repack.antlr.v4.runtime.RecognitionException; - import io.github.douira.glsl_transformer.ast.node.TranslationUnit; import io.github.douira.glsl_transformer.util.*; @@ -97,26 +95,24 @@ public void setEnumType(Class enumClass) { throw new UnsupportedOperationException("The tri enum map types may not be changed."); } - public EnumMap transform(String a, String b, String c) - throws RecognitionException { + public EnumMap transform(String a, String b, String c) { var items = new EnumMap(enumClass); items.put(aType, a); items.put(bType, b); items.put(cType, c); - return transform(items); + return transform(getRootSupplier(), items); } - public EnumMap transform(String a, String b, String c, J parameters) - throws RecognitionException { + public EnumMap transform(String a, String b, String c, J parameters) { return withJobParameters(parameters, () -> transform(a, b, c)); } - public Triple transform(Triple str) throws RecognitionException { + public Triple transform(Triple str) { var result = transform(str.a, str.b, str.c); return new Triple<>(result.get(aType), result.get(bType), result.get(cType)); } - public Triple transform(Triple str, J parameters) throws RecognitionException { + public Triple transform(Triple str, J parameters) { return withJobParameters(parameters, () -> transform(str)); } } diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTListener.java b/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTListener.java index 11e4498310..1970547f3a 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTListener.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTListener.java @@ -1,20 +1,38 @@ package io.github.douira.glsl_transformer.ast.traversal; -import io.github.douira.glsl_transformer.ast.node.*; +import io.github.douira.glsl_transformer.ast.node.IterationConditionInitializer; +import io.github.douira.glsl_transformer.ast.node.TranslationUnit; import io.github.douira.glsl_transformer.ast.node.declaration.*; import io.github.douira.glsl_transformer.ast.node.expression.*; import io.github.douira.glsl_transformer.ast.node.expression.binary.*; import io.github.douira.glsl_transformer.ast.node.expression.unary.*; -import io.github.douira.glsl_transformer.ast.node.external_declaration.*; -import io.github.douira.glsl_transformer.ast.node.statement.*; -import io.github.douira.glsl_transformer.ast.node.statement.loop.*; -import io.github.douira.glsl_transformer.ast.node.statement.selection.*; +import io.github.douira.glsl_transformer.ast.node.external_declaration.DeclarationExternalDeclaration; +import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration; +import io.github.douira.glsl_transformer.ast.node.external_declaration.FunctionDefinition; +import io.github.douira.glsl_transformer.ast.node.external_declaration.LayoutDefaults; +import io.github.douira.glsl_transformer.ast.node.statement.CompoundStatement; +import io.github.douira.glsl_transformer.ast.node.statement.ManyStatement; +import io.github.douira.glsl_transformer.ast.node.statement.Statement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.DoWhileLoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.ForLoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.LoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.WhileLoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.selection.SelectionStatement; +import io.github.douira.glsl_transformer.ast.node.statement.selection.SwitchStatement; import io.github.douira.glsl_transformer.ast.node.statement.terminal.*; import io.github.douira.glsl_transformer.ast.node.type.FullySpecifiedType; -import io.github.douira.glsl_transformer.ast.node.type.initializer.*; +import io.github.douira.glsl_transformer.ast.node.type.initializer.ExpressionInitializer; +import io.github.douira.glsl_transformer.ast.node.type.initializer.Initializer; +import io.github.douira.glsl_transformer.ast.node.type.initializer.NestedInitializer; import io.github.douira.glsl_transformer.ast.node.type.qualifier.*; -import io.github.douira.glsl_transformer.ast.node.type.specifier.*; -import io.github.douira.glsl_transformer.ast.node.type.struct.*; +import io.github.douira.glsl_transformer.ast.node.type.specifier.ArraySpecifier; +import io.github.douira.glsl_transformer.ast.node.type.specifier.FunctionPrototype; +import io.github.douira.glsl_transformer.ast.node.type.specifier.TypeReference; +import io.github.douira.glsl_transformer.ast.node.type.specifier.TypeSpecifier; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructBody; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructDeclarator; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructMember; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructSpecifier; /** * The AST listener interface has a method for entering and exiting each diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTVisitor.java b/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTVisitor.java index 57872ba386..686239d972 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTVisitor.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTVisitor.java @@ -1,20 +1,34 @@ package io.github.douira.glsl_transformer.ast.traversal; -import io.github.douira.glsl_transformer.ast.node.*; +import io.github.douira.glsl_transformer.ast.node.Identifier; +import io.github.douira.glsl_transformer.ast.node.IterationConditionInitializer; +import io.github.douira.glsl_transformer.ast.node.TranslationUnit; +import io.github.douira.glsl_transformer.ast.node.VersionStatement; import io.github.douira.glsl_transformer.ast.node.declaration.*; import io.github.douira.glsl_transformer.ast.node.expression.*; import io.github.douira.glsl_transformer.ast.node.expression.binary.*; import io.github.douira.glsl_transformer.ast.node.expression.unary.*; import io.github.douira.glsl_transformer.ast.node.external_declaration.*; -import io.github.douira.glsl_transformer.ast.node.statement.*; -import io.github.douira.glsl_transformer.ast.node.statement.loop.*; -import io.github.douira.glsl_transformer.ast.node.statement.selection.*; +import io.github.douira.glsl_transformer.ast.node.statement.CompoundStatement; +import io.github.douira.glsl_transformer.ast.node.statement.ManyStatement; +import io.github.douira.glsl_transformer.ast.node.statement.Statement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.DoWhileLoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.ForLoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.LoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.loop.WhileLoopStatement; +import io.github.douira.glsl_transformer.ast.node.statement.selection.SelectionStatement; +import io.github.douira.glsl_transformer.ast.node.statement.selection.SwitchStatement; import io.github.douira.glsl_transformer.ast.node.statement.terminal.*; import io.github.douira.glsl_transformer.ast.node.type.FullySpecifiedType; -import io.github.douira.glsl_transformer.ast.node.type.initializer.*; +import io.github.douira.glsl_transformer.ast.node.type.initializer.ExpressionInitializer; +import io.github.douira.glsl_transformer.ast.node.type.initializer.Initializer; +import io.github.douira.glsl_transformer.ast.node.type.initializer.NestedInitializer; import io.github.douira.glsl_transformer.ast.node.type.qualifier.*; import io.github.douira.glsl_transformer.ast.node.type.specifier.*; -import io.github.douira.glsl_transformer.ast.node.type.struct.*; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructBody; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructDeclarator; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructMember; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructSpecifier; /** * The AST visitor knows how to traverse the AST and visit each node. @@ -48,21 +62,21 @@ default R visitEmptyDeclaration(EmptyDeclaration node) { default R visitPragmaDirective(PragmaDirective node) { var result = visitData(node.stdGL); result = visitData(result, node.type); - result = visitData(result, node.customName); + result = visitData(result, node.getCustomName()); return visitData(result, node.state); } default R visitExtensionDirective(ExtensionDirective node) { - var result = visitData(superNodeTypeResult(), node.name); + var result = visitData(superNodeTypeResult(), node.getName()); return visitData(result, node.behavior); } default R visitCustomDirective(CustomDirective node) { - return visitData(node.content); + return visitData(node.getContent()); } default R visitIncludeDirective(IncludeDirective node) { - return visitData(node.content); + return visitData(node.getContent()); } default R visitDeclarationExternalDeclaration(DeclarationExternalDeclaration node) { diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTVoidVisitor.java b/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTVoidVisitor.java index 5738276163..699cbdc8d7 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTVoidVisitor.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTVoidVisitor.java @@ -1,6 +1,7 @@ package io.github.douira.glsl_transformer.ast.traversal; -import io.github.douira.glsl_transformer.ast.node.abstract_node.*; +import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; +import io.github.douira.glsl_transformer.ast.node.abstract_node.ListNode; public abstract class ASTVoidVisitor implements ASTVisitor { public void visitVoid(ASTNode node) { diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTWalker.java b/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTWalker.java index ddb94a2550..5473141176 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTWalker.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/traversal/ASTWalker.java @@ -1,6 +1,7 @@ package io.github.douira.glsl_transformer.ast.traversal; -import io.github.douira.glsl_transformer.ast.node.abstract_node.*; +import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; +import io.github.douira.glsl_transformer.ast.node.abstract_node.InnerASTNode; public class ASTWalker extends ASTBaseVisitor { protected ASTListener listener; diff --git a/src/main/java/io/github/douira/glsl_transformer/ast/traversal/GeneralASTVisitor.java b/src/main/java/io/github/douira/glsl_transformer/ast/traversal/GeneralASTVisitor.java index 160231bdce..a3602114c3 100644 --- a/src/main/java/io/github/douira/glsl_transformer/ast/traversal/GeneralASTVisitor.java +++ b/src/main/java/io/github/douira/glsl_transformer/ast/traversal/GeneralASTVisitor.java @@ -1,8 +1,9 @@ package io.github.douira.glsl_transformer.ast.traversal; -import java.util.List; +import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; +import io.github.douira.glsl_transformer.ast.node.abstract_node.ListNode; -import io.github.douira.glsl_transformer.ast.node.abstract_node.*; +import java.util.List; public interface GeneralASTVisitor { default R startVisit(ASTNode node) { diff --git a/src/main/java/io/github/douira/glsl_transformer/parser/CachingParser.java b/src/main/java/io/github/douira/glsl_transformer/parser/CachingParser.java index 9655aad6e4..66a6f78b95 100644 --- a/src/main/java/io/github/douira/glsl_transformer/parser/CachingParser.java +++ b/src/main/java/io/github/douira/glsl_transformer/parser/CachingParser.java @@ -1,14 +1,10 @@ package io.github.douira.glsl_transformer.parser; -import java.util.function.Function; - -import repack.antlr.v4.runtime.*; - -import io.github.douira.glsl_transformer.GLSLParser; -import io.github.douira.glsl_transformer.GLSLParser.TranslationUnitContext; import io.github.douira.glsl_transformer.ast.data.TypedTreeCache; import io.github.douira.glsl_transformer.ast.transform.ASTBuilder; import io.github.douira.glsl_transformer.token_filter.TokenFilter; +import repack.antlr.v4.runtime.BufferedTokenStream; +import repack.antlr.v4.runtime.ParserRuleContext; /** * The caching parser extends the enhanced parser and returns previous parse @@ -45,17 +41,11 @@ public void setParseCacheSizeAndClear(int size) { parseCache = new TypedTreeCache<>(size); } - @Override - public TranslationUnitContext parse(String str) { - return parse(str, TranslationUnitContext.class, GLSLParser::translationUnit); - } - @Override public C parse( String str, - Class ruleType, - Function parseMethod) { - return parse(str, null, ruleType, parseMethod); + ParseShape parseShape) { + return parse(str, null, parseShape); } @Override @@ -63,11 +53,10 @@ public C parse( public C parse( String str, ParserRuleContext parent, - Class ruleType, - Function parseMethod) { - var result = parseCache.cachedGet(str, ruleType, + ParseShape parseShape) { + var result = parseCache.cachedGet(str, parseShape.ruleType, () -> { - var node = parse(str, parent, parseMethod); + var node = parse(str, parent, parseShape.parseMethod); return new CacheContents(node, getTokenStream()); }); if (result != null) { diff --git a/src/main/java/io/github/douira/glsl_transformer/parser/EnhancedParser.java b/src/main/java/io/github/douira/glsl_transformer/parser/EnhancedParser.java index 21463c73fa..43b9b95284 100644 --- a/src/main/java/io/github/douira/glsl_transformer/parser/EnhancedParser.java +++ b/src/main/java/io/github/douira/glsl_transformer/parser/EnhancedParser.java @@ -1,14 +1,15 @@ package io.github.douira.glsl_transformer.parser; -import java.util.function.*; - +import io.github.douira.glsl_transformer.GLSLLexer; +import io.github.douira.glsl_transformer.GLSLParser; +import io.github.douira.glsl_transformer.GLSLParser.TranslationUnitContext; +import io.github.douira.glsl_transformer.token_filter.TokenFilter; import repack.antlr.v4.runtime.*; import repack.antlr.v4.runtime.atn.PredictionMode; import repack.antlr.v4.runtime.misc.ParseCancellationException; -import io.github.douira.glsl_transformer.*; -import io.github.douira.glsl_transformer.GLSLParser.TranslationUnitContext; -import io.github.douira.glsl_transformer.token_filter.TokenFilter; +import java.util.function.BiConsumer; +import java.util.function.Function; /** * The enhanced parser does more than just parsing. It also does lexing, @@ -27,8 +28,6 @@ public void syntaxError( } } - private static EnhancedParser INSTANCE; - // initialized with null since they need an argument private final GLSLLexer lexer = new GLSLLexer(null); private final GLSLParser parser = new GLSLParser(null); @@ -77,7 +76,7 @@ public enum ParsingStrategy { /** * The last parsed tokens stream. - * + * * @see #input */ protected BufferedTokenStream tokenStream; @@ -96,12 +95,12 @@ public enum ParsingStrategy { * parsing any construct a parse tree containing error nodes. These nodes can * mess up transformation and printing. Do not expect anything to function * properly if an error was encountered during parsing. - * + * * Custom error handlers can be registered on the parser and lexer manually. For * example, an error handler similar to ConsoleErrorListener that allows * recovery and only collects the errors instead of printing them could be * created. - * + * * @param throwParseErrors If {@code true}, the parser throw any * parse errors encountered during parsing */ @@ -119,23 +118,12 @@ public void setThrowParseErrors(boolean throwParseErrors) { this.throwParseErrors = throwParseErrors; } - /** - * Gets the internal singleton instance of the parser. This should generally not - * be used by external library users. - */ - public static EnhancedParser getInternalInstance() { - if (INSTANCE == null) { - INSTANCE = new CachingParser(true); - } - return INSTANCE; - } - /** * Sets if the parser should be re-run in LL parsing mode if the SLL parsing * mode return an error. This is generally only necessary if it's important that * errors are only reported if there are actually errors. Keep in mind that LL * parsing mode is much slower than SLL. - * + * * @param parsingStrategy The parsing strategy to use */ public void setParsingStrategy(ParsingStrategy parsingStrategy) { @@ -163,7 +151,7 @@ public void setLLOnly() { * stream. However, the parser should not be used for parsing manually anyway. * The state and contents of the parser are set up correctly when the * transformation is performed. - * + * * {@inheritDoc} */ public GLSLParser getParser() { @@ -181,7 +169,7 @@ public BufferedTokenStream getTokenStream() { /** * Sets the token filter to use before parsing. It's placed between the lexer * and the token stream. - * + * * @param tokenFilter The new token filter */ public void setTokenFilter(TokenFilter tokenFilter) { @@ -190,17 +178,17 @@ public void setTokenFilter(TokenFilter tokenFilter) { /** * Parses a string as a translation unit. - * + * * @param str The string to parse * @return The parsed string as a translation unit parse tree */ public TranslationUnitContext parse(String str) { - return parse(str, GLSLParser::translationUnit); + return parse(str, ParseShape.TRANSLATION_UNIT); } /** * Parses a string using a parser method reference into a parse tree. - * + * * @param The type of the resulting parsed node * @param str The string to parse * @param parseMethod The parser method reference to use for parsing @@ -214,14 +202,13 @@ public C parse( public C parse( String str, - Class ruleType, - Function parseMethod) { - return parse(str, (ParserRuleContext) null, parseMethod); + ParseShape parseShape) { + return parse(str, (ParserRuleContext) null, parseShape.parseMethod); } /** * Parses a string using a parser method reference into a parse tree. - * + * * @param The type of the resulting parsed node * @param str The string to parse * @param parent The parent to attach to the parsed node @@ -238,16 +225,15 @@ public C parse( public C parse( String str, ParserRuleContext parent, - Class ruleType, - Function parseMethod) { - return parse(CharStreams.fromString(str), parent, parseMethod); + ParseShape parseShape) { + return parse(CharStreams.fromString(str), parent, parseShape.parseMethod); } /** * Parses an int stream (which is similar to a string) using a parser method * reference into a parse tree. This method exists so non-string streams can * also be parsed. - * + * * @param The type of the resulting parsed node * @param stream The int stream to parse * @param parent The parent to attach to the parsed node diff --git a/src/main/java/io/github/douira/glsl_transformer/parser/ExtendedParser.java b/src/main/java/io/github/douira/glsl_transformer/parser/ExtendedParser.java index c8f3be6b6e..9aec536415 100644 --- a/src/main/java/io/github/douira/glsl_transformer/parser/ExtendedParser.java +++ b/src/main/java/io/github/douira/glsl_transformer/parser/ExtendedParser.java @@ -1,6 +1,7 @@ package io.github.douira.glsl_transformer.parser; -import repack.antlr.v4.runtime.*; +import repack.antlr.v4.runtime.Parser; +import repack.antlr.v4.runtime.TokenStream; /** * This class is used as the base parser class in code generated by ANTLR. It @@ -11,7 +12,7 @@ public abstract class ExtendedParser extends Parser { /** * Creates a new extended parser. This is simply to fulfill the expected * constructor signature. - * + * * @param input The input token stream to parse */ public ExtendedParser(TokenStream input) { diff --git a/src/main/java/io/github/douira/glsl_transformer/parser/FilterTokenSource.java b/src/main/java/io/github/douira/glsl_transformer/parser/FilterTokenSource.java index 758ed458de..2223fd701a 100644 --- a/src/main/java/io/github/douira/glsl_transformer/parser/FilterTokenSource.java +++ b/src/main/java/io/github/douira/glsl_transformer/parser/FilterTokenSource.java @@ -1,8 +1,10 @@ package io.github.douira.glsl_transformer.parser; -import repack.antlr.v4.runtime.*; - import io.github.douira.glsl_transformer.token_filter.TokenFilter; +import repack.antlr.v4.runtime.CharStream; +import repack.antlr.v4.runtime.Token; +import repack.antlr.v4.runtime.TokenFactory; +import repack.antlr.v4.runtime.TokenSource; /** * The filter token source wraps another token source but reads tokens from it @@ -15,7 +17,7 @@ public class FilterTokenSource implements TokenSource { /** * Creates a new filtering token source with a given token source to wrap. - * + * * @param tokenSource The real token source to get tokens from */ public FilterTokenSource(TokenSource tokenSource) { @@ -26,7 +28,7 @@ public FilterTokenSource(TokenSource tokenSource) { * Sets the token filter on this filtering token source wrapper. Set to * {@code null} to effectively disable any manipulation of the tokens generated * by the contained token source. - * + * * @param tokenFilter The new token filter */ public void setTokenFilter(TokenFilter tokenFilter) { @@ -47,7 +49,7 @@ public void resetState() { * Uses {@link repack.antlr.v4.runtime.TokenSource#nextToken()} on the real token * source to filter to get tokens and then filters them with the contained token * filter if there is one. - * + * * {@inheritDoc} */ @Override diff --git a/src/main/java/io/github/douira/glsl_transformer/parser/ParseShape.java b/src/main/java/io/github/douira/glsl_transformer/parser/ParseShape.java new file mode 100644 index 0000000000..2852494363 --- /dev/null +++ b/src/main/java/io/github/douira/glsl_transformer/parser/ParseShape.java @@ -0,0 +1,64 @@ +package io.github.douira.glsl_transformer.parser; + +import io.github.douira.glsl_transformer.GLSLParser; +import io.github.douira.glsl_transformer.GLSLParser.*; +import io.github.douira.glsl_transformer.ast.node.TranslationUnit; +import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; +import io.github.douira.glsl_transformer.ast.node.expression.Expression; +import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration; +import io.github.douira.glsl_transformer.ast.node.statement.Statement; +import io.github.douira.glsl_transformer.ast.node.type.FullySpecifiedType; +import io.github.douira.glsl_transformer.ast.query.RootSupplier; +import io.github.douira.glsl_transformer.ast.transform.ASTBuilder; +import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import repack.antlr.v4.runtime.ParserRuleContext; + +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * A static data class that contains the information needed to parse and build a + * specific type of node. Contains the class of the rule context, a method of + * {@link GLSLParser} to parse this kind of rule context from a string, and a + * method of {@link ASTBuilder} to build an AST node from a rule context. + * + * Usually the static pre-made instances of this class are sufficient but + * additional specific instances can be created and should then be stored as a + * static final field for reuse. + */ +public class ParseShape { + public static final ParseShape TRANSLATION_UNIT = new ParseShape<>( + TranslationUnitContext.class, + GLSLParser::translationUnit, + ASTBuilder::visitTranslationUnit); + public static final ParseShape EXTERNAL_DECLARATION = new ParseShape<>( + ExternalDeclarationContext.class, + GLSLParser::externalDeclaration, + ASTBuilder::visitExternalDeclaration); + public static final ParseShape STATEMENT = new ParseShape<>( + StatementContext.class, + GLSLParser::statement, + ASTBuilder::visitStatement); + public static final ParseShape EXPRESSION = new ParseShape<>( + ExpressionContext.class, + GLSLParser::expression, + ASTBuilder::visitExpression); + public static final ParseShape FULLY_SPECIFIED_TYPE = new ParseShape<>( + FullySpecifiedTypeContext.class, + GLSLParser::fullySpecifiedType, + ASTBuilder::visitFullySpecifiedType); + + public final Class ruleType; + public final Function parseMethod; + public final BiFunction visitMethod; + + public ParseShape(Class ruleType, Function parseMethod, BiFunction visitMethod) { + this.ruleType = ruleType; + this.parseMethod = parseMethod; + this.visitMethod = visitMethod; + } + + public N _parseNodeSeparateInternal(String input) { + return ASTParser._getInternalInstance().parseNodeSeparate(RootSupplier.DEFAULT, this, input); + } +} diff --git a/src/main/java/io/github/douira/glsl_transformer/token_filter/ChannelFilter.java b/src/main/java/io/github/douira/glsl_transformer/token_filter/ChannelFilter.java index 7b8c194c21..7ab8a02300 100644 --- a/src/main/java/io/github/douira/glsl_transformer/token_filter/ChannelFilter.java +++ b/src/main/java/io/github/douira/glsl_transformer/token_filter/ChannelFilter.java @@ -1,10 +1,9 @@ package io.github.douira.glsl_transformer.token_filter; -import java.util.EnumSet; - +import io.github.douira.glsl_transformer.ast.transform.JobParameters; import repack.antlr.v4.runtime.Token; -import io.github.douira.glsl_transformer.ast.transform.JobParameters; +import java.util.EnumSet; /** * The channel filter accepts all tokens that are not from a lexer channel that @@ -15,7 +14,7 @@ public class ChannelFilter extends TokenFilter { /** * Creates a new channel filter with the given disallowed channels. - * + * * @param disallowedChannels The disallowed channels */ public ChannelFilter(EnumSet disallowedChannels) { @@ -24,7 +23,7 @@ public ChannelFilter(EnumSet disallowedChannels) { /** * Creates a new channel filter with a single disallowed channel. - * + * * @param disallowedChannel The disallowed channel */ public ChannelFilter(TokenChannel disallowedChannel) { diff --git a/src/main/java/io/github/douira/glsl_transformer/token_filter/StringFilter.java b/src/main/java/io/github/douira/glsl_transformer/token_filter/StringFilter.java index 121a1b2c99..ef6ab1ac6d 100644 --- a/src/main/java/io/github/douira/glsl_transformer/token_filter/StringFilter.java +++ b/src/main/java/io/github/douira/glsl_transformer/token_filter/StringFilter.java @@ -5,7 +5,6 @@ import repack.antlr.v4.runtime.Token; import io.github.douira.glsl_transformer.ast.transform.JobParameters; -import io.github.douira.glsl_transformer.util.CompatUtil; /** * The string token filter disallows tokens that are matched against a set of @@ -29,7 +28,7 @@ public StringFilter(Set disallowed) { * @param disallowed The string to match */ public StringFilter(String disallowed) { - this.disallowed = CompatUtil.setOf(disallowed); + this.disallowed = Set.of(disallowed); } /** @@ -38,7 +37,7 @@ public StringFilter(String disallowed) { * @param disallowed The strings to match */ public StringFilter(String... disallowed) { - this.disallowed = CompatUtil.setOf(disallowed); + this.disallowed = Set.of(disallowed); } @Override diff --git a/src/main/java/io/github/douira/glsl_transformer/util/CompatUtil.java b/src/main/java/io/github/douira/glsl_transformer/util/CompatUtil.java deleted file mode 100644 index a0d694f887..0000000000 --- a/src/main/java/io/github/douira/glsl_transformer/util/CompatUtil.java +++ /dev/null @@ -1,182 +0,0 @@ -package io.github.douira.glsl_transformer.util; - -import java.util.*; -import java.util.function.*; -import java.util.stream.*; - -/** - * This class contains utility methods that allow maintaining Java 8 API - * compatability. (Even though the code is at Java 16 source compatability) - */ -public class CompatUtil { - /** - * Repeats the given string a number of times. - * - * From https://stackoverflow.com/a/1235213 - * - * @param str The string to repeat - * @param n The number of times to repeat the string - * @return The given string repeated n times - */ - public static String repeat(String str, int n) { - if (str == null) { - return null; - } - if (str.length() == 0 || n <= 0) { - return ""; - } - if (n == 1) { - return str; - } - - var builder = new StringBuilder(str.length() * n); - for (int i = 0; i < n; i++) { - builder.append(str); - } - return builder.toString(); - } - - /** - * Creates a {@link java.util.HashSet} that contains the given items. The heap - * pollution warning is suppressed as it is in {@link java.util.Arrays}. - * - * @param The type of the items - * @param items The items to add to the set - * @return The set with the given items - */ - @SafeVarargs - public static Set setOf(V... items) { - return new HashSet<>(Arrays.asList(items)); - } - - /** - * Creates a {@link java.util.HashSet} that contains the given item. - * - * @param The type of the item - * @param item The item to add to the set - * @return The set with the given item - */ - public static Set setOf(V item) { - var set = new HashSet(); - set.add(item); - return set; - } - - /** - * Creates a {@link java.util.HashSet} that contains the given items. - * - * @param The type of the items - * @param itemA The first item to add to the set - * @param itemB The second item to add to the set - * @return The set with the given items - */ - public static Set setOf(V itemA, V itemB) { - var set = new HashSet(); - set.add(itemA); - set.add(itemB); - return set; - } - - /** - * Creates an {@link java.util.ArrayList} that contains the given items in the - * same order. This is likely cheaper for making a collection than using - * {@link #setOf(Object...)}. - * - * @param The type of the items - * @param items The items to create the list out of - * @return The list with the given items - */ - @SafeVarargs - public static List listOf(V... items) { - return Arrays.asList(items); - } - - /** - * Returns a sequential ordered {@code Stream} produced by iterative - * application of the given {@code next} function to an initial element, - * conditioned on satisfying the given {@code hasNext} predicate. The - * stream terminates as soon as the {@code hasNext} predicate returns false. - * - *

- * {@code Stream.iterate} should produce the same sequence of elements as - * produced by the corresponding for-loop: - * - *

{@code
-   *     for (T index=seed; hasNext.test(index); index = next.apply(index)) {
-   *         ...
-   *     }
-   * }
- * - *

- * The resulting sequence may be empty if the {@code hasNext} predicate - * does not hold on the seed value. Otherwise the first element will be the - * supplied {@code seed} value, the next element (if present) will be the - * result of applying the {@code next} function to the {@code seed} value, - * and so on iteratively until the {@code hasNext} predicate indicates that - * the stream should terminate. - * - *

- * The action of applying the {@code hasNext} predicate to an element - * happens-before - * the action of applying the {@code next} function to that element. The - * action of applying the {@code next} function for one element - * happens-before the action of applying the {@code hasNext} - * predicate for subsequent elements. For any given element an action may - * be performed in whatever thread the library chooses. - * - * @param the type of stream elements - * @param seed the initial element - * @param hasNext a predicate to apply to elements to determine when the - * stream must terminate. - * @param next a function to be applied to the previous element to produce - * a new element - * @return a new sequential {@code Stream} - * @implNote The implementation was taken from the JDK 9 source code. - */ - public static Stream iterateStream(V seed, Predicate hasNext, UnaryOperator next) { - Objects.requireNonNull(next); - Objects.requireNonNull(hasNext); - Spliterator spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE, - Spliterator.ORDERED | Spliterator.IMMUTABLE) { - V prev; - boolean started, finished; - - @Override - public boolean tryAdvance(Consumer action) { - Objects.requireNonNull(action); - if (finished) - return false; - V t; - if (started) - t = next.apply(prev); - else { - t = seed; - started = true; - } - if (!hasNext.test(t)) { - prev = null; - finished = true; - return false; - } - action.accept(prev = t); - return true; - } - - @Override - public void forEachRemaining(Consumer action) { - Objects.requireNonNull(action); - if (finished) - return; - finished = true; - V t = started ? next.apply(prev) : seed; - prev = null; - while (hasNext.test(t)) { - action.accept(t); - t = next.apply(t); - } - } - }; - return StreamSupport.stream(spliterator, false); - } -} diff --git a/src/main/java/io/github/douira/glsl_transformer/util/ExcludeFromJacocoGeneratedReport.java b/src/main/java/io/github/douira/glsl_transformer/util/ExcludeFromJacocoGeneratedReport.java index 44e2b7fef3..ca31ea99b7 100644 --- a/src/main/java/io/github/douira/glsl_transformer/util/ExcludeFromJacocoGeneratedReport.java +++ b/src/main/java/io/github/douira/glsl_transformer/util/ExcludeFromJacocoGeneratedReport.java @@ -1,6 +1,9 @@ package io.github.douira.glsl_transformer.util; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * This annotation causes the annotated method to be excluded from the jacoco diff --git a/src/main/java/kroppeb/stareval/function/Type.java b/src/main/java/kroppeb/stareval/function/Type.java index 2e5d2d3028..fd7cff31bf 100644 --- a/src/main/java/kroppeb/stareval/function/Type.java +++ b/src/main/java/kroppeb/stareval/function/Type.java @@ -178,6 +178,7 @@ public static UniformType convert(Type type) { else if (type == VectorType.VEC3) return UniformType.VEC3; else if (type == VectorType.VEC4) return UniformType.VEC4; else if (type == VectorType.I_VEC2) return UniformType.VEC2I; + else if (type == VectorType.I_VEC3) return UniformType.VEC3I; else if (type == MatrixType.MAT4) return UniformType.MAT4; else throw new IllegalArgumentException("Unsupported custom uniform type: " + type); } diff --git a/src/main/java/llamalad7/mixinextras/MixinExtrasAP.java b/src/main/java/llamalad7/mixinextras/MixinExtrasAP.java deleted file mode 100644 index 6ef5e2916a..0000000000 --- a/src/main/java/llamalad7/mixinextras/MixinExtrasAP.java +++ /dev/null @@ -1,32 +0,0 @@ -package llamalad7.mixinextras; - -import org.spongepowered.asm.util.logging.MessageRouter; - -import javax.annotation.processing.*; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.TypeElement; -import java.util.Set; - -@SupportedAnnotationTypes({}) -public class MixinExtrasAP extends AbstractProcessor { - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - return false; - } - - @Override - public synchronized void init(ProcessingEnvironment processingEnv) { - super.init(processingEnv); - try { - MessageRouter.setMessager(processingEnv.getMessager()); - MixinExtrasBootstrap.initialize(false); - } catch (NoClassDefFoundError e) { - // The Mixin AP probably isn't available, e.g. if loom has excluded it from IDEA. - } - } - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } -} diff --git a/src/main/java/llamalad7/mixinextras/MixinExtrasBootstrap.java b/src/main/java/llamalad7/mixinextras/MixinExtrasBootstrap.java deleted file mode 100644 index f2e64ebbdf..0000000000 --- a/src/main/java/llamalad7/mixinextras/MixinExtrasBootstrap.java +++ /dev/null @@ -1,45 +0,0 @@ -package llamalad7.mixinextras; - -import llamalad7.mixinextras.injector.ModifyExpressionValueInjectionInfo; -import llamalad7.mixinextras.injector.ModifyReceiverInjectionInfo; -import llamalad7.mixinextras.injector.ModifyReturnValueInjectionInfo; -import llamalad7.mixinextras.injector.WrapWithConditionInjectionInfo; -import llamalad7.mixinextras.injector.wrapoperation.WrapOperationApplicatorExtension; -import llamalad7.mixinextras.injector.wrapoperation.WrapOperationInjectionInfo; -import llamalad7.mixinextras.sugar.impl.SugarApplicatorExtension; -import llamalad7.mixinextras.sugar.impl.SugarWrapperInjectionInfo; -import llamalad7.mixinextras.utils.MixinInternals; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; - -@SuppressWarnings("unused") -public class MixinExtrasBootstrap { - private static boolean initialized = false; - private static final String VERSION = "0.2.0-beta.1"; - - public static String getVersion() { - return VERSION; - } - - public static void init() { - initialize(true); - } - - static void initialize(boolean runtime) { - if (!initialized) { - initialized = true; - - InjectionInfo.register(ModifyExpressionValueInjectionInfo.class); - InjectionInfo.register(ModifyReceiverInjectionInfo.class); - InjectionInfo.register(ModifyReturnValueInjectionInfo.class); - InjectionInfo.register(WrapOperationInjectionInfo.class); - InjectionInfo.register(WrapWithConditionInjectionInfo.class); - - InjectionInfo.register(SugarWrapperInjectionInfo.class); - - if (runtime) { - MixinInternals.registerExtension(new SugarApplicatorExtension()); - MixinInternals.registerExtension(new WrapOperationApplicatorExtension()); - } - } - } -} diff --git a/src/main/java/llamalad7/mixinextras/injector/LateApplyingInjectorInfo.java b/src/main/java/llamalad7/mixinextras/injector/LateApplyingInjectorInfo.java deleted file mode 100644 index 4258edf0af..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/LateApplyingInjectorInfo.java +++ /dev/null @@ -1,7 +0,0 @@ -package llamalad7.mixinextras.injector; - -public interface LateApplyingInjectorInfo { - void lateApply(); - - void wrap(LateApplyingInjectorInfo outer); -} diff --git a/src/main/java/llamalad7/mixinextras/injector/ModifyExpressionValue.java b/src/main/java/llamalad7/mixinextras/injector/ModifyExpressionValue.java deleted file mode 100644 index 7a0d8d9408..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/ModifyExpressionValue.java +++ /dev/null @@ -1,27 +0,0 @@ -package llamalad7.mixinextras.injector; - -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Slice; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface ModifyExpressionValue { - String[] method(); - - At[] at(); - - Slice[] slice() default {}; - - boolean remap() default true; - - int require() default -1; - - int expect() default 1; - - int allow() default -1; -} diff --git a/src/main/java/llamalad7/mixinextras/injector/ModifyExpressionValueInjectionInfo.java b/src/main/java/llamalad7/mixinextras/injector/ModifyExpressionValueInjectionInfo.java deleted file mode 100644 index 3402de4854..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/ModifyExpressionValueInjectionInfo.java +++ /dev/null @@ -1,21 +0,0 @@ -package llamalad7.mixinextras.injector; - -import org.objectweb.asm.tree.AnnotationNode; -import org.objectweb.asm.tree.MethodNode; -import org.spongepowered.asm.mixin.injection.code.Injector; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo.HandlerPrefix; -import org.spongepowered.asm.mixin.transformer.MixinTargetContext; - -@InjectionInfo.AnnotationType(ModifyExpressionValue.class) -@HandlerPrefix("modifyExpressionValue") -public class ModifyExpressionValueInjectionInfo extends InjectionInfo { - public ModifyExpressionValueInjectionInfo(MixinTargetContext mixin, MethodNode method, AnnotationNode annotation) { - super(mixin, method, annotation); - } - - @Override - protected Injector parseInjector(AnnotationNode injectAnnotation) { - return new ModifyExpressionValueInjector(this); - } -} diff --git a/src/main/java/llamalad7/mixinextras/injector/ModifyExpressionValueInjector.java b/src/main/java/llamalad7/mixinextras/injector/ModifyExpressionValueInjector.java deleted file mode 100644 index 01235798e0..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/ModifyExpressionValueInjector.java +++ /dev/null @@ -1,102 +0,0 @@ -package llamalad7.mixinextras.injector; - -import llamalad7.mixinextras.utils.CompatibilityHelper; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.*; -import org.spongepowered.asm.mixin.injection.code.Injector; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionNodes.InjectionNode; -import org.spongepowered.asm.mixin.injection.struct.Target; -import org.spongepowered.asm.util.Bytecode; - -public class ModifyExpressionValueInjector extends Injector { - public ModifyExpressionValueInjector(InjectionInfo info) { - super(info, "@ModifyExpressionValue"); - } - - @Override - protected void inject(Target target, InjectionNode node) { - this.checkTargetReturnsAValue(target, node); - this.checkTargetModifiers(target, false); - - AbstractInsnNode valueNode = node.getCurrentTarget(); - Type valueType = getReturnType(valueNode); - if (valueNode instanceof TypeInsnNode && valueNode.getOpcode() == Opcodes.NEW) { - valueNode = target.findInitNodeFor(((TypeInsnNode) valueNode)); - } - - this.injectValueModifier(target, valueNode, valueType); - } - - private void checkTargetReturnsAValue(Target target, InjectionNode node) { - Type returnType = getReturnType(node.getCurrentTarget()); - if (returnType == Type.VOID_TYPE) { - throw CompatibilityHelper.makeInvalidInjectionException(this.info, - String.format( - "%s annotation is targeting an instruction with a return type of 'void' in %s in %s", - this.annotationType, target, this - )); - } - - if (returnType == null) { - throw CompatibilityHelper.makeInvalidInjectionException(this.info, String.format("%s annotation is targeting an invalid insn in %s in %s", - this.annotationType, target, this)); - } - } - - private void injectValueModifier(Target target, AbstractInsnNode valueNode, Type valueType) { - Target.Extension extraStack = target.extendStack(); - final InsnList after = new InsnList(); - this.invokeHandler(valueType, target, extraStack, after); - extraStack.apply(); - target.insns.insert(valueNode, after); - } - - private void invokeHandler(Type valueType, Target target, Target.Extension extraStack, InsnList after) { - InjectorData handler = new InjectorData(target, "expression value modifier"); - this.validateParams(handler, valueType, valueType); - - if (!this.isStatic) { - after.add(new VarInsnNode(Opcodes.ALOAD, 0)); - if (valueType.getSize() == 2) { - after.add(new InsnNode(Opcodes.DUP_X2)); - after.add(new InsnNode(Opcodes.POP)); - } else { - after.add(new InsnNode(Opcodes.SWAP)); - } - } - - if (handler.captureTargetArgs > 0) { - this.pushArgs(target.arguments, after, target.getArgIndices(), 0, handler.captureTargetArgs, extraStack); - } - - this.invokeHandler(after); - } - - private Type getReturnType(AbstractInsnNode node) { - if (node instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) node; - return Type.getReturnType(methodInsnNode.desc); - } - - if (node instanceof FieldInsnNode) { - FieldInsnNode fieldInsnNode = (FieldInsnNode) node; - if (fieldInsnNode.getOpcode() == Opcodes.GETFIELD || fieldInsnNode.getOpcode() == Opcodes.GETSTATIC) { - return Type.getType(fieldInsnNode.desc); - } - return Type.VOID_TYPE; - } - - if (Bytecode.isConstant(node)) { - return Bytecode.getConstantType(node); - } - - if (node instanceof TypeInsnNode && node.getOpcode() == Opcodes.NEW) { - TypeInsnNode typeInsnNode = ((TypeInsnNode) node); - return Type.getObjectType(typeInsnNode.desc); - } - - return null; - } -} diff --git a/src/main/java/llamalad7/mixinextras/injector/ModifyReceiver.java b/src/main/java/llamalad7/mixinextras/injector/ModifyReceiver.java deleted file mode 100644 index 53c4104917..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/ModifyReceiver.java +++ /dev/null @@ -1,27 +0,0 @@ -package llamalad7.mixinextras.injector; - -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Slice; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface ModifyReceiver { - String[] method(); - - At[] at(); - - Slice[] slice() default {}; - - boolean remap() default true; - - int require() default -1; - - int expect() default 1; - - int allow() default -1; -} diff --git a/src/main/java/llamalad7/mixinextras/injector/ModifyReceiverInjectionInfo.java b/src/main/java/llamalad7/mixinextras/injector/ModifyReceiverInjectionInfo.java deleted file mode 100644 index 0305f94a4a..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/ModifyReceiverInjectionInfo.java +++ /dev/null @@ -1,21 +0,0 @@ -package llamalad7.mixinextras.injector; - -import org.objectweb.asm.tree.AnnotationNode; -import org.objectweb.asm.tree.MethodNode; -import org.spongepowered.asm.mixin.injection.code.Injector; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo.HandlerPrefix; -import org.spongepowered.asm.mixin.transformer.MixinTargetContext; - -@InjectionInfo.AnnotationType(ModifyReceiver.class) -@HandlerPrefix("modifyReceiver") -public class ModifyReceiverInjectionInfo extends InjectionInfo { - public ModifyReceiverInjectionInfo(MixinTargetContext mixin, MethodNode method, AnnotationNode annotation) { - super(mixin, method, annotation); - } - - @Override - protected Injector parseInjector(AnnotationNode injectAnnotation) { - return new ModifyReceiverInjector(this); - } -} diff --git a/src/main/java/llamalad7/mixinextras/injector/ModifyReceiverInjector.java b/src/main/java/llamalad7/mixinextras/injector/ModifyReceiverInjector.java deleted file mode 100644 index 4f3c7f3dd6..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/ModifyReceiverInjector.java +++ /dev/null @@ -1,90 +0,0 @@ -package llamalad7.mixinextras.injector; - -import llamalad7.mixinextras.utils.CompatibilityHelper; -import llamalad7.mixinextras.utils.InjectorUtils; -import org.apache.commons.lang3.ArrayUtils; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.*; -import org.spongepowered.asm.mixin.injection.code.Injector; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionNodes.InjectionNode; -import org.spongepowered.asm.mixin.injection.struct.Target; - -public class ModifyReceiverInjector extends Injector { - public ModifyReceiverInjector(InjectionInfo info) { - super(info, "@ModifyReceiver"); - } - - @Override - protected void inject(Target target, InjectionNode node) { - this.checkTargetIsValid(target, node); - this.checkTargetModifiers(target, false); - this.modifyReceiverOfTarget(target, node); - } - - private void checkTargetIsValid(Target target, InjectionNode node) { - AbstractInsnNode insn = node.getOriginalTarget(); - switch (insn.getOpcode()) { - case Opcodes.INVOKEVIRTUAL: - case Opcodes.INVOKESPECIAL: - case Opcodes.INVOKEINTERFACE: - case Opcodes.GETFIELD: - case Opcodes.PUTFIELD: - return; - default: - throw CompatibilityHelper.makeInvalidInjectionException(this.info, String.format("%s annotation is targeting an invalid insn in %s in %s", - this.annotationType, target, this)); - } - } - - private void modifyReceiverOfTarget(Target target, InjectionNode node) { - AbstractInsnNode currentTarget = node.getCurrentTarget(); - Type[] originalArgTypes = getEffectiveArgTypes(node.getOriginalTarget()); - Type[] currentArgTypes = getEffectiveArgTypes(currentTarget); - InsnList insns = new InsnList(); - boolean isVirtualRedirect = InjectorUtils.isVirtualRedirect(node); - this.injectReceiverModifier(target, originalArgTypes, currentArgTypes, isVirtualRedirect, insns); - target.insertBefore(node, insns); - } - - private void injectReceiverModifier(Target target, Type[] originalArgTypes, Type[] currentArgTypes, boolean isVirtualRedirect, InsnList insns) { - InjectorData handler = new InjectorData(target, "receiver modifier"); - this.validateParams(handler, originalArgTypes[0], originalArgTypes); - - int[] argMap = this.storeArgs(target, currentArgTypes, insns, 0); - int[] handlerArgMap = ArrayUtils.addAll(argMap, target.getArgIndices()); - if (isVirtualRedirect) { - // We need to disregard the extra "this" which will be added for a virtual redirect. - handlerArgMap = ArrayUtils.remove(handlerArgMap, 0); - // We also need to ensure it remains on the stack before the receiver - insns.add(new VarInsnNode(Opcodes.ALOAD, 0)); - } - - this.invokeHandlerWithArgs(this.methodArgs, insns, handlerArgMap); - - // If this is a virtual redirect, both "this" and the receiver are already on the stack - this.pushArgs(currentArgTypes, insns, argMap, isVirtualRedirect ? 2 : 1, argMap.length); - } - - private Type[] getEffectiveArgTypes(AbstractInsnNode node) { - switch (node.getOpcode()) { - case Opcodes.INVOKEVIRTUAL: - case Opcodes.INVOKESPECIAL: - case Opcodes.INVOKEINTERFACE: { - MethodInsnNode methodInsnNode = ((MethodInsnNode) node); - return ArrayUtils.addAll(new Type[]{Type.getObjectType(methodInsnNode.owner)}, Type.getArgumentTypes(methodInsnNode.desc)); - } - case Opcodes.GETFIELD: { - FieldInsnNode fieldInsnNode = ((FieldInsnNode) node); - return new Type[]{Type.getObjectType(fieldInsnNode.owner)}; - } - case Opcodes.PUTFIELD: { - FieldInsnNode fieldInsnNode = ((FieldInsnNode) node); - return new Type[]{Type.getObjectType(fieldInsnNode.owner), Type.getType(fieldInsnNode.desc)}; - } - } - - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/llamalad7/mixinextras/injector/ModifyReturnValue.java b/src/main/java/llamalad7/mixinextras/injector/ModifyReturnValue.java deleted file mode 100644 index 7df3a4e0ec..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/ModifyReturnValue.java +++ /dev/null @@ -1,27 +0,0 @@ -package llamalad7.mixinextras.injector; - -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Slice; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface ModifyReturnValue { - String[] method(); - - At[] at(); - - Slice[] slice() default {}; - - boolean remap() default true; - - int require() default -1; - - int expect() default 1; - - int allow() default -1; -} diff --git a/src/main/java/llamalad7/mixinextras/injector/ModifyReturnValueInjectionInfo.java b/src/main/java/llamalad7/mixinextras/injector/ModifyReturnValueInjectionInfo.java deleted file mode 100644 index 4ebe302c35..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/ModifyReturnValueInjectionInfo.java +++ /dev/null @@ -1,21 +0,0 @@ -package llamalad7.mixinextras.injector; - -import org.objectweb.asm.tree.AnnotationNode; -import org.objectweb.asm.tree.MethodNode; -import org.spongepowered.asm.mixin.injection.code.Injector; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo.HandlerPrefix; -import org.spongepowered.asm.mixin.transformer.MixinTargetContext; - -@InjectionInfo.AnnotationType(ModifyReturnValue.class) -@HandlerPrefix("modifyReturnValue") -public class ModifyReturnValueInjectionInfo extends InjectionInfo { - public ModifyReturnValueInjectionInfo(MixinTargetContext mixin, MethodNode method, AnnotationNode annotation) { - super(mixin, method, annotation); - } - - @Override - protected Injector parseInjector(AnnotationNode injectAnnotation) { - return new ModifyReturnValueInjector(this); - } -} diff --git a/src/main/java/llamalad7/mixinextras/injector/ModifyReturnValueInjector.java b/src/main/java/llamalad7/mixinextras/injector/ModifyReturnValueInjector.java deleted file mode 100644 index 492daf6ce6..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/ModifyReturnValueInjector.java +++ /dev/null @@ -1,50 +0,0 @@ -package llamalad7.mixinextras.injector; - -import llamalad7.mixinextras.utils.CompatibilityHelper; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.*; -import org.spongepowered.asm.mixin.injection.code.Injector; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionNodes.InjectionNode; -import org.spongepowered.asm.mixin.injection.struct.Target; - -public class ModifyReturnValueInjector extends Injector { - public ModifyReturnValueInjector(InjectionInfo info) { - super(info, "@ModifyReturnValue"); - } - - @Override - protected void inject(Target target, InjectionNode node) { - int opcode = node.getCurrentTarget().getOpcode(); - if (opcode < Opcodes.IRETURN || opcode >= Opcodes.RETURN) { - throw CompatibilityHelper.makeInvalidInjectionException(this.info, String.format("%s annotation is targeting an invalid insn in %s in %s", - this.annotationType, target, this)); - } - this.checkTargetModifiers(target, false); - this.injectReturnValueModifier(target, node); - } - - private void injectReturnValueModifier(Target target, InjectionNode node) { - InjectorData handler = new InjectorData(target, "return value modifier"); - InsnList insns = new InsnList(); - - this.validateParams(handler, target.returnType, target.returnType); - - if (!this.isStatic) { - insns.add(new VarInsnNode(Opcodes.ALOAD, 0)); - if (target.returnType.getSize() == 2) { - insns.add(new InsnNode(Opcodes.DUP_X2)); - insns.add(new InsnNode(Opcodes.POP)); - } else { - insns.add(new InsnNode(Opcodes.SWAP)); - } - } - - if (handler.captureTargetArgs > 0) { - this.pushArgs(target.arguments, insns, target.getArgIndices(), 0, handler.captureTargetArgs); - } - - this.invokeHandler(insns); - target.insertBefore(node, insns); - } -} diff --git a/src/main/java/llamalad7/mixinextras/injector/WrapWithCondition.java b/src/main/java/llamalad7/mixinextras/injector/WrapWithCondition.java deleted file mode 100644 index 657076a180..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/WrapWithCondition.java +++ /dev/null @@ -1,27 +0,0 @@ -package llamalad7.mixinextras.injector; - -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Slice; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface WrapWithCondition { - String[] method(); - - At[] at(); - - Slice[] slice() default {}; - - boolean remap() default true; - - int require() default -1; - - int expect() default 1; - - int allow() default -1; -} diff --git a/src/main/java/llamalad7/mixinextras/injector/WrapWithConditionInjectionInfo.java b/src/main/java/llamalad7/mixinextras/injector/WrapWithConditionInjectionInfo.java deleted file mode 100644 index 20cc202802..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/WrapWithConditionInjectionInfo.java +++ /dev/null @@ -1,57 +0,0 @@ -package llamalad7.mixinextras.injector; - -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.AnnotationNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; -import org.spongepowered.asm.mixin.injection.code.Injector; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo.HandlerPrefix; -import org.spongepowered.asm.mixin.injection.struct.InjectionNodes; -import org.spongepowered.asm.mixin.transformer.MixinTargetContext; - -import java.util.List; - -@InjectionInfo.AnnotationType(WrapWithCondition.class) -@HandlerPrefix("wrapWithCondition") -public class WrapWithConditionInjectionInfo extends InjectionInfo { - static final String POPPED_OPERATION_DECORATOR = "mixinextras_operationIsImmediatelyPopped"; - - public WrapWithConditionInjectionInfo(MixinTargetContext mixin, MethodNode method, AnnotationNode annotation) { - super(mixin, method, annotation); - } - - @Override - protected Injector parseInjector(AnnotationNode injectAnnotation) { - return new WrapWithConditionInjector(this); - } - - @Override - public void prepare() { - super.prepare(); - for (List nodeList : this.targetNodes.values()) { - for (InjectionNodes.InjectionNode node : nodeList) { - AbstractInsnNode currentTarget = node.getCurrentTarget(); - if (currentTarget instanceof MethodInsnNode) { - Type returnType = Type.getReturnType(((MethodInsnNode) currentTarget).desc); - if (this.isTypePoppedByInstruction(returnType, currentTarget.getNext())) { - node.decorate(POPPED_OPERATION_DECORATOR, true); - } - } - } - } - } - - private boolean isTypePoppedByInstruction(Type type, AbstractInsnNode insn) { - switch (type.getSize()) { - case 2: - return insn.getOpcode() == Opcodes.POP2; - case 1: - return insn.getOpcode() == Opcodes.POP; - default: - return false; - } - } -} diff --git a/src/main/java/llamalad7/mixinextras/injector/WrapWithConditionInjector.java b/src/main/java/llamalad7/mixinextras/injector/WrapWithConditionInjector.java deleted file mode 100644 index 8ed3660068..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/WrapWithConditionInjector.java +++ /dev/null @@ -1,144 +0,0 @@ -package llamalad7.mixinextras.injector; - -import llamalad7.mixinextras.utils.CompatibilityHelper; -import llamalad7.mixinextras.utils.InjectorUtils; -import org.apache.commons.lang3.ArrayUtils; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.*; -import org.spongepowered.asm.mixin.injection.code.Injector; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionNodes.InjectionNode; -import org.spongepowered.asm.mixin.injection.struct.Target; - -public class WrapWithConditionInjector extends Injector { - public WrapWithConditionInjector(InjectionInfo info) { - super(info, "@WrapWithCondition"); - } - - @Override - protected void inject(Target target, InjectionNode node) { - this.checkTargetIsLogicallyVoid(target, node); - this.checkTargetModifiers(target, false); - this.wrapTargetWithCondition(target, node); - } - - private void checkTargetIsLogicallyVoid(Target target, InjectionNode node) { - if (node.hasDecoration(WrapWithConditionInjectionInfo.POPPED_OPERATION_DECORATOR)) { - // We have already checked that the operation's return value is immediately popped, therefore it is effectively void. - return; - } - - Type returnType = getReturnType(node.getCurrentTarget()); - if (returnType == null) { - throw CompatibilityHelper.makeInvalidInjectionException(this.info, String.format("%s annotation is targeting an invalid insn in %s in %s", - this.annotationType, target, this)); - } - - if (returnType != Type.VOID_TYPE) { - throw CompatibilityHelper.makeInvalidInjectionException(this.info, - String.format( - "%s annotation is targeting an instruction with a non-void return type in %s in %s", - this.annotationType, target, this - )); - } - } - - private void wrapTargetWithCondition(Target target, InjectionNode node) { - AbstractInsnNode currentTarget = node.getCurrentTarget(); - Type returnType = getReturnType(currentTarget); - Type[] originalArgTypes = getEffectiveArgTypes(node.getOriginalTarget()); - Type[] currentArgTypes = getEffectiveArgTypes(currentTarget); - InsnList before = new InsnList(); - InsnList after = new InsnList(); - boolean isVirtualRedirect = InjectorUtils.isVirtualRedirect(node); - this.invokeHandler(target, returnType, originalArgTypes, currentArgTypes, isVirtualRedirect, before, after); - target.wrapNode(currentTarget, currentTarget, before, after); - } - - private void invokeHandler(Target target, Type returnType, Type[] originalArgTypes, Type[] currentArgTypes, boolean isVirtualRedirect, InsnList before, InsnList after) { - InjectorData handler = new InjectorData(target, "condition wrapper"); - this.validateParams(handler, Type.BOOLEAN_TYPE, originalArgTypes); - - int[] argMap = this.storeArgs(target, currentArgTypes, before, 0); - int[] handlerArgMap = ArrayUtils.addAll(argMap, target.getArgIndices()); - if (isVirtualRedirect) { - // We need to disregard the extra "this" which will be added for a virtual redirect. - handlerArgMap = ArrayUtils.remove(handlerArgMap, 0); - } - - this.invokeHandlerWithArgs(this.methodArgs, before, handlerArgMap); - - LabelNode afterOperation = new LabelNode(); - LabelNode afterDummy = new LabelNode(); - before.add(new JumpInsnNode(Opcodes.IFEQ, afterOperation)); - - this.pushArgs(currentArgTypes, before, argMap, 0, argMap.length); - // Target instruction will be here - after.add(new JumpInsnNode(Opcodes.GOTO, afterDummy)); - after.add(afterOperation); - if (returnType != Type.VOID_TYPE) { - after.add(new InsnNode(this.getDummyOpcodeForType(returnType))); - } - after.add(afterDummy); - } - - private Type getReturnType(AbstractInsnNode node) { - if (node instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) node; - return Type.getReturnType(methodInsnNode.desc); - } - - if (node instanceof FieldInsnNode) { - FieldInsnNode fieldInsnNode = (FieldInsnNode) node; - if (fieldInsnNode.getOpcode() == Opcodes.GETFIELD || fieldInsnNode.getOpcode() == Opcodes.GETSTATIC) { - return Type.getType(fieldInsnNode.desc); - } - return Type.VOID_TYPE; - } - - return null; - } - - private Type[] getEffectiveArgTypes(AbstractInsnNode node) { - if (node instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = ((MethodInsnNode) node); - return node.getOpcode() == Opcodes.INVOKESTATIC ? - Type.getArgumentTypes(methodInsnNode.desc) : - ArrayUtils.addAll(new Type[]{Type.getObjectType(methodInsnNode.owner)}, Type.getArgumentTypes(methodInsnNode.desc)); - } - if (node instanceof FieldInsnNode) { - FieldInsnNode fieldInsnNode = ((FieldInsnNode) node); - if (fieldInsnNode.getOpcode() == Opcodes.PUTFIELD) { - return new Type[]{Type.getObjectType(fieldInsnNode.owner), Type.getType(fieldInsnNode.desc)}; - } - if (fieldInsnNode.getOpcode() == Opcodes.PUTSTATIC) { - return new Type[]{Type.getType(fieldInsnNode.desc)}; - } - } - - throw new UnsupportedOperationException(); - } - - private int getDummyOpcodeForType(Type type) { - switch (type.getSort()) { - case Type.BOOLEAN: - case Type.CHAR: - case Type.BYTE: - case Type.SHORT: - case Type.INT: - return Opcodes.ICONST_0; - case Type.FLOAT: - return Opcodes.FCONST_0; - case Type.LONG: - return Opcodes.LCONST_0; - case Type.DOUBLE: - return Opcodes.DCONST_0; - case Type.ARRAY: - case Type.OBJECT: - return Opcodes.ACONST_NULL; - default: - throw new UnsupportedOperationException(); - } - } -} diff --git a/src/main/java/llamalad7/mixinextras/injector/wrapoperation/Operation.java b/src/main/java/llamalad7/mixinextras/injector/wrapoperation/Operation.java deleted file mode 100644 index bbc9f2f577..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/wrapoperation/Operation.java +++ /dev/null @@ -1,11 +0,0 @@ -package llamalad7.mixinextras.injector.wrapoperation; - -/** - * Represents an operation (method call or field get/set) that has been wrapped by {@link WrapOperation}. - * This may either be the operation the user targeted originally, or a wrapped version of it, allowing for chaining. - * @param the return type of the operation. - */ -@FunctionalInterface -public interface Operation { - R call(Object... args); -} diff --git a/src/main/java/llamalad7/mixinextras/injector/wrapoperation/WrapOperation.java b/src/main/java/llamalad7/mixinextras/injector/wrapoperation/WrapOperation.java deleted file mode 100644 index e9a26f057d..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/wrapoperation/WrapOperation.java +++ /dev/null @@ -1,36 +0,0 @@ -package llamalad7.mixinextras.injector.wrapoperation; - -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Constant; -import org.spongepowered.asm.mixin.injection.Slice; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface WrapOperation { - String[] method(); - - /** - * Selector for targeting method calls and field gets/sets. - */ - At[] at() default {}; - - /** - * Selector for targeting `instanceof`s. - */ - Constant[] constant() default {}; - - Slice[] slice() default {}; - - boolean remap() default true; - - int require() default -1; - - int expect() default 1; - - int allow() default -1; -} diff --git a/src/main/java/llamalad7/mixinextras/injector/wrapoperation/WrapOperationApplicatorExtension.java b/src/main/java/llamalad7/mixinextras/injector/wrapoperation/WrapOperationApplicatorExtension.java deleted file mode 100644 index 45d27b93d8..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/wrapoperation/WrapOperationApplicatorExtension.java +++ /dev/null @@ -1,44 +0,0 @@ -package llamalad7.mixinextras.injector.wrapoperation; - -import llamalad7.mixinextras.injector.LateApplyingInjectorInfo; -import org.objectweb.asm.tree.ClassNode; -import org.spongepowered.asm.mixin.MixinEnvironment; -import org.spongepowered.asm.mixin.transformer.ext.IExtension; -import org.spongepowered.asm.mixin.transformer.ext.ITargetClassContext; - -import java.util.*; - -/** - * This extension is responsible for actually injecting all `@WrapOperation`s which were queued up during the normal - * injection phase. Applying them here means we are guaranteed to run after every other injector, which is crucial. - */ -public class WrapOperationApplicatorExtension implements IExtension { - private static final Map> QUEUED_INJECTIONS = Collections.synchronizedMap(new WeakHashMap<>()); - - static void offerInjection(ITargetClassContext targetClassContext, LateApplyingInjectorInfo injectorInfo) { - QUEUED_INJECTIONS.computeIfAbsent(targetClassContext, k -> new ArrayList<>()).add(injectorInfo); - } - - @Override - public boolean checkActive(MixinEnvironment environment) { - return true; - } - - @Override - public void preApply(ITargetClassContext context) { - } - - @Override - public void postApply(ITargetClassContext context) { - List queuedInjections = QUEUED_INJECTIONS.get(context); - if (queuedInjections != null) { - for (LateApplyingInjectorInfo injection : queuedInjections) { - injection.lateApply(); - } - } - } - - @Override - public void export(MixinEnvironment env, String name, boolean force, ClassNode classNode) { - } -} diff --git a/src/main/java/llamalad7/mixinextras/injector/wrapoperation/WrapOperationInjectionInfo.java b/src/main/java/llamalad7/mixinextras/injector/wrapoperation/WrapOperationInjectionInfo.java deleted file mode 100644 index 8e10210c11..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/wrapoperation/WrapOperationInjectionInfo.java +++ /dev/null @@ -1,80 +0,0 @@ -package llamalad7.mixinextras.injector.wrapoperation; - -import llamalad7.mixinextras.injector.LateApplyingInjectorInfo; -import llamalad7.mixinextras.utils.CompatibilityHelper; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.AnnotationNode; -import org.objectweb.asm.tree.MethodNode; -import org.spongepowered.asm.mixin.injection.code.Injector; -import org.spongepowered.asm.mixin.injection.points.BeforeConstant; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo.HandlerPrefix; -import org.spongepowered.asm.mixin.transformer.MixinTargetContext; -import org.spongepowered.asm.util.Annotations; - -import java.util.List; - -@InjectionInfo.AnnotationType(WrapOperation.class) -@HandlerPrefix("wrapOperation") -public class WrapOperationInjectionInfo extends InjectionInfo implements LateApplyingInjectorInfo { - private LateApplyingInjectorInfo injectionInfoToQueue = this; - - public WrapOperationInjectionInfo(MixinTargetContext mixin, MethodNode method, AnnotationNode annotation) { - super(mixin, method, annotation, determineAtKey(mixin, method, annotation)); - } - - @Override - protected Injector parseInjector(AnnotationNode injectAnnotation) { - return new WrapOperationInjector(this); - } - - @Override - public void inject() { - WrapOperationApplicatorExtension.offerInjection(this.mixin.getTarget(), injectionInfoToQueue); - } - - @Override - public void postInject() { - } - - @Override - public void lateApply() { - super.inject(); - super.postInject(); - } - - @Override - public void wrap(LateApplyingInjectorInfo outer) { - this.injectionInfoToQueue = outer; - } - - @Override - protected void parseInjectionPoints(List ats) { - if (this.atKey.equals("at")) { - super.parseInjectionPoints(ats); - return; - } - // If we're wrapping a `constant`, we need to parse the injection points ourselves. - Type returnType = Type.getReturnType(this.method.desc); - - for (AnnotationNode at : ats) { - this.injectionPoints.add(new BeforeConstant(CompatibilityHelper.getMixin(this), at, returnType.getDescriptor())); - } - } - - private static String determineAtKey(MixinTargetContext mixin, MethodNode method, AnnotationNode annotation) { - boolean at = Annotations.getValue(annotation, "at") != null; - boolean constant = Annotations.getValue(annotation, "constant") != null; - if (at == constant) { - throw new IllegalStateException( - String.format("@WrapOperation injector %s::%s must specify exactly one of `at` and `constant`, got %s.", - mixin.getMixin().getClassName(), - method.name, - at ? "both" : "neither" - ) - ); - } else { - return at ? "at" : "constant"; - } - } -} diff --git a/src/main/java/llamalad7/mixinextras/injector/wrapoperation/WrapOperationInjector.java b/src/main/java/llamalad7/mixinextras/injector/wrapoperation/WrapOperationInjector.java deleted file mode 100644 index c5697e414e..0000000000 --- a/src/main/java/llamalad7/mixinextras/injector/wrapoperation/WrapOperationInjector.java +++ /dev/null @@ -1,344 +0,0 @@ -package llamalad7.mixinextras.injector.wrapoperation; - -import llamalad7.mixinextras.utils.CompatibilityHelper; -import llamalad7.mixinextras.utils.InjectorUtils; -import org.apache.commons.lang3.ArrayUtils; -import org.objectweb.asm.Handle; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.*; -import org.spongepowered.asm.mixin.injection.code.Injector; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionNodes.InjectionNode; -import org.spongepowered.asm.mixin.injection.struct.Target; -import org.spongepowered.asm.util.Bytecode; -import org.spongepowered.asm.util.asm.ASM; - -import java.lang.invoke.CallSite; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.util.*; -import java.util.function.Predicate; - -class WrapOperationInjector extends Injector { - private static final Handle LMF_HANDLE = new Handle( - Opcodes.H_INVOKESTATIC, - "java/lang/invoke/LambdaMetafactory", - "metafactory", - Bytecode.generateDescriptor(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class), - false - ); - private static final String NPE = Type.getInternalName(NullPointerException.class); - - public WrapOperationInjector(InjectionInfo info) { - super(info, "@WrapOperation"); - } - - @Override - protected void inject(Target target, InjectionNode node) { - this.checkTargetModifiers(target, false); - this.checkNode(target, node); - this.wrapOperation(target, node); - } - - private void checkNode(Target target, InjectionNode node) { - AbstractInsnNode originalTarget = node.getOriginalTarget(); - AbstractInsnNode currentTarget = node.getCurrentTarget(); - if (!(currentTarget instanceof MethodInsnNode || currentTarget instanceof FieldInsnNode || originalTarget.getOpcode() == Opcodes.INSTANCEOF)) { - throw CompatibilityHelper.makeInvalidInjectionException(this.info, - String.format( - "%s annotation is targeting an invalid insn in %s in %s", - this.annotationType, target, this - )); - } - } - - private void wrapOperation(Target target, InjectionNode node) { - AbstractInsnNode currentTarget = node.getCurrentTarget(); - Type[] argTypes = getEffectiveArgTypes(currentTarget); - Type returnType = getReturnType(node); - InsnList insns = new InsnList(); - AbstractInsnNode champion = this.invokeHandler(target, node, argTypes, returnType, insns); - target.wrapNode(currentTarget, champion, insns, new InsnList()); - target.insns.remove(currentTarget); - } - - private AbstractInsnNode invokeHandler(Target target, InjectionNode node, Type[] argTypes, Type returnType, InsnList insns) { - InjectorData handler = new InjectorData(target, "operation wrapper"); - boolean hasExtraThis = node.isReplaced() && node.getCurrentTarget().getOpcode() != Opcodes.INVOKESTATIC; - if (hasExtraThis) { - // We will add the extra `this` in ourselves in the generated bridge method later. - argTypes = ArrayUtils.remove(argTypes, 0); - } - Type[] originalArgs = getEffectiveArgTypes(node.getOriginalTarget()); - this.validateParams(handler, returnType, ArrayUtils.add(originalArgs, Type.getType(Operation.class))); - - // Store *all* the args, including ones added by redirectors and previous operation wrappers. - // Excess ones will be bound to the lambda. - int[] argMap = this.storeArgs(target, argTypes, insns, 0); - if (hasExtraThis) { - insns.add(new InsnNode(Opcodes.POP)); - } - - if (!this.isStatic) { - insns.add(new VarInsnNode(Opcodes.ALOAD, 0)); - } - // Push the args which should go to the handler method. - this.pushArgs(this.methodArgs, insns, argMap, 0, originalArgs.length); - // Push the receiver of the bridge method (if applicable) and any captured parameters it will need. - if (hasExtraThis) { - insns.add(new VarInsnNode(Opcodes.ALOAD, 0)); - } - this.pushArgs(argTypes, insns, argMap, originalArgs.length, argMap.length); - // The trailing params are any arguments which come after the original args, and should therefore be bound to the lambda. - this.makeSupplier(target, originalArgs, returnType, node, insns, hasExtraThis, ArrayUtils.subarray(argTypes, originalArgs.length, argTypes.length)); - if (handler.captureTargetArgs > 0) { - this.pushArgs(target.arguments, insns, target.getArgIndices(), 0, handler.captureTargetArgs); - } - AbstractInsnNode champion = super.invokeHandler(insns); - - if (InjectorUtils.isDynamicInstanceofRedirect(node)) { - // At this point, we have the boolean result and the checked object on the stack. - // The object was DUPed by RedirectInjector before the handler was called, so removing the DUP is too risky. - // Instead, we simply pop the excess object. - insns.add(new InsnNode(Opcodes.SWAP)); - insns.add(new InsnNode(Opcodes.POP)); - } - return champion; - } - - private void makeSupplier(Target target, Type[] argTypes, Type returnType, InjectionNode node, InsnList insns, boolean hasExtraThis, Type[] trailingParams) { - Type[] descriptorArgs = trailingParams; - if (hasExtraThis) { - // The receiver also needs to be a parameter in the INDY descriptor. - descriptorArgs = ArrayUtils.add(descriptorArgs, 0, Type.getObjectType(this.classNode.name)); - } - insns.add(new InvokeDynamicInsnNode( - // The SAM method will be called `call` - "call", - // The generated lambda will implement `Operation` and have any trailing parameters bound to it - Bytecode.generateDescriptor(Operation.class, (Object[]) descriptorArgs), - // We want to generate the impl with LMF - LMF_HANDLE, - // The SAM method will take an array of args and return an `Object` (the return value of the wrapped call) - Type.getMethodType(Type.getType(Object.class), Type.getType(Object[].class)), - // The implementation method will be generated for us to handle array unpacking - generateSyntheticBridge(target, node, argTypes, hasExtraThis, trailingParams), - // Specialization of the SAM signature - Type.getMethodType( - returnType.getDescriptor().length() == 1 ? Type.getObjectType(returnType == Type.VOID_TYPE ? "java/lang/Void" : Bytecode.getBoxingType(returnType)) : returnType, - Type.getType(Object[].class) - ) - )); - } - - private Handle generateSyntheticBridge(Target target, InjectionNode node, Type[] argTypes, boolean virtual, Type[] boundParams) { - // The bridge method's args will consist of any bound parameters followed by an array - - Type returnType = getReturnType(node); - - MethodNode method = new MethodNode( - ASM.API_VERSION, - Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | (virtual ? 0 : Opcodes.ACC_STATIC), - "mixinextras$bridge$" + UUID.randomUUID() + '$' + getName(node.getCurrentTarget()), - Bytecode.generateDescriptor( - returnType.getDescriptor().length() == 1 ? - Type.getObjectType( - returnType == Type.VOID_TYPE ? "java/lang/Void" : Bytecode.getBoxingType(returnType) - ) : returnType, - ArrayUtils.add(boundParams, Type.getType(Object[].class))), - null, null - ); - method.instructions = new InsnList() {{ - if (virtual) { - add(new VarInsnNode(Opcodes.ALOAD, 0)); - } - int paramArrayIndex = virtual ? 1 : 0; - for (Type boundParamType : boundParams) { - paramArrayIndex += boundParamType.getSize(); - } - add(new VarInsnNode(Opcodes.ALOAD, paramArrayIndex)); - for (int i = 0; i < argTypes.length; i++) { - Type argType = argTypes[i]; - add(new InsnNode(Opcodes.DUP)); - // I'm assuming a wrapped method won't have more than 127 args... - add(new IntInsnNode(Opcodes.BIPUSH, i)); - add(new InsnNode(Opcodes.AALOAD)); - if (argType.getDescriptor().length() == 1) { - // Primitive, cast and unbox - add(new TypeInsnNode(Opcodes.CHECKCAST, Bytecode.getBoxingType(argType))); - add(new MethodInsnNode( - Opcodes.INVOKEVIRTUAL, - Bytecode.getBoxingType(argType), - Bytecode.getUnboxingMethod(argType), - Type.getMethodDescriptor(argType), - false - )); - } else { - // Object type, just cast - add(new TypeInsnNode(Opcodes.CHECKCAST, argType.getInternalName())); - } - // Swap to get the array back on the top of the stack - if (argType.getSize() == 2) { - add(new InsnNode(Opcodes.DUP2_X1)); - add(new InsnNode(Opcodes.POP2)); - } else { - add(new InsnNode(Opcodes.SWAP)); - } - } - // We have one dangling array reference, get rid of it - add(new InsnNode(Opcodes.POP)); - int boundParamIndex = virtual ? 1 : 0; - for (Type boundParamType : boundParams) { - add(new VarInsnNode(boundParamType.getOpcode(Opcodes.ILOAD), boundParamIndex)); - boundParamIndex += boundParamType.getSize(); - } - add(copyNode(node, paramArrayIndex, target)); - if (returnType == Type.VOID_TYPE) { - add(new InsnNode(Opcodes.ACONST_NULL)); - add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Void")); - } else if (returnType.getDescriptor().length() == 1) { - // Primitive, needs boxing - add(new MethodInsnNode( - Opcodes.INVOKESTATIC, - Bytecode.getBoxingType(returnType), - "valueOf", - Bytecode.generateDescriptor(Type.getObjectType(Bytecode.getBoxingType(returnType)), returnType), - false - )); - } - add(new InsnNode(Opcodes.ARETURN)); - }}; - this.classNode.methods.add(method); - - return new Handle( - virtual ? Opcodes.H_INVOKESPECIAL : Opcodes.H_INVOKESTATIC, - this.classNode.name, - method.name, - method.desc, - (this.classNode.access & Opcodes.ACC_INTERFACE) != 0 - ); - } - - private InsnList copyNode(InjectionNode node, int paramArrayIndex, Target target) { - InsnList insns = new InsnList(); - insns.add(node.getCurrentTarget().clone(Collections.emptyMap())); - - if (InjectorUtils.isDynamicInstanceofRedirect(node)) { - // We have a Class object and need to get it back to a boolean using the first element of the lambda args. - // The code added by RedirectInjector expects a reference to the checked object already on the stack, so we - // load the first and only lambda arg, and then swap it with the Class result from the redirector. - insns.add(new VarInsnNode(Opcodes.ALOAD, paramArrayIndex)); - insns.add(new InsnNode(Opcodes.ICONST_0)); - insns.add(new InsnNode(Opcodes.AALOAD)); - insns.add(new InsnNode(Opcodes.SWAP)); - // Sanity checks for the instructions being moved based on what I expect RedirectInjector to have added. - checkAndMoveNodes( - target.insns, - insns, - node.getCurrentTarget().getNext(), - it -> it.getOpcode() == Opcodes.DUP, - it -> it.getOpcode() == Opcodes.IFNONNULL, - it -> it.getOpcode() == Opcodes.NEW && ((TypeInsnNode) it).desc.equals(NPE), - it -> it.getOpcode() == Opcodes.DUP, - it -> it instanceof LdcInsnNode && ((LdcInsnNode) it).cst instanceof String, - it -> it.getOpcode() == Opcodes.INVOKESPECIAL && ((MethodInsnNode) it).owner.equals(NPE), - it -> it.getOpcode() == Opcodes.ATHROW, - it -> it instanceof LabelNode, - it -> it.getOpcode() == Opcodes.SWAP, - it -> it.getOpcode() == Opcodes.DUP, - it -> it.getOpcode() == Opcodes.IFNULL, - it -> it.getOpcode() == Opcodes.INVOKEVIRTUAL && ((MethodInsnNode) it).name.equals("getClass"), - it -> it.getOpcode() == Opcodes.INVOKEVIRTUAL && ((MethodInsnNode) it).name.equals("isAssignableFrom"), - it -> it.getOpcode() == Opcodes.GOTO, - it -> it instanceof LabelNode, - it -> it.getOpcode() == Opcodes.POP, - it -> it.getOpcode() == Opcodes.POP, - it -> it.getOpcode() == Opcodes.ICONST_0, - it -> it instanceof LabelNode - ); - } - return insns; - } - - @SafeVarargs - private final void checkAndMoveNodes(InsnList from, InsnList to, AbstractInsnNode current, Predicate... predicates) { - for (Predicate predicate : predicates) { - if (!predicate.test(current)) { - throw new AssertionError("Failed assertion when wrapping instructions. Please inform LlamaLad7!"); - } - AbstractInsnNode old = current; - do { - current = current.getNext(); - } while (current instanceof FrameNode); - from.remove(old); - to.add(old); - } - } - - private Type getReturnType(InjectionNode node) { - AbstractInsnNode originalTarget = node.getOriginalTarget(); - AbstractInsnNode currentTarget = node.getCurrentTarget(); - - if (originalTarget.getOpcode() == Opcodes.INSTANCEOF) { - return Type.BOOLEAN_TYPE; - } - - if (currentTarget instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) currentTarget; - return Type.getReturnType(methodInsnNode.desc); - } - if (currentTarget instanceof FieldInsnNode) { - FieldInsnNode fieldInsnNode = (FieldInsnNode) currentTarget; - if (fieldInsnNode.getOpcode() == Opcodes.GETFIELD || fieldInsnNode.getOpcode() == Opcodes.GETSTATIC) { - return Type.getType(fieldInsnNode.desc); - } - return Type.VOID_TYPE; - } - - throw new UnsupportedOperationException(); - } - - private Type[] getEffectiveArgTypes(AbstractInsnNode node) { - if (node instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = ((MethodInsnNode) node); - return node.getOpcode() == Opcodes.INVOKESTATIC ? - Type.getArgumentTypes(methodInsnNode.desc) : - ArrayUtils.addAll(new Type[]{Type.getObjectType(methodInsnNode.owner)}, Type.getArgumentTypes(methodInsnNode.desc)); - } - if (node instanceof FieldInsnNode) { - FieldInsnNode fieldInsnNode = ((FieldInsnNode) node); - switch (fieldInsnNode.getOpcode()) { - case Opcodes.GETFIELD: - return new Type[]{Type.getObjectType(fieldInsnNode.owner)}; - case Opcodes.PUTFIELD: - return new Type[]{Type.getObjectType(fieldInsnNode.owner), Type.getType(fieldInsnNode.desc)}; - case Opcodes.GETSTATIC: - return new Type[0]; - case Opcodes.PUTSTATIC: - return new Type[]{Type.getType(fieldInsnNode.desc)}; - } - } - if (node.getOpcode() == Opcodes.INSTANCEOF) { - return new Type[]{Type.getType(Object.class)}; - } - - throw new UnsupportedOperationException(); - } - - private String getName(AbstractInsnNode node) { - if (node instanceof MethodInsnNode) { - return ((MethodInsnNode) node).name; - } - if (node instanceof FieldInsnNode) { - return ((FieldInsnNode) node).name; - } - if (node.getOpcode() == Opcodes.INSTANCEOF) { - String desc = ((TypeInsnNode) node).desc; - return "instanceof" + desc.substring(desc.lastIndexOf('/') + 1); - } - - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/llamalad7/mixinextras/sugar/Local.java b/src/main/java/llamalad7/mixinextras/sugar/Local.java deleted file mode 100644 index 7e1131d7a5..0000000000 --- a/src/main/java/llamalad7/mixinextras/sugar/Local.java +++ /dev/null @@ -1,20 +0,0 @@ -package llamalad7.mixinextras.sugar; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.PARAMETER) -@Retention(RetentionPolicy.CLASS) -public @interface Local { - boolean print() default false; - - int ordinal() default -1; - - int index() default -1; - - String[] name() default {}; - - boolean argsOnly() default false; -} diff --git a/src/main/java/llamalad7/mixinextras/sugar/impl/LocalSugarApplicator.java b/src/main/java/llamalad7/mixinextras/sugar/impl/LocalSugarApplicator.java deleted file mode 100644 index fcc4c1b212..0000000000 --- a/src/main/java/llamalad7/mixinextras/sugar/impl/LocalSugarApplicator.java +++ /dev/null @@ -1,101 +0,0 @@ -package llamalad7.mixinextras.sugar.impl; - -import llamalad7.mixinextras.utils.CompatibilityHelper; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.AnnotationNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.VarInsnNode; -import org.spongepowered.asm.mixin.injection.modify.InvalidImplicitDiscriminatorException; -import org.spongepowered.asm.mixin.injection.modify.LocalVariableDiscriminator; -import org.spongepowered.asm.mixin.injection.modify.LocalVariableDiscriminator.Context; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionNodes.InjectionNode; -import org.spongepowered.asm.mixin.injection.struct.Target; -import org.spongepowered.asm.util.Annotations; -import org.spongepowered.asm.util.Bytecode; -import org.spongepowered.asm.util.PrettyPrinter; -import org.spongepowered.asm.util.SignaturePrinter; - -class LocalSugarApplicator extends SugarApplicator { - private final boolean isArgsOnly; - - public LocalSugarApplicator(InjectionInfo info, Type paramType, AnnotationNode sugar) { - super(info, paramType, sugar); - this.isArgsOnly = Annotations.getValue(sugar, "argsOnly", (Boolean) false); - } - - @Override - void validate(Target target, InjectionNode node) { - LocalVariableDiscriminator discriminator = LocalVariableDiscriminator.parse(sugar); - Context context = getOrCreateLocalContext(target, node); - if (discriminator.printLVT()) { - printLocals(target, node.getCurrentTarget(), context, discriminator); - info.addCallbackInvocation(info.getMethod()); - throw new SugarApplicationException("Application aborted because locals are being printed instead."); - } - try { - if (discriminator.findLocal(context) < 0) { - throw new SugarApplicationException("Unable to find matching local!"); - } - } catch (InvalidImplicitDiscriminatorException e) { - throw new SugarApplicationException("Invalid implicit variable discriminator: ", e); - } - } - - @Override - void preInject(Target target, InjectionNode node) { - getOrCreateLocalContext(target, node); - } - - @Override - void inject(Target target, InjectionNode node) { - LocalVariableDiscriminator discriminator = LocalVariableDiscriminator.parse(sugar); - Context context = node.getDecoration(getLocalContextKey()); - int index = discriminator.findLocal(context); - if (index < 0) { - throw new SugarApplicationException("Failed to match a local, this should have been caught during validation."); - } - InsnList insns = new InsnList(); - insns.add(new VarInsnNode(paramType.getOpcode(Opcodes.ILOAD), index)); - target.insertBefore(node, insns); - } - - private Context getOrCreateLocalContext(Target target, InjectionNode node) { - String decorationKey = getLocalContextKey(); - if (node.hasDecoration(decorationKey)) { - return node.getDecoration(decorationKey); - } - Context context = CompatibilityHelper.makeLvtContext(info, paramType, isArgsOnly, target, node.getCurrentTarget()); - node.decorate(decorationKey, context); - return context; - } - - private String getLocalContextKey() { - return String.format("mixinextras_localSugarContext(%s,%s)", paramType, isArgsOnly ? "argsOnly" : "fullFrame"); - } - - private void printLocals(Target target, AbstractInsnNode node, Context context, LocalVariableDiscriminator discriminator) { - int baseArgIndex = target.isStatic ? 0 : 1; - - new PrettyPrinter() - .kvWidth(20) - .kv("Target Class", target.classNode.name.replace('/', '.')) - .kv("Target Method", target.method.name) - .kv("Capture Type", SignaturePrinter.getTypeName(paramType, false)) - .kv("Instruction", "[%d] %s %s", target.insns.indexOf(node), node.getClass().getSimpleName(), - Bytecode.getOpcodeName(node.getOpcode())).hr() - .kv("Match mode", isImplicit(discriminator, baseArgIndex) ? "IMPLICIT (match single)" : "EXPLICIT (match by criteria)") - .kv("Match ordinal", discriminator.getOrdinal() < 0 ? "any" : discriminator.getOrdinal()) - .kv("Match index", discriminator.getIndex() < baseArgIndex ? "any" : discriminator.getIndex()) - .kv("Match name(s)", discriminator.hasNames() ? discriminator.getNames() : "any") - .kv("Args only", isArgsOnly).hr() - .add(context) - .print(System.err); - } - - private boolean isImplicit(LocalVariableDiscriminator discriminator, int baseArgIndex) { - return discriminator.getOrdinal() < 0 && discriminator.getIndex() < baseArgIndex && discriminator.getNames().isEmpty(); - } -} diff --git a/src/main/java/llamalad7/mixinextras/sugar/impl/SugarApplicationException.java b/src/main/java/llamalad7/mixinextras/sugar/impl/SugarApplicationException.java deleted file mode 100644 index 90ba9bb416..0000000000 --- a/src/main/java/llamalad7/mixinextras/sugar/impl/SugarApplicationException.java +++ /dev/null @@ -1,13 +0,0 @@ -package llamalad7.mixinextras.sugar.impl; - -import org.spongepowered.asm.mixin.throwables.MixinException; - -public class SugarApplicationException extends MixinException { - public SugarApplicationException(String message) { - super(message); - } - - public SugarApplicationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/llamalad7/mixinextras/sugar/impl/SugarApplicator.java b/src/main/java/llamalad7/mixinextras/sugar/impl/SugarApplicator.java deleted file mode 100644 index 25340785ff..0000000000 --- a/src/main/java/llamalad7/mixinextras/sugar/impl/SugarApplicator.java +++ /dev/null @@ -1,47 +0,0 @@ -package llamalad7.mixinextras.sugar.impl; - -import llamalad7.mixinextras.sugar.Local; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.AnnotationNode; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionNodes.InjectionNode; -import org.spongepowered.asm.mixin.injection.struct.Target; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.HashMap; -import java.util.Map; - -abstract class SugarApplicator { - private static final Map> MAP = new HashMap<>(); - - static { - MAP.put(Type.getDescriptor(Local.class), LocalSugarApplicator.class); - } - - protected final InjectionInfo info; - protected final Type paramType; - protected final AnnotationNode sugar; - - SugarApplicator(InjectionInfo info, Type paramType, AnnotationNode sugar) { - this.info = info; - this.paramType = paramType; - this.sugar = sugar; - } - - abstract void validate(Target target, InjectionNode node); - - abstract void preInject(Target target, InjectionNode node); - - abstract void inject(Target target, InjectionNode node); - - static SugarApplicator create(InjectionInfo info, Type paramType, AnnotationNode sugar) { - try { - Class clazz = MAP.get(sugar.desc); - Constructor ctor = clazz.getDeclaredConstructor(InjectionInfo.class, Type.class, AnnotationNode.class); - return ctor.newInstance(info, paramType, sugar); - } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } -} diff --git a/src/main/java/llamalad7/mixinextras/sugar/impl/SugarApplicatorExtension.java b/src/main/java/llamalad7/mixinextras/sugar/impl/SugarApplicatorExtension.java deleted file mode 100644 index 2e4a60c385..0000000000 --- a/src/main/java/llamalad7/mixinextras/sugar/impl/SugarApplicatorExtension.java +++ /dev/null @@ -1,31 +0,0 @@ -package llamalad7.mixinextras.sugar.impl; - -import llamalad7.mixinextras.utils.MixinInternals; -import org.apache.commons.lang3.tuple.Pair; -import org.objectweb.asm.tree.ClassNode; -import org.spongepowered.asm.mixin.MixinEnvironment; -import org.spongepowered.asm.mixin.extensibility.IMixinInfo; -import org.spongepowered.asm.mixin.transformer.ext.IExtension; -import org.spongepowered.asm.mixin.transformer.ext.ITargetClassContext; - -public class SugarApplicatorExtension implements IExtension { - @Override - public boolean checkActive(MixinEnvironment environment) { - return true; - } - - @Override - public void preApply(ITargetClassContext context) { - for (Pair pair : MixinInternals.getMixinsFor(context)) { - SugarInjector.prepareMixin(pair.getLeft(), pair.getRight()); - } - } - - @Override - public void postApply(ITargetClassContext context) { - } - - @Override - public void export(MixinEnvironment env, String name, boolean force, ClassNode classNode) { - } -} diff --git a/src/main/java/llamalad7/mixinextras/sugar/impl/SugarInjector.java b/src/main/java/llamalad7/mixinextras/sugar/impl/SugarInjector.java deleted file mode 100644 index 4582fe71d7..0000000000 --- a/src/main/java/llamalad7/mixinextras/sugar/impl/SugarInjector.java +++ /dev/null @@ -1,227 +0,0 @@ -package llamalad7.mixinextras.sugar.impl; - -import llamalad7.mixinextras.sugar.Local; -import llamalad7.mixinextras.utils.ASMUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.*; -import org.spongepowered.asm.mixin.extensibility.IMixinInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionNodes.InjectionNode; -import org.spongepowered.asm.mixin.injection.struct.Target; - -import java.util.*; -import java.util.stream.Collectors; - -class SugarInjector { - private static final String SUGAR_PACKAGE = Type.getDescriptor(Local.class).substring(0, Type.getDescriptor(Local.class).lastIndexOf('/') + 1); - private static final Set PREPARED_MIXINS = new HashSet<>(); - - private final InjectionInfo injectionInfo; - private final IMixinInfo mixin; - private Map> targets; - private String desugaredHandlerDesc; - private final MethodNode handler; - private final List sugarParams = new ArrayList<>(); - private final List> sugarParamAnnotations = new ArrayList<>(); - private final List applicators = new ArrayList<>(); - private final List exceptions = new ArrayList<>(); - - SugarInjector(InjectionInfo injectionInfo, IMixinInfo mixin, MethodNode handler) { - this.injectionInfo = injectionInfo; - this.mixin = mixin; - this.handler = handler; - } - - void setTargets(Map> targets) { - this.targets = targets; - } - - static void prepareMixin(IMixinInfo mixinInfo, ClassNode mixinNode) { - if (PREPARED_MIXINS.contains(mixinInfo.getClassName())) { - // Don't scan the whole class again. - return; - } - for (MethodNode method : mixinNode.methods) { - if (hasSugar(method)) { - wrapInjectorAnnotation(mixinInfo, method); - } - } - PREPARED_MIXINS.add(mixinInfo.getClassName()); - } - - private static boolean hasSugar(MethodNode method) { - List[] annotations = method.invisibleParameterAnnotations; - if (annotations == null) { - return false; - } - for (List paramAnnotations : annotations) { - if (paramAnnotations == null) { - continue; - } - for (AnnotationNode annotation : paramAnnotations) { - if (annotation.desc.startsWith(SUGAR_PACKAGE)) { - return true; - } - } - } - return false; - } - - private static void wrapInjectorAnnotation(IMixinInfo mixin, MethodNode method) { - AnnotationNode injectorAnnotation = InjectionInfo.getInjectorAnnotation(mixin, method); - if (injectorAnnotation == null) { - return; - } - AnnotationNode wrapped = new AnnotationNode(Type.getDescriptor(SugarWrapper.class)); - wrapped.visit("original", injectorAnnotation); - method.visibleAnnotations.remove(injectorAnnotation); - method.visibleAnnotations.add(wrapped); - } - - @SuppressWarnings("unchecked") - void stripSugar() { - List params = new ArrayList<>(); - List> invisibleAnnotations = new ArrayList<>(); - boolean foundSugar = false; - int i = 0; - for (Type type : Type.getArgumentTypes(handler.desc)) { - List annotations = handler.invisibleParameterAnnotations[i]; - if (annotations == null || annotations.stream().noneMatch(it -> it != null && it.desc.startsWith(SUGAR_PACKAGE))) { - if (foundSugar) { - throw new IllegalStateException(String.format("Found non-trailing sugared parameters on %s", handler.name + handler.desc)); - } - params.add(type); - invisibleAnnotations.add(annotations); - } else { - foundSugar = true; - sugarParams.add(type); - sugarParamAnnotations.add(annotations); - } - i++; - } - handler.invisibleParameterAnnotations = invisibleAnnotations.toArray(new List[0]); - handler.desc = Type.getMethodDescriptor(Type.getReturnType(handler.desc), params.toArray(new Type[0])); - desugaredHandlerDesc = handler.desc; - } - - void prepareSugar() { - for (Pair sugar : findSugars()) { - applicators.add(SugarApplicator.create(injectionInfo, sugar.getLeft(), sugar.getRight())); - } - for (SugarApplicator applicator : applicators) { - for (Map.Entry> entry : targets.entrySet()) { - Target target = entry.getKey(); - for (ListIterator it = entry.getValue().listIterator(); it.hasNext(); ) { - InjectionNode node = it.next(); - try { - applicator.validate(target, node); - } catch (SugarApplicationException e) { - exceptions.add( - new SugarApplicationException( - String.format( - "Failed to validate sugar %s on method %s from mixin %s in target method %s at instruction %s", - ASMUtils.annotationToString(applicator.sugar), handler.name + handler.desc, mixin, target, node - ), - e - ) - ); - it.remove(); - } - } - } - } - } - - void applySugar() { - reSugar(); - for (Target target : targets.keySet()) { - for (MethodInsnNode targetInsn : findHandlerCalls(target)) { - InjectionNode node = target.addInjectionNode(targetInsn); - try { - for (SugarApplicator applicator : applicators) { - applicator.preInject(target, node); - } - for (SugarApplicator applicator : applicators) { - applicator.inject(target, node); - } - } catch (Exception e) { - throw new SugarApplicationException( - String.format( - "Failed to apply sugar to method %s from mixin %s in target method %s at instruction %s", - handler.name + handler.desc, mixin, target, node - ), - e - ); - } - targetInsn.desc = handler.desc; - } - } - } - - List getExceptions() { - return exceptions; - } - - @SuppressWarnings("unchecked") - private void reSugar() { - List paramTypes = new ArrayList<>(Arrays.asList(Type.getArgumentTypes(handler.desc))); - List> paramAnnotations = (List>) (Object) new ArrayList<>( - Arrays.asList( - handler.invisibleParameterAnnotations == null ? new List[paramTypes.size()] : handler.invisibleParameterAnnotations - ) - ); - paramTypes.addAll(sugarParams); - paramAnnotations.addAll(sugarParamAnnotations); - handler.desc = Type.getMethodDescriptor(Type.getReturnType(handler.desc), paramTypes.toArray(new Type[0])); - handler.invisibleParameterAnnotations = paramAnnotations.toArray(new List[0]); - } - - private List findHandlerCalls(Target target) { - List result = new ArrayList<>(); - for (AbstractInsnNode insn : target) { - if (insn instanceof MethodInsnNode){ - MethodInsnNode call = (MethodInsnNode) insn; - if (call.owner.equals(target.classNode.name) && call.name.equals(handler.name) && call.desc.equals(desugaredHandlerDesc)) { - result.add(call); - } - } - } - return result; - } - - private List> findSugars() { - if (handler.invisibleParameterAnnotations == null) { - return Collections.emptyList(); - } - List> result = new ArrayList<>(); - int i = 0; - for (List annotationNodes : sugarParamAnnotations) { - AnnotationNode sugar = findSugar(annotationNodes); - if (sugar != null) { - result.add(Pair.of(sugarParams.get(i), sugar)); - } - i++; - } - return result; - } - - private AnnotationNode findSugar(List annotations) { - if (annotations == null) { - return null; - } - AnnotationNode result = null; - for (AnnotationNode annotation : annotations) { - if (annotation.desc.startsWith(SUGAR_PACKAGE)) { - if (result != null) { - throw new IllegalStateException( - "Found multiple sugars on the same parameter! Got " - + annotations.stream().map(ASMUtils::annotationToString).collect(Collectors.joining(" ")) - ); - } - result = annotation; - } - } - return result; - } -} diff --git a/src/main/java/llamalad7/mixinextras/sugar/impl/SugarWrapper.java b/src/main/java/llamalad7/mixinextras/sugar/impl/SugarWrapper.java deleted file mode 100644 index 294d956400..0000000000 --- a/src/main/java/llamalad7/mixinextras/sugar/impl/SugarWrapper.java +++ /dev/null @@ -1,8 +0,0 @@ -package llamalad7.mixinextras.sugar.impl; - -/** - * Used to wrap injector annotations if the handler methods have sugar. - * This allows us to do all the work from {@link SugarWrapperInjectionInfo}. - */ -@interface SugarWrapper { -} diff --git a/src/main/java/llamalad7/mixinextras/sugar/impl/SugarWrapperInjectionInfo.java b/src/main/java/llamalad7/mixinextras/sugar/impl/SugarWrapperInjectionInfo.java deleted file mode 100644 index 0ed66d24bc..0000000000 --- a/src/main/java/llamalad7/mixinextras/sugar/impl/SugarWrapperInjectionInfo.java +++ /dev/null @@ -1,108 +0,0 @@ -package llamalad7.mixinextras.sugar.impl; - -import llamalad7.mixinextras.injector.LateApplyingInjectorInfo; -import llamalad7.mixinextras.utils.CompatibilityHelper; -import llamalad7.mixinextras.utils.MixinInternals; -import org.objectweb.asm.tree.AnnotationNode; -import org.objectweb.asm.tree.MethodNode; -import org.spongepowered.asm.mixin.injection.code.Injector; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo.AnnotationType; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo.HandlerPrefix; -import org.spongepowered.asm.mixin.injection.throwables.InjectionError; -import org.spongepowered.asm.mixin.injection.throwables.InvalidInjectionException; -import org.spongepowered.asm.mixin.transformer.MixinTargetContext; -import org.spongepowered.asm.util.Annotations; - -@AnnotationType(SugarWrapper.class) -@HandlerPrefix("sugarWrapper") -public class SugarWrapperInjectionInfo extends InjectionInfo implements LateApplyingInjectorInfo { - private final InjectionInfo delegate; - private final AnnotationNode originalAnnotation; - private final SugarInjector sugarInjector; - private final boolean lateApply; - - public SugarWrapperInjectionInfo(MixinTargetContext mixin, MethodNode method, AnnotationNode annotation) { - super(mixin, method, annotation); - sugarInjector = new SugarInjector(this, mixin.getMixin(), method); - method.visibleAnnotations.remove(annotation); - method.visibleAnnotations.add(originalAnnotation = Annotations.getValue(annotation, "original")); - sugarInjector.stripSugar(); - delegate = InjectionInfo.parse(mixin, method); - sugarInjector.setTargets(MixinInternals.getTargets(delegate)); - lateApply = delegate instanceof LateApplyingInjectorInfo; - if (lateApply) { - ((LateApplyingInjectorInfo) delegate).wrap(this); - } - } - - @Override - protected void readAnnotation() { - } - - @Override - protected Injector parseInjector(AnnotationNode injectAnnotation) { - return null; - } - - @Override - public boolean isValid() { - return delegate.isValid(); - } - - @Override - public void prepare() { - delegate.prepare(); - method.visibleAnnotations.remove(originalAnnotation); - sugarInjector.prepareSugar(); - } - - // @Override on 0.8.3+ - @SuppressWarnings("unused") - public void preInject() { - CompatibilityHelper.preInject(delegate); - } - - @Override - public void inject() { - delegate.inject(); - } - - @Override - public void postInject() { - try { - delegate.postInject(); - } catch (InvalidInjectionException | InjectionError e) { - for (SugarApplicationException sugarException : sugarInjector.getExceptions()) { - e.addSuppressed(sugarException); - } - throw e; - } - if (!lateApply) { - sugarInjector.applySugar(); - } - } - - @Override - public void addCallbackInvocation(MethodNode handler) { - delegate.addCallbackInvocation(handler); - } - - @Override - public void lateApply() { - try { - ((LateApplyingInjectorInfo) delegate).lateApply(); - } catch (InvalidInjectionException | InjectionError e) { - for (SugarApplicationException sugarException : sugarInjector.getExceptions()) { - e.addSuppressed(sugarException); - } - throw e; - } - sugarInjector.applySugar(); - } - - @Override - public void wrap(LateApplyingInjectorInfo outer) { - throw new UnsupportedOperationException("Cannot wrap a sugar wrapper!"); - } -} diff --git a/src/main/java/llamalad7/mixinextras/utils/ASMUtils.java b/src/main/java/llamalad7/mixinextras/utils/ASMUtils.java deleted file mode 100644 index c7e6616321..0000000000 --- a/src/main/java/llamalad7/mixinextras/utils/ASMUtils.java +++ /dev/null @@ -1,58 +0,0 @@ -package llamalad7.mixinextras.utils; - -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.AnnotationNode; - -import java.util.List; -import java.util.stream.Collectors; - -public class ASMUtils { - public static String annotationToString(AnnotationNode annotation) { - StringBuilder builder = new StringBuilder("@").append(typeToString(Type.getType(annotation.desc))); - List values = annotation.values; - if (values.isEmpty()) { - return builder.toString(); - } - builder.append('('); - for (int i = 0; i < values.size(); i += 2) { - if (i != 0) { - builder.append(", "); - } - String name = (String) values.get(i); - Object value = values.get(i + 1); - builder.append(name).append(" = ").append(valueToString(value)); - } - builder.append(')'); - return builder.toString(); - } - - public static String typeToString(Type type) { - String name = type.getClassName(); - return name.substring(name.lastIndexOf('.') + 1).replace('$', '.'); - } - - private static String valueToString(Object value) { - if (value instanceof String) { - return '"' + value.toString() + '"'; - } - if (value instanceof Type) { - Type type = (Type) value; - return typeToString(type) + ".class"; - } - if (value instanceof String[]) { - String[] enumInfo = (String[]) value; - return typeToString(Type.getType(enumInfo[0])) + '.' + enumInfo[1]; - } - if (value instanceof AnnotationNode) { - return annotationToString((AnnotationNode) value); - } - if (value instanceof List) { - List list = (List) value; - if (list.size() == 1) { - return valueToString(list.get(0)); - } - return '{' + list.stream().map(ASMUtils::valueToString).collect(Collectors.joining(", ")) + '}'; - } - return value.toString(); - } -} diff --git a/src/main/java/llamalad7/mixinextras/utils/CompatibilityHelper.java b/src/main/java/llamalad7/mixinextras/utils/CompatibilityHelper.java deleted file mode 100644 index 533f21d59b..0000000000 --- a/src/main/java/llamalad7/mixinextras/utils/CompatibilityHelper.java +++ /dev/null @@ -1,96 +0,0 @@ -package llamalad7.mixinextras.utils; - -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.spongepowered.asm.mixin.injection.modify.LocalVariableDiscriminator.Context; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.Target; -import org.spongepowered.asm.mixin.injection.throwables.InvalidInjectionException; -import org.spongepowered.asm.mixin.refmap.IMixinContext; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; - -/** - * Helpers for writing code that is compatible with all variants of Mixin 0.8+ - */ -@SuppressWarnings("unchecked") -public class CompatibilityHelper { - private static final Constructor INVALID_INJECTION_EXCEPTION_CONSTRUCTOR; - private static final Method INJECTION_INFO_GET_MIXIN_METHOD; - private static final Constructor LVT_CONTEXT_CONSTRUCTOR; - private static final Method INJECTION_INFO_PRE_INJECT_METHOD; - - static { - INVALID_INJECTION_EXCEPTION_CONSTRUCTOR = - (Constructor) Arrays.stream(InvalidInjectionException.class.getConstructors()) - .filter(it -> { - Class[] parameters = it.getParameterTypes(); - return parameters.length == 2 && parameters[0].isAssignableFrom(InjectionInfo.class) && parameters[1] == String.class; - }) - .findAny() - .orElse(null); - - INJECTION_INFO_GET_MIXIN_METHOD = - Arrays.stream(InjectionInfo.class.getMethods()) - .filter(it -> it.getParameterTypes().length == 0 && it.getReturnType() == IMixinContext.class && it.getName().startsWith("get")) - .findAny() - .orElse(null); - - LVT_CONTEXT_CONSTRUCTOR = - (Constructor) Arrays.stream(Context.class.getConstructors()) - .filter(it -> { - Class[] parameters = it.getParameterTypes(); - int offset = parameters.length == 4 ? 0 : parameters.length == 5 ? 1 : -1; - if (offset == -1) { - return false; - } - return parameters[offset] == Type.class && parameters[offset + 1] == boolean.class && parameters[offset + 2] == Target.class && parameters[offset + 3] == AbstractInsnNode.class; - }) - .findAny() - .orElse(null); - - INJECTION_INFO_PRE_INJECT_METHOD = Arrays.stream(InjectionInfo.class.getMethods()) - .filter(it -> it.getName().equals("preInject")) - .findFirst() - .orElse(null); - } - - public static RuntimeException makeInvalidInjectionException(InjectionInfo info, String message) { - try { - return INVALID_INJECTION_EXCEPTION_CONSTRUCTOR.newInstance(info, message); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - - public static IMixinContext getMixin(InjectionInfo info) { - try { - return (IMixinContext) INJECTION_INFO_GET_MIXIN_METHOD.invoke(info); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - - public static Context makeLvtContext(InjectionInfo info, Type returnType, boolean argsOnly, Target target, AbstractInsnNode node) { - try { - if (LVT_CONTEXT_CONSTRUCTOR.getParameterCount() == 4) { - return LVT_CONTEXT_CONSTRUCTOR.newInstance(returnType, argsOnly, target, node); - } else { - return LVT_CONTEXT_CONSTRUCTOR.newInstance(info, returnType, argsOnly, target, node); - } - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - - public static void preInject(InjectionInfo info) { - try { - INJECTION_INFO_PRE_INJECT_METHOD.invoke(info); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } -} diff --git a/src/main/java/llamalad7/mixinextras/utils/InjectorUtils.java b/src/main/java/llamalad7/mixinextras/utils/InjectorUtils.java deleted file mode 100644 index 18297da6ee..0000000000 --- a/src/main/java/llamalad7/mixinextras/utils/InjectorUtils.java +++ /dev/null @@ -1,22 +0,0 @@ -package llamalad7.mixinextras.utils; - -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.spongepowered.asm.mixin.injection.struct.InjectionNodes; - -public class InjectorUtils { - public static boolean isVirtualRedirect(InjectionNodes.InjectionNode node) { - return node.isReplaced() && node.hasDecoration("redirector") && node.getCurrentTarget().getOpcode() != Opcodes.INVOKESTATIC; - } - - public static boolean isDynamicInstanceofRedirect(InjectionNodes.InjectionNode node) { - AbstractInsnNode originalTarget = node.getOriginalTarget(); - AbstractInsnNode currentTarget = node.getCurrentTarget(); - - return originalTarget.getOpcode() == Opcodes.INSTANCEOF - && currentTarget instanceof MethodInsnNode - && Type.getReturnType(((MethodInsnNode) currentTarget).desc).equals(Type.getType(Class.class)); - } -} diff --git a/src/main/java/llamalad7/mixinextras/utils/MixinInternals.java b/src/main/java/llamalad7/mixinextras/utils/MixinInternals.java deleted file mode 100644 index c3b1a2c898..0000000000 --- a/src/main/java/llamalad7/mixinextras/utils/MixinInternals.java +++ /dev/null @@ -1,113 +0,0 @@ -package llamalad7.mixinextras.utils; - -import org.apache.commons.lang3.tuple.Pair; -import org.objectweb.asm.tree.ClassNode; -import org.spongepowered.asm.mixin.MixinEnvironment; -import org.spongepowered.asm.mixin.extensibility.IMixinInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionInfo; -import org.spongepowered.asm.mixin.injection.struct.InjectionNodes.InjectionNode; -import org.spongepowered.asm.mixin.injection.struct.Target; -import org.spongepowered.asm.mixin.transformer.IMixinTransformer; -import org.spongepowered.asm.mixin.transformer.ext.Extensions; -import org.spongepowered.asm.mixin.transformer.ext.IExtension; -import org.spongepowered.asm.mixin.transformer.ext.ITargetClassContext; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.*; - -/** - * Mumfrey, look away. - */ -public class MixinInternals { - private static final Field TARGET_CLASS_CONTEXT_MIXINS_FIELD; - private static final Method MIXIN_INFO_GET_STATE_METHOD; - private static final Field STATE_CLASS_NODE_FIELD; - private static final Field EXTENSIONS_FIELD; - private static final Field ACTIVE_EXTENSIONS_FIELD; - private static final Field INJECTION_INFO_TARGET_NODES_FIELD; - - static { - try { - Class TargetClassContext = Class.forName("org.spongepowered.asm.mixin.transformer.TargetClassContext"); - TARGET_CLASS_CONTEXT_MIXINS_FIELD = TargetClassContext.getDeclaredField("mixins"); - TARGET_CLASS_CONTEXT_MIXINS_FIELD.setAccessible(true); - Class MixinInfo = Class.forName("org.spongepowered.asm.mixin.transformer.MixinInfo"); - MIXIN_INFO_GET_STATE_METHOD = MixinInfo.getDeclaredMethod("getState"); - MIXIN_INFO_GET_STATE_METHOD.setAccessible(true); - Class State = Class.forName("org.spongepowered.asm.mixin.transformer.MixinInfo$State"); - STATE_CLASS_NODE_FIELD = State.getDeclaredField("classNode"); - STATE_CLASS_NODE_FIELD.setAccessible(true); - INJECTION_INFO_TARGET_NODES_FIELD = InjectionInfo.class.getDeclaredField("targetNodes"); - INJECTION_INFO_TARGET_NODES_FIELD.setAccessible(true); - EXTENSIONS_FIELD = Extensions.class.getDeclaredField("extensions"); - EXTENSIONS_FIELD.setAccessible(true); - ACTIVE_EXTENSIONS_FIELD = Extensions.class.getDeclaredField("activeExtensions"); - ACTIVE_EXTENSIONS_FIELD.setAccessible(true); - } catch (ClassNotFoundException | NoSuchFieldException | NoSuchMethodException e) { - throw new RuntimeException("Failed to access some mixin internals, please report to LlamaLad7!", e); - } - } - - @SuppressWarnings("unchecked") - public static List> getMixinsFor(ITargetClassContext context) { - try { - List> result = new ArrayList<>(); - SortedSet mixins = (SortedSet) TARGET_CLASS_CONTEXT_MIXINS_FIELD.get(context); - for (IMixinInfo mixin : mixins) { - Object state = MIXIN_INFO_GET_STATE_METHOD.invoke(mixin); - ClassNode classNode = (ClassNode) STATE_CLASS_NODE_FIELD.get(state); - result.add(Pair.of(mixin, classNode)); - } - return result; - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException("Failed to use mixin internals, please report to LlamaLad7!", e); - } - } - - @SuppressWarnings("unchecked") - public static Map> getTargets(InjectionInfo info) { - try { - return (Map>) INJECTION_INFO_TARGET_NODES_FIELD.get(info); - } catch (IllegalAccessException e) { - throw new RuntimeException("Failed to use mixin internals, please report to LlamaLad7!", e); - } - } - - @SuppressWarnings("unchecked") - public static void registerExtension(IExtension extension) { - try { - IMixinTransformer transformer = (IMixinTransformer) MixinEnvironment.getDefaultEnvironment().getActiveTransformer(); - Extensions extensions = (Extensions) transformer.getExtensions(); - List extensionsList = (List) EXTENSIONS_FIELD.get(extensions); - addExtension(extensionsList, extension); - List activeExtensions = new ArrayList<>((List) ACTIVE_EXTENSIONS_FIELD.get(extensions)); - addExtension(activeExtensions, extension); - ACTIVE_EXTENSIONS_FIELD.set(extensions, Collections.unmodifiableList(activeExtensions)); - } catch (IllegalAccessException e) { - throw new RuntimeException("Failed to use mixin internals, please report to LlamaLad7!", e); - } - } - - /** - * This keeps the extensions in "groups", because when there are multiple relocated versions active that's the - * behaviour we want. - */ - private static void addExtension(List extensions, IExtension newExtension) { - String extensionClassName = newExtension.getClass().getName(); - extensionClassName = extensionClassName.substring(extensionClassName.lastIndexOf('.')); - int index = -1; - for (int i = 0; i < extensions.size(); i++) { - IExtension extension = extensions.get(i); - if (extension.getClass().getName().endsWith(extensionClassName)) { - index = i; - } - } - if (index == -1) { - extensions.add(newExtension); - } else { - extensions.add(index + 1, newExtension); - } - } -} diff --git a/src/main/java/net/coderbot/batchedentityrendering/impl/FullyBufferedMultiBufferSource.java b/src/main/java/net/coderbot/batchedentityrendering/impl/FullyBufferedMultiBufferSource.java index ac982c5381..ed0a119af2 100644 --- a/src/main/java/net/coderbot/batchedentityrendering/impl/FullyBufferedMultiBufferSource.java +++ b/src/main/java/net/coderbot/batchedentityrendering/impl/FullyBufferedMultiBufferSource.java @@ -10,13 +10,7 @@ import net.minecraft.client.renderer.RenderType; import net.minecraft.util.profiling.ProfilerFiller; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.function.Function; public class FullyBufferedMultiBufferSource extends MultiBufferSource.BufferSource implements MemoryTrackingBuffer, Groupable, WrappingMultiBufferSource { @@ -55,8 +49,14 @@ public FullyBufferedMultiBufferSource() { this.wrappingFunctionStack = new ArrayList<>(); } + private boolean isReady; + private Map> typeToSegment = new HashMap<>(); + private List renderOrder = new ArrayList<>(); + @Override public VertexConsumer getBuffer(RenderType renderType) { + removeReady(); + if (wrappingFunction != null) { renderType = wrappingFunction.apply(renderType); } @@ -87,14 +87,19 @@ public VertexConsumer getBuffer(RenderType renderType) { return builders[affinity].getBuffer(renderType); } - @Override - public void endBatch() { + private void removeReady() { + isReady = false; + typeToSegment.clear(); + renderOrder.clear(); + } + + public void readyUp() { + isReady = true; + ProfilerFiller profiler = Minecraft.getInstance().getProfiler(); profiler.push("collect"); - Map> typeToSegment = new HashMap<>(); - for (SegmentedBufferBuilder builder : builders) { List segments = builder.getSegments(); @@ -105,9 +110,21 @@ public void endBatch() { profiler.popPush("resolve ordering"); - Iterable renderOrder = renderOrderManager.getRenderOrder(); + renderOrder = renderOrderManager.getRenderOrder(); + + renderOrderManager.reset(); + affinities.clear(); + + profiler.pop(); + } + + @Override + public void endBatch() { + ProfilerFiller profiler = Minecraft.getInstance().getProfiler(); - profiler.popPush("draw buffers"); + if (!isReady) readyUp(); + + profiler.push("draw buffers"); for (RenderType type : renderOrder) { type.setupRenderState(); @@ -124,8 +141,44 @@ public void endBatch() { profiler.popPush("reset"); - renderOrderManager.reset(); - affinities.clear(); + removeReady(); + + profiler.pop(); + } + + public void endBatchWithType(TransparencyType transparencyType) { + ProfilerFiller profiler = Minecraft.getInstance().getProfiler(); + + if (!isReady) readyUp(); + + profiler.push("draw buffers"); + + List types = new ArrayList<>(); + + for (RenderType type : renderOrder) { + if (((BlendingStateHolder) type).getTransparencyType() != transparencyType) { + continue; + } + + types.add(type); + + type.setupRenderState(); + + renderTypes += 1; + + for (BufferSegment segment : typeToSegment.getOrDefault(type, Collections.emptyList())) { + segmentRenderer.drawInner(segment); + drawCalls += 1; + } + + typeToSegment.remove(type); + + type.clearRenderState(); + } + + profiler.popPush("reset type " + transparencyType); + + renderOrder.removeAll(types); profiler.pop(); } diff --git a/src/main/java/net/coderbot/batchedentityrendering/impl/SegmentedBufferBuilder.java b/src/main/java/net/coderbot/batchedentityrendering/impl/SegmentedBufferBuilder.java index f46c164862..6a38f13bee 100644 --- a/src/main/java/net/coderbot/batchedentityrendering/impl/SegmentedBufferBuilder.java +++ b/src/main/java/net/coderbot/batchedentityrendering/impl/SegmentedBufferBuilder.java @@ -84,6 +84,46 @@ public List getSegments() { return segments; } + public List getSegmentsForType(TransparencyType transparencyType) { + if (currentType == null) { + return Collections.emptyList(); + } + + if (((BlendingStateHolder) currentType).getTransparencyType() == transparencyType) { + usedTypes.add(currentType); + + if (shouldSortOnUpload(currentType)) { + buffer.setQuadSortOrigin(0, 0, 0); + } + + buffer.end(); + currentType = null; + } + + List segments = new ArrayList<>(usedTypes.size()); + + List types = new ArrayList<>(); + + for (RenderType type : usedTypes) { + if (((BlendingStateHolder) type).getTransparencyType() != transparencyType) { + continue; + } + + types.add(type); + + Pair pair = buffer.popNextBuffer(); + + BufferBuilder.DrawState parameters = pair.getFirst(); + ByteBuffer slice = pair.getSecond(); + + segments.add(new BufferSegment(slice, parameters, type)); + } + + usedTypes.removeAll(types); + + return segments; + } + private static boolean shouldSortOnUpload(RenderType type) { return ((RenderTypeAccessor) type).shouldSortOnUpload(); } diff --git a/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/GraphTranslucencyRenderOrderManager.java b/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/GraphTranslucencyRenderOrderManager.java index dd28ed3763..6eae98ee0c 100644 --- a/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/GraphTranslucencyRenderOrderManager.java +++ b/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/GraphTranslucencyRenderOrderManager.java @@ -102,7 +102,13 @@ public void reset() { } } - public Iterable getRenderOrder() { + @Override + public void resetType(TransparencyType type) { + // TODO: Is reallocation efficient? + types.put(type, new MapDigraph<>()); + } + + public List getRenderOrder() { int layerCount = 0; for (Digraph graph : types.values()) { diff --git a/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/RenderOrderManager.java b/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/RenderOrderManager.java index 6e6c6407db..6756fe048b 100644 --- a/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/RenderOrderManager.java +++ b/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/RenderOrderManager.java @@ -1,12 +1,18 @@ package net.coderbot.batchedentityrendering.impl.ordering; +import net.coderbot.batchedentityrendering.impl.TransparencyType; import net.minecraft.client.renderer.RenderType; +import java.util.List; + public interface RenderOrderManager { void begin(RenderType type); void startGroup(); boolean maybeStartGroup(); void endGroup(); void reset(); - Iterable getRenderOrder(); + + void resetType(TransparencyType type); + + List getRenderOrder(); } diff --git a/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/SimpleRenderOrderManager.java b/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/SimpleRenderOrderManager.java index 1ab6f1480a..8396f2fd97 100644 --- a/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/SimpleRenderOrderManager.java +++ b/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/SimpleRenderOrderManager.java @@ -1,8 +1,10 @@ package net.coderbot.batchedentityrendering.impl.ordering; +import net.coderbot.batchedentityrendering.impl.TransparencyType; import net.minecraft.client.renderer.RenderType; import java.util.LinkedHashSet; +import java.util.List; public class SimpleRenderOrderManager implements RenderOrderManager { private final LinkedHashSet renderTypes; @@ -33,7 +35,12 @@ public void reset() { renderTypes.clear(); } - public Iterable getRenderOrder() { - return renderTypes; + @Override + public void resetType(TransparencyType type) { + + } + + public List getRenderOrder() { + return List.copyOf(renderTypes); } } diff --git a/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/TranslucencyRenderOrderManager.java b/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/TranslucencyRenderOrderManager.java index 2c255781b8..2b459e262f 100644 --- a/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/TranslucencyRenderOrderManager.java +++ b/src/main/java/net/coderbot/batchedentityrendering/impl/ordering/TranslucencyRenderOrderManager.java @@ -58,7 +58,12 @@ public void reset() { }); } - public Iterable getRenderOrder() { + @Override + public void resetType(TransparencyType type) { + renderTypes.get(type).clear(); + } + + public List getRenderOrder() { int layerCount = 0; for (LinkedHashSet set : renderTypes.values()) { diff --git a/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinBufferBuilder.java b/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinBufferBuilder.java index 684df95592..cf04f98421 100644 --- a/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinBufferBuilder.java +++ b/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinBufferBuilder.java @@ -25,7 +25,8 @@ public int getUsedSize() { @Override public void freeAndDeleteBuffer() { - MemoryUtil.memFree(buffer); + if (buffer == null) return; + MemoryUtil.getAllocator(false).free(MemoryUtil.memAddress(buffer)); buffer = null; } } diff --git a/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinDebugScreenOverlay.java b/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinDebugScreenOverlay.java index 42ef6ff65f..c33e02197e 100644 --- a/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinDebugScreenOverlay.java +++ b/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinDebugScreenOverlay.java @@ -2,6 +2,7 @@ import net.coderbot.batchedentityrendering.impl.BatchingDebugMessageHelper; import net.coderbot.batchedentityrendering.impl.DrawCallTrackingRenderBuffers; +import net.coderbot.iris.Iris; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.DebugScreenOverlay; import org.spongepowered.asm.mixin.Mixin; @@ -25,7 +26,9 @@ public abstract class MixinDebugScreenOverlay { DrawCallTrackingRenderBuffers drawTracker = (DrawCallTrackingRenderBuffers) Minecraft.getInstance().renderBuffers(); // blank line separator - messages.add(""); - messages.add("[Entity Batching] " + BatchingDebugMessageHelper.getDebugMessage(drawTracker)); + if (Iris.getIrisConfig().areDebugOptionsEnabled()) { + messages.add(""); + messages.add("[Entity Batching] " + BatchingDebugMessageHelper.getDebugMessage(drawTracker)); + } } } diff --git a/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinLevelRenderer.java b/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinLevelRenderer.java index b58d683323..5c9ff62023 100644 --- a/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinLevelRenderer.java +++ b/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinLevelRenderer.java @@ -3,8 +3,11 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix4f; import net.coderbot.batchedentityrendering.impl.DrawCallTrackingRenderBuffers; +import net.coderbot.batchedentityrendering.impl.FullyBufferedMultiBufferSource; import net.coderbot.batchedentityrendering.impl.Groupable; import net.coderbot.batchedentityrendering.impl.RenderBuffersExt; +import net.coderbot.batchedentityrendering.impl.TransparencyType; +import net.coderbot.iris.block_rendering.BlockRenderingSettings; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GameRenderer; @@ -66,8 +69,29 @@ public class MixinLevelRenderer { @Inject(method = "renderLevel", at = @At(value = "CONSTANT", args = "stringValue=translucent"), locals = LocalCapture.CAPTURE_FAILHARD) private void batchedentityrendering$beginTranslucents(PoseStack poseStack, float f, long l, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci) { - Minecraft.getInstance().getProfiler().popPush("entity_draws"); - this.renderBuffers.bufferSource().endBatch(); + if (renderBuffers.bufferSource() instanceof FullyBufferedMultiBufferSource fullyBufferedMultiBufferSource) { + fullyBufferedMultiBufferSource.readyUp(); + } + + if (BlockRenderingSettings.INSTANCE.shouldSeparateEntityDraws()) { + Minecraft.getInstance().getProfiler().popPush("entity_draws_opaque"); + if (renderBuffers.bufferSource() instanceof FullyBufferedMultiBufferSource source) { + source.endBatchWithType(TransparencyType.OPAQUE); + } else { + this.renderBuffers.bufferSource().endBatch(); + } + } else { + Minecraft.getInstance().getProfiler().popPush("entity_draws"); + this.renderBuffers.bufferSource().endBatch(); + } + } + + + @Inject(method = "renderLevel", at = @At(value = "CONSTANT", args = "stringValue=translucent", shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD) + private void batchedentityrendering$endTranslucents(PoseStack poseStack, float f, long l, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci) { + if (BlockRenderingSettings.INSTANCE.shouldSeparateEntityDraws()) { + this.renderBuffers.bufferSource().endBatch(); + } } @Inject(method = "renderLevel", at = @At("RETURN")) diff --git a/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinLevelRenderer_EntityListSorting.java b/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinLevelRenderer_EntityListSorting.java index 60b98aaa4d..306ccb07fe 100644 --- a/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinLevelRenderer_EntityListSorting.java +++ b/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinLevelRenderer_EntityListSorting.java @@ -10,37 +10,34 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Slice; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Sorts the entity list to allow entities of the same type to be properly batched. Without sorting, entities are * essentially rendered in random order, which makes it harder for entity batching to work properly. - * + *

* Sorting reduces the number of RenderTypes that need to be active at any given time for batching to be effective. * For example, instead of the batching system needing to be prepared to render a pig at any time, it can know that * every pig is being rendered all at once, then it can use unused space within the buffer previously used for pigs for * something else. - * + *

* This is even more effective with vanilla's entity rendering, since it only has a single buffer for most purposes, * except for a configured set of batched render types. - * + *

* This injection point has been carefully chosen to avoid conflicts with other mixins such as one from Carpet: - * https://github.com/gnembon/fabric-carpet/blob/776f798aecb792a5881ccae8784888156207a047/src/main/java/carpet/mixins/WorldRenderer_pausedShakeMixin.java#L23 - * + * https://github.com/gnembon/fabric-carpet/blob/776f798aecb792a5881ccae8784888156207a047/src/main/java/carpet/mixins + * /WorldRenderer_pausedShakeMixin.java#L23 + *

* By using ModifyVariable instead of Redirect, it is more likely to be compatible with other rendering mods. We also * use a priority of 999 to apply before most other mixins to this method, meaning that other mods adding entities to * the rendering list (like Twilight Forest) are more likely to have these added entities sorted. */ @Mixin(value = LevelRenderer.class, priority = 999) public class MixinLevelRenderer_EntityListSorting { - @Shadow - private ClientLevel level; + @Shadow + private ClientLevel level; - @ModifyVariable(method = "renderLevel", at = @At(value = "INVOKE_ASSIGN", target = "Ljava/lang/Iterable;iterator()Ljava/util/Iterator;"), + @ModifyVariable(method = "renderLevel", at = @At(value = "STORE"), slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBuffers;bufferSource()Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;"), to = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;shouldRender(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/client/renderer/culling/Frustum;DDD)Z")), allow = 1) private Iterator batchedentityrendering$sortEntityList(Iterator iterator) { diff --git a/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinRenderType.java b/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinRenderType.java new file mode 100644 index 0000000000..be8d8ae3ca --- /dev/null +++ b/src/main/java/net/coderbot/batchedentityrendering/mixin/MixinRenderType.java @@ -0,0 +1,15 @@ +package net.coderbot.batchedentityrendering.mixin; + +import net.coderbot.batchedentityrendering.impl.BlendingStateHolder; +import net.coderbot.batchedentityrendering.impl.TransparencyType; +import net.minecraft.client.renderer.RenderType; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(RenderType.class) +public class MixinRenderType implements BlendingStateHolder { + // Fallback + @Override + public TransparencyType getTransparencyType() { + return TransparencyType.GENERAL_TRANSPARENT; + } +} diff --git a/src/main/java/net/coderbot/iris/Iris.java b/src/main/java/net/coderbot/iris/Iris.java index b1991ea0d9..09503eff5e 100644 --- a/src/main/java/net/coderbot/iris/Iris.java +++ b/src/main/java/net/coderbot/iris/Iris.java @@ -1,30 +1,8 @@ package net.coderbot.iris; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.file.FileSystem; -import java.nio.file.FileSystemNotFoundException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.InvalidPathException; -import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.Properties; -import java.util.stream.Stream; -import java.util.zip.ZipError; -import java.util.zip.ZipException; - -import org.jetbrains.annotations.NotNull; -import org.lwjgl.glfw.GLFW; - import com.google.common.base.Throwables; import com.mojang.blaze3d.platform.GlDebug; import com.mojang.blaze3d.platform.InputConstants; - import net.coderbot.iris.config.IrisConfig; import net.coderbot.iris.gl.GLDebug; import net.coderbot.iris.gl.shader.StandardMacros; @@ -38,6 +16,7 @@ import net.coderbot.iris.shaderpack.ProgramSet; import net.coderbot.iris.shaderpack.ShaderPack; import net.coderbot.iris.shaderpack.discovery.ShaderpackDirectoryManager; +import net.coderbot.iris.shaderpack.materialmap.NamespacedId; import net.coderbot.iris.shaderpack.option.OptionSet; import net.coderbot.iris.shaderpack.option.Profile; import net.coderbot.iris.shaderpack.option.values.MutableOptionValues; @@ -47,8 +26,8 @@ import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.level.dimension.DimensionType; import net.minecraftforge.client.ClientRegistry; import net.minecraftforge.common.ForgeConfig; import net.minecraftforge.fml.IExtensionPoint; @@ -60,6 +39,20 @@ import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLPaths; import net.minecraftforge.network.NetworkConstants; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.glfw.GLFW; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Properties; +import java.util.stream.Stream; +import java.util.zip.ZipError; +import java.util.zip.ZipException; @Mod(Iris.MODID) public class Iris { @@ -88,6 +81,7 @@ public class Iris { private static KeyMapping reloadKeybind; private static KeyMapping toggleShadersKeybind; private static KeyMapping shaderpackScreenKeybind; + private static KeyMapping wireframeKeybind; private static final Map shaderPackOptionQueue = new HashMap<>(); // Flag variable used when reloading @@ -97,11 +91,11 @@ public class Iris { private static String IRIS_VERSION; private static boolean fallback; - + public Iris() { try { FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onInitializeClient); - + ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> NetworkConstants.IGNORESERVERONLY, (a, b) -> true)); }catch(Exception e) {} } @@ -137,18 +131,20 @@ public void onEarlyInitialize() { reloadKeybind = new KeyMapping("iris.keybind.reload", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_R, "iris.keybinds"); toggleShadersKeybind = new KeyMapping("iris.keybind.toggleShaders", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_K, "iris.keybinds"); shaderpackScreenKeybind = new KeyMapping("iris.keybind.shaderPackSelection", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_O, "iris.keybinds"); + wireframeKeybind = new KeyMapping("iris.keybind.wireframe", InputConstants.Type.KEYSYM, InputConstants.UNKNOWN.getValue(), "iris.keybinds"); setupCommands(Minecraft.getInstance()); initialized = true; } - + public void onInitializeClient(final FMLClientSetupEvent event) { IRIS_VERSION = ModList.get().getModContainerById(MODID).get().getModInfo().getVersion().toString(); ClientRegistry.registerKeyBinding(reloadKeybind); ClientRegistry.registerKeyBinding(toggleShadersKeybind); - ClientRegistry.registerKeyBinding(shaderpackScreenKeybind); - + ClientRegistry.registerKeyBinding(shaderpackScreenKeybind); + ClientRegistry.registerKeyBinding(wireframeKeybind); + ForgeConfig.CLIENT.experimentalForgeLightPipelineEnabled.set(false); } @@ -196,14 +192,16 @@ public static void onRenderSystemInit() { return; } - setDebug(irisConfig.areDebugOptionsEnabled()); - PBRTextureManager.INSTANCE.init(); // Only load the shader pack when we can access OpenGL loadShaderpack(); } + public static void duringRenderSystemInit() { + setDebug(irisConfig.areDebugOptionsEnabled()); + } + /** * Called when the title screen is initialized for the first time. */ @@ -251,9 +249,17 @@ public static void handleKeybinds(Minecraft minecraft) { } } else if (shaderpackScreenKeybind.consumeClick()) { minecraft.setScreen(new ShaderPackScreen(null)); + } else if (wireframeKeybind.consumeClick()) { + if (irisConfig.areDebugOptionsEnabled() && minecraft.player != null && !Minecraft.getInstance().isLocalServer()) { + minecraft.player.displayClientMessage(new TextComponent("No cheating; wireframe only in singleplayer!"), false); + } } } + public static boolean shouldActivateWireframe() { + return irisConfig.areDebugOptionsEnabled() && wireframeKeybind.isDown(); + } + public static void toggleShaders(Minecraft minecraft, boolean enabled) throws IOException { irisConfig.setShadersEnabled(enabled); irisConfig.save(); @@ -285,7 +291,7 @@ public static void loadShaderpack() { // Attempt to load an external shaderpack if it is available Optional externalName = irisConfig.getShaderPackName(); - if (!externalName.isPresent()) { + if (externalName.isEmpty()) { logger.info("Shaders are disabled because no valid shaderpack is selected"); setShadersDisabled(); @@ -313,9 +319,14 @@ private static boolean loadExternalShaderpack(String name) { return false; } + if (!isValidShaderpack(shaderPackRoot)) { + logger.error("Pack \"{}\" is not valid! Can't load it.", name); + return false; + } + Path shaderPackPath; - if (shaderPackRoot.toString().endsWith(".zip")) { + if (!Files.isDirectory(shaderPackRoot) && shaderPackRoot.toString().endsWith(".zip")) { Optional optionalPath; try { @@ -429,7 +440,7 @@ private static void setShadersDisabled() { logger.info("Shaders are disabled"); } - private static void setDebug(boolean enable) { + public static void setDebug(boolean enable) { int success; if (enable) { success = GLDebug.setupDebugMessageCallback(); @@ -490,6 +501,10 @@ private static void tryUpdateConfigPropertiesFile(Path path, Properties properti } } + public static boolean isValidToShowPack(Path pack) { + return Files.isDirectory(pack) || pack.toString().endsWith(".zip"); + } + public static boolean isValidShaderpack(Path pack) { if (Files.isDirectory(pack)) { // Sometimes the shaderpack directory itself can be @@ -508,6 +523,7 @@ public static boolean isValidShaderpack(Path pack) { .anyMatch(path -> path.endsWith("shaders")); } catch (IOException ignored) { // ignored, not a valid shader pack. + return false; } } @@ -618,19 +634,13 @@ private static void destroyEverything() { } } - public static DimensionId lastDimension = null; + public static NamespacedId lastDimension = null; - public static DimensionId getCurrentDimension() { + public static NamespacedId getCurrentDimension() { ClientLevel level = Minecraft.getInstance().level; if (level != null) { - if (level.dimensionType().effectsLocation().equals(DimensionType.END_EFFECTS) || level.dimension().equals(net.minecraft.world.level.Level.END)) { - return DimensionId.END; - } else if (level.dimensionType().effectsLocation().equals(DimensionType.NETHER_EFFECTS) || level.dimension().equals(net.minecraft.world.level.Level.NETHER)) { - return DimensionId.NETHER; - } else { - return DimensionId.OVERWORLD; - } + return new NamespacedId(level.dimension().location().getNamespace(), level.dimension().location().getPath()); } else { // This prevents us from reloading the shaderpack unless we need to. Otherwise, if the player is in the // nether and quits the game, we might end up reloading the shaders on exit and on entry to the level @@ -639,7 +649,7 @@ public static DimensionId getCurrentDimension() { } } - private static WorldRenderingPipeline createPipeline(DimensionId dimensionId) { + private static WorldRenderingPipeline createPipeline(NamespacedId dimensionId) { if (currentPack == null) { // Completely disables shader-based rendering return new FixedFunctionWorldRenderingPipeline(); diff --git a/src/main/java/net/coderbot/iris/apiimpl/IrisApiV0Impl.java b/src/main/java/net/coderbot/iris/apiimpl/IrisApiV0Impl.java index 75df3089a8..f814d6bb80 100644 --- a/src/main/java/net/coderbot/iris/apiimpl/IrisApiV0Impl.java +++ b/src/main/java/net/coderbot/iris/apiimpl/IrisApiV0Impl.java @@ -20,7 +20,7 @@ public class IrisApiV0Impl implements IrisApi { @Override public int getMinorApiRevision() { - return 1; + return 2; } @Override @@ -58,4 +58,15 @@ public IrisApiConfig getConfig() { public IrisTextVertexSink createTextVertexSink(int maxQuadCount, IntFunction bufferProvider) { return new IrisTextVertexSinkImpl(maxQuadCount, bufferProvider); } + + @Override + public float getSunPathRotation() { + WorldRenderingPipeline pipeline = Iris.getPipelineManager().getPipelineNullable(); + + if (pipeline == null) { + return 0; + } + + return pipeline.getSunPathRotation(); + } } diff --git a/src/main/java/net/coderbot/iris/block_rendering/BlockRenderingSettings.java b/src/main/java/net/coderbot/iris/block_rendering/BlockRenderingSettings.java index 3087cb82c6..b99729bf5b 100644 --- a/src/main/java/net/coderbot/iris/block_rendering/BlockRenderingSettings.java +++ b/src/main/java/net/coderbot/iris/block_rendering/BlockRenderingSettings.java @@ -17,10 +17,14 @@ public class BlockRenderingSettings { private Object2IntMap blockStateIds; private Map blockTypeIds; private Object2IntFunction entityIds; + private Object2IntFunction itemIds; private float ambientOcclusionLevel; private boolean disableDirectionalShading; + private boolean hasVillagerConversionId; private boolean useSeparateAo; private boolean useExtendedVertexFormat; + private boolean separateEntityDraws; + private boolean voxelizeLightBlocks; public BlockRenderingSettings() { reloadRequired = false; @@ -30,6 +34,9 @@ public BlockRenderingSettings() { disableDirectionalShading = false; useSeparateAo = false; useExtendedVertexFormat = false; + separateEntityDraws = false; + voxelizeLightBlocks = false; + hasVillagerConversionId = false; } public boolean isReloadRequired() { @@ -56,6 +63,11 @@ public Object2IntFunction getEntityIds() { return entityIds; } + @Nullable + public Object2IntFunction getItemIds() { + return itemIds; + } + public void setBlockStateIds(Object2IntMap blockStateIds) { if (this.blockStateIds != null && this.blockStateIds.equals(blockStateIds)) { return; @@ -77,6 +89,12 @@ public void setBlockTypeIds(Map blockTypeIds) { public void setEntityIds(Object2IntFunction entityIds) { // note: no reload needed, entities are rebuilt every frame. this.entityIds = entityIds; + this.hasVillagerConversionId = entityIds.containsKey(new NamespacedId("minecraft", "zombie_villager_converting")); + } + + public void setItemIds(Object2IntFunction itemIds) { + // note: no reload needed, entities are rebuilt every frame. + this.itemIds = itemIds; } public float getAmbientOcclusionLevel() { @@ -130,4 +148,29 @@ public void setUseExtendedVertexFormat(boolean useExtendedVertexFormat) { this.reloadRequired = true; this.useExtendedVertexFormat = useExtendedVertexFormat; } + + public boolean shouldVoxelizeLightBlocks() { + return voxelizeLightBlocks; + } + + public void setVoxelizeLightBlocks(boolean voxelizeLightBlocks) { + if (voxelizeLightBlocks == this.voxelizeLightBlocks) { + return; + } + + this.reloadRequired = true; + this.voxelizeLightBlocks = voxelizeLightBlocks; + } + + public boolean shouldSeparateEntityDraws() { + return separateEntityDraws; + } + + public void setSeparateEntityDraws(boolean separateEntityDraws) { + this.separateEntityDraws = separateEntityDraws; + } + + public boolean hasVillagerConversionId() { + return hasVillagerConversionId; + } } diff --git a/src/main/java/net/coderbot/iris/colorspace/ColorSpace.java b/src/main/java/net/coderbot/iris/colorspace/ColorSpace.java new file mode 100644 index 0000000000..6a94b4bf2b --- /dev/null +++ b/src/main/java/net/coderbot/iris/colorspace/ColorSpace.java @@ -0,0 +1,9 @@ +package net.coderbot.iris.colorspace; + +public enum ColorSpace { + SRGB, + DCI_P3, + DISPLAY_P3, + REC2020, + ADOBE_RGB +} diff --git a/src/main/java/net/coderbot/iris/colorspace/ColorSpaceComputeConverter.java b/src/main/java/net/coderbot/iris/colorspace/ColorSpaceComputeConverter.java new file mode 100644 index 0000000000..eed32b0860 --- /dev/null +++ b/src/main/java/net/coderbot/iris/colorspace/ColorSpaceComputeConverter.java @@ -0,0 +1,70 @@ +package net.coderbot.iris.colorspace; + +import com.google.common.collect.ImmutableSet; +import net.coderbot.iris.gl.IrisRenderSystem; +import net.coderbot.iris.gl.program.ComputeProgram; +import net.coderbot.iris.gl.program.ProgramBuilder; +import net.coderbot.iris.gl.texture.InternalTextureFormat; +import net.coderbot.iris.shaderpack.StringPair; +import net.coderbot.iris.shaderpack.preprocessor.JcppProcessor; +import org.apache.commons.io.IOUtils; +import org.lwjgl.opengl.GL43C; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class ColorSpaceComputeConverter implements ColorSpaceConverter { + private int width; + private int height; + private ColorSpace colorSpace; + private ComputeProgram program; + + private int target; + public ColorSpaceComputeConverter(int width, int height, ColorSpace colorSpace) { + rebuildProgram(width, height, colorSpace); + } + + public void rebuildProgram(int width, int height, ColorSpace colorSpace) { + if (program != null) { + program.destroy(); + program = null; + } + + this.width = width; + this.height = height; + this.colorSpace = colorSpace; + + String source; + try { + source = new String(IOUtils.toByteArray(Objects.requireNonNull(getClass().getResourceAsStream("/colorSpace.csh"))), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + + List defineList = new ArrayList<>(); + defineList.add(new StringPair("COMPUTE", "")); + defineList.add(new StringPair("CURRENT_COLOR_SPACE", String.valueOf(colorSpace.ordinal()))); + + for (ColorSpace space : ColorSpace.values()) { + defineList.add(new StringPair(space.name(), String.valueOf(space.ordinal()))); + } + source = JcppProcessor.glslPreprocessSource(source, defineList); + + ProgramBuilder builder = ProgramBuilder.beginCompute("colorSpaceCompute", source, ImmutableSet.of()); + builder.addTextureImage(() -> target, InternalTextureFormat.RGBA8, "readImage"); + this.program = builder.buildCompute(); + } + + public void process(int targetImage) { + if (colorSpace == ColorSpace.SRGB) return; + + this.target = targetImage; + program.use(); + IrisRenderSystem.dispatchCompute(width / 8, height / 8, 1); + IrisRenderSystem.memoryBarrier(GL43C.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL43C.GL_TEXTURE_FETCH_BARRIER_BIT); + ComputeProgram.unbind(); + } +} diff --git a/src/main/java/net/coderbot/iris/colorspace/ColorSpaceConverter.java b/src/main/java/net/coderbot/iris/colorspace/ColorSpaceConverter.java new file mode 100644 index 0000000000..07a1d86263 --- /dev/null +++ b/src/main/java/net/coderbot/iris/colorspace/ColorSpaceConverter.java @@ -0,0 +1,6 @@ +package net.coderbot.iris.colorspace; + +public interface ColorSpaceConverter { + void rebuildProgram(int width, int height, ColorSpace colorSpace); + void process(int target); +} diff --git a/src/main/java/net/coderbot/iris/colorspace/ColorSpaceFragmentConverter.java b/src/main/java/net/coderbot/iris/colorspace/ColorSpaceFragmentConverter.java new file mode 100644 index 0000000000..9d1a827d61 --- /dev/null +++ b/src/main/java/net/coderbot/iris/colorspace/ColorSpaceFragmentConverter.java @@ -0,0 +1,92 @@ +package net.coderbot.iris.colorspace; + +import com.google.common.collect.ImmutableSet; +import com.mojang.blaze3d.platform.GlStateManager; +import net.coderbot.iris.gl.IrisRenderSystem; +import net.coderbot.iris.gl.framebuffer.GlFramebuffer; +import net.coderbot.iris.gl.program.Program; +import net.coderbot.iris.gl.program.ProgramBuilder; +import net.coderbot.iris.gl.uniform.UniformUpdateFrequency; +import net.coderbot.iris.postprocess.FullScreenQuadRenderer; +import net.coderbot.iris.shaderpack.StringPair; +import net.coderbot.iris.shaderpack.preprocessor.JcppProcessor; +import net.coderbot.iris.vendored.joml.Matrix4f; +import org.apache.commons.io.IOUtils; +import org.lwjgl.opengl.GL11C; +import org.lwjgl.opengl.GL30C; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class ColorSpaceFragmentConverter implements ColorSpaceConverter { + private int width; + private int height; + private ColorSpace colorSpace; + private Program program; + private GlFramebuffer framebuffer; + private int swapTexture; + + private int target; + public ColorSpaceFragmentConverter(int width, int height, ColorSpace colorSpace) { + rebuildProgram(width, height, colorSpace); + } + + public void rebuildProgram(int width, int height, ColorSpace colorSpace) { + if (program != null) { + program.destroy(); + program = null; + framebuffer.destroy(); + framebuffer = null; + GlStateManager._deleteTexture(swapTexture); + swapTexture = 0; + } + + this.width = width; + this.height = height; + this.colorSpace = colorSpace; + + String vertexSource; + String source; + try { + vertexSource = new String(IOUtils.toByteArray(Objects.requireNonNull(getClass().getResourceAsStream("/colorSpace.vsh"))), StandardCharsets.UTF_8); + source = new String(IOUtils.toByteArray(Objects.requireNonNull(getClass().getResourceAsStream("/colorSpace.csh"))), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + + List defineList = new ArrayList<>(); + defineList.add(new StringPair("CURRENT_COLOR_SPACE", String.valueOf(colorSpace.ordinal()))); + + for (ColorSpace space : ColorSpace.values()) { + defineList.add(new StringPair(space.name(), String.valueOf(space.ordinal()))); + } + source = JcppProcessor.glslPreprocessSource(source, defineList); + + ProgramBuilder builder = ProgramBuilder.begin("colorSpaceFragment", vertexSource, null, source, ImmutableSet.of()); + + builder.uniformJomlMatrix(UniformUpdateFrequency.ONCE, "projection", () -> new Matrix4f(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, -1, -1, 0, 1)); + builder.addDynamicSampler(() -> target, "readImage"); + + swapTexture = GlStateManager._genTexture(); + IrisRenderSystem.texImage2D(swapTexture, GL30C.GL_TEXTURE_2D, 0, GL30C.GL_RGBA8, width, height, 0, GL30C.GL_RGBA, GL30C.GL_UNSIGNED_BYTE, null); + + this.framebuffer = new GlFramebuffer(); + framebuffer.addColorAttachment(0, swapTexture); + this.program = builder.build(); + } + + public void process(int targetImage) { + if (colorSpace == ColorSpace.SRGB) return; + + this.target = targetImage; + program.use(); + framebuffer.bind(); + FullScreenQuadRenderer.INSTANCE.render(); + Program.unbind(); + framebuffer.bindAsReadBuffer(); + IrisRenderSystem.copyTexSubImage2D(targetImage, GL11C.GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height); + } +} diff --git a/src/main/java/net/coderbot/iris/compat/dh/DHCompat.java b/src/main/java/net/coderbot/iris/compat/dh/DHCompat.java new file mode 100644 index 0000000000..e30dfec871 --- /dev/null +++ b/src/main/java/net/coderbot/iris/compat/dh/DHCompat.java @@ -0,0 +1,15 @@ +package net.coderbot.iris.compat.dh; + +import net.coderbot.iris.gl.framebuffer.GlFramebuffer; + +public class DHCompat { + private GlFramebuffer fb; + + public int getFramebuffer() { + return fb.getId(); + } + + public void setFramebuffer(GlFramebuffer fb) { + this.fb = fb; + } +} diff --git a/src/main/java/net/coderbot/iris/mixin/MixinExtrasPlugin.java b/src/main/java/net/coderbot/iris/compat/dh/mixin/IrisDHCompatMixinPlugin.java similarity index 68% rename from src/main/java/net/coderbot/iris/mixin/MixinExtrasPlugin.java rename to src/main/java/net/coderbot/iris/compat/dh/mixin/IrisDHCompatMixinPlugin.java index f91da5c2bf..d7e39b6728 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinExtrasPlugin.java +++ b/src/main/java/net/coderbot/iris/compat/dh/mixin/IrisDHCompatMixinPlugin.java @@ -1,19 +1,21 @@ -package net.coderbot.iris.mixin; - -import java.util.List; -import java.util.Set; +package net.coderbot.iris.compat.dh.mixin; +import net.minecraftforge.fml.loading.FMLLoader; import org.objectweb.asm.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; -import llamalad7.mixinextras.MixinExtrasBootstrap; - -public class MixinExtrasPlugin implements IMixinConfigPlugin { +import java.util.List; +import java.util.Set; +/** + * Non-critical mixin config plugin, just disables mixins if Distant Horizons isn't present, + * since otherwise the log gets spammed with warnings. + */ +public class IrisDHCompatMixinPlugin implements IMixinConfigPlugin { @Override public void onLoad(String mixinPackage) { - MixinExtrasBootstrap.init(); + } @Override @@ -23,7 +25,7 @@ public String getRefMapperConfig() { @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { - return true; + return FMLLoader.getLoadingModList().getModFileById("distanthorizons") != null; } @Override @@ -45,5 +47,4 @@ public void preApply(String targetClassName, ClassNode targetClass, String mixin public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } - } diff --git a/src/main/java/net/coderbot/iris/compat/dh/mixin/MixinDHApplyShader.java b/src/main/java/net/coderbot/iris/compat/dh/mixin/MixinDHApplyShader.java new file mode 100644 index 0000000000..9880c13d52 --- /dev/null +++ b/src/main/java/net/coderbot/iris/compat/dh/mixin/MixinDHApplyShader.java @@ -0,0 +1,24 @@ +package net.coderbot.iris.compat.dh.mixin; + +import com.seibel.distanthorizons.core.render.renderer.shaders.DhApplyShader; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import net.coderbot.iris.Iris; +import net.coderbot.iris.compat.dh.DHCompat; +import net.coderbot.iris.pipeline.WorldRenderingPipeline; +import net.coderbot.iris.pipeline.newshader.NewWorldRenderingPipeline; +import net.irisshaders.iris.api.v0.IrisApi; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(value = DhApplyShader.class, remap = false) +public class MixinDHApplyShader { + @Redirect(method = "onRender", at = @At(value = "INVOKE", target = "Lcom/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper;getTargetFrameBuffer()I")) + private int changeFB(IMinecraftRenderWrapper instance) { + if (Iris.getPipelineManager().getPipelineNullable() instanceof NewWorldRenderingPipeline pipeline) { + return pipeline.getDHCompat().getFramebuffer(); + } else { + return instance.getTargetFrameBuffer(); + } + } +} diff --git a/src/main/java/net/coderbot/iris/compat/sodium/AllowedSodiumVersion.java b/src/main/java/net/coderbot/iris/compat/sodium/AllowedSodiumVersion.java deleted file mode 100644 index 2cfa8deb28..0000000000 --- a/src/main/java/net/coderbot/iris/compat/sodium/AllowedSodiumVersion.java +++ /dev/null @@ -1,43 +0,0 @@ -package net.coderbot.iris.compat.sodium; - -import java.util.Optional; - -public class AllowedSodiumVersion { - private final String version; - private final String downloadLink; - private final boolean prefixMatch; - - public AllowedSodiumVersion(String version, String downloadLink, boolean prefixMatch) { - this.version = version; - this.downloadLink = downloadLink; - this.prefixMatch = prefixMatch; - } - - public static AllowedSodiumVersion prefix(String prefix) { - return new AllowedSodiumVersion(prefix, null, true); - } - - public static AllowedSodiumVersion exact(String version, String downloadLink) { - return new AllowedSodiumVersion(version, downloadLink, false); - } - - public boolean matches(String candidate) { - if (prefixMatch) { - return candidate.startsWith(version); - } else { - return candidate.equals(version); - } - } - - public String getVersion() { - return version; - } - - public boolean isPrefixMatch() { - return prefixMatch; - } - - public Optional getDownloadLink() { - return Optional.ofNullable(downloadLink); - } -} diff --git a/src/main/java/net/coderbot/iris/compat/sodium/SodiumVersionCheck.java b/src/main/java/net/coderbot/iris/compat/sodium/SodiumVersionCheck.java deleted file mode 100644 index c7cda22924..0000000000 --- a/src/main/java/net/coderbot/iris/compat/sodium/SodiumVersionCheck.java +++ /dev/null @@ -1,36 +0,0 @@ -package net.coderbot.iris.compat.sodium; - -import com.google.common.collect.ImmutableList; - -import java.util.Optional; - -public class SodiumVersionCheck { - // The allowed versions of Sodium for use with Iris - // - // Make sure to update the comments / download links when editing this!!! - // If you forget to edit the download links you'll cause the support team a bunch - // of pain. So don't forget! - private static final ImmutableList ALLOWED_SODIUM_VERSIONS = ImmutableList.of( - // Release version - AllowedSodiumVersion.exact("0.4.1+build.15", - "https://modrinth.com/mod/sodium/version/mc1.18.2-0.4.1"), - - // For use by ReplayMod - AllowedSodiumVersion.prefix("0.4.1+replaymod") - ); - - public static String getDownloadLink() { - return ALLOWED_SODIUM_VERSIONS.stream().map(AllowedSodiumVersion::getDownloadLink) - .filter(Optional::isPresent).findFirst().get().get(); - } - - public static boolean isAllowedVersion(String sodiumVersion) { - for (AllowedSodiumVersion allowed : ALLOWED_SODIUM_VERSIONS) { - if (allowed.matches(sodiumVersion)) { - return true; - } - } - - return false; - } -} diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/block_context/BlockContextHolder.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/block_context/BlockContextHolder.java index 15b7ae1bdd..fbd41a2e12 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/block_context/BlockContextHolder.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/block_context/BlockContextHolder.java @@ -13,6 +13,7 @@ public class BlockContextHolder { public short blockId; public short renderType; + public boolean ignoreMidBlock; public BlockContextHolder() { this.blockStateIds = Object2IntMaps.emptyMap(); diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/block_context/ChunkBuildBuffersExt.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/block_context/ChunkBuildBuffersExt.java index 19f5f578e7..04082a729d 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/block_context/ChunkBuildBuffersExt.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/block_context/ChunkBuildBuffersExt.java @@ -8,4 +8,6 @@ public interface ChunkBuildBuffersExt { void iris$setMaterialId(BlockState state, short renderType); void iris$resetBlockContext(); + + void iris$ignoreMidBlock(boolean state); } diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/options/IrisSodiumOptions.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/options/IrisSodiumOptions.java index 1f581865ab..0946846038 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/options/IrisSodiumOptions.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/options/IrisSodiumOptions.java @@ -8,6 +8,7 @@ import me.jellysquid.mods.sodium.client.gui.options.control.SliderControl; import me.jellysquid.mods.sodium.client.gui.options.storage.MinecraftOptionsStorage; import net.coderbot.iris.Iris; +import net.coderbot.iris.colorspace.ColorSpace; import net.coderbot.iris.gui.option.IrisVideoSettings; import net.minecraft.client.Options; import net.minecraft.network.chat.Component; @@ -21,7 +22,7 @@ public static OptionImpl createMaxShadowDistanceSlider(Minecra OptionImpl maxShadowDistanceSlider = OptionImpl.createBuilder(int.class, vanillaOpts) .setName(new TranslatableComponent("options.iris.shadowDistance")) .setTooltip(new TranslatableComponent("options.iris.shadowDistance.sodium_tooltip")) - .setControl(option -> new SliderControl(option, 0, 32, 1, ControlValueFormatter.quantityOrDisabled("Chunks", "Disabled"))) + .setControl(option -> new SliderControl(option, 0, 32, 1, translateVariableOrDisabled("options.chunks", "Disabled"))) .setBinding((options, value) -> { IrisVideoSettings.shadowDistance = value; try { @@ -40,13 +41,42 @@ public static OptionImpl createMaxShadowDistanceSlider(Minecra return maxShadowDistanceSlider; } + public static OptionImpl createColorSpaceButton(MinecraftOptionsStorage vanillaOpts) { + OptionImpl colorSpace = OptionImpl.createBuilder(ColorSpace.class, vanillaOpts) + .setName(new TranslatableComponent("options.iris.colorSpace")) + .setTooltip(new TranslatableComponent("options.iris.colorSpace.sodium_tooltip")) + .setControl(option -> new CyclingControl<>(option, ColorSpace.class, + new Component[] { new TextComponent("sRGB"), new TextComponent("DCI_P3"), new TextComponent("Display P3"), new TextComponent("REC2020"), new TextComponent("Adobe RGB") })) + .setBinding((options, value) -> { + IrisVideoSettings.colorSpace = value; + try { + Iris.getIrisConfig().save(); + } catch (IOException e) { + e.printStackTrace(); + } + }, + options -> IrisVideoSettings.colorSpace) + .setImpact(OptionImpact.LOW) + .setEnabled(true) + .build(); + + + return colorSpace; + } + + static ControlValueFormatter translateVariableOrDisabled(String key, String disabled) { + return (v) -> { + return v == 0 ? disabled : (new TranslatableComponent(key, v)).getString(); + }; + } + public static OptionImpl createLimitedVideoSettingsButton(MinecraftOptionsStorage vanillaOpts) { return OptionImpl.createBuilder(SupportedGraphicsMode.class, vanillaOpts) .setName(new TranslatableComponent("options.graphics")) // TODO: State that Fabulous Graphics is incompatible with Shader Packs in the tooltip .setTooltip(new TranslatableComponent("sodium.options.graphics_quality.tooltip")) .setControl(option -> new CyclingControl<>(option, SupportedGraphicsMode.class, - new Component[] { new TextComponent("Fast"), new TextComponent("Fancy") })) + new Component[] { new TranslatableComponent("options.graphics.fast"), new TranslatableComponent("options.graphics.fancy") })) .setBinding( (opts, value) -> opts.graphicsMode = value.toVanilla(), opts -> SupportedGraphicsMode.fromVanilla(opts.graphicsMode)) diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/GlUniformMatrix3f.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/GlUniformMatrix3f.java new file mode 100644 index 0000000000..6540922d74 --- /dev/null +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/GlUniformMatrix3f.java @@ -0,0 +1,24 @@ +package net.coderbot.iris.compat.sodium.impl.shader_overrides; + +import me.jellysquid.mods.sodium.client.gl.shader.uniform.GlUniform; +import org.lwjgl.opengl.GL30C; +import org.lwjgl.system.MemoryStack; +import repack.joml.Matrix3f; + +import java.nio.FloatBuffer; + +public class GlUniformMatrix3f extends GlUniform { + public GlUniformMatrix3f(int index) { + super(index); + } + + @Override + public void set(Matrix3f value) { + try (MemoryStack stack = MemoryStack.stackPush()) { + FloatBuffer buf = stack.callocFloat(12); + value.get(buf); + + GL30C.glUniformMatrix3fv(this.index, false, buf); + } + } +} diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkProgramOverrides.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkProgramOverrides.java index 92b3f5b488..29d7d6da97 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkProgramOverrides.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkProgramOverrides.java @@ -1,7 +1,9 @@ package net.coderbot.iris.compat.sodium.impl.shader_overrides; import me.jellysquid.mods.sodium.client.gl.GlObject; -import me.jellysquid.mods.sodium.client.gl.shader.*; +import me.jellysquid.mods.sodium.client.gl.shader.GlProgram; +import me.jellysquid.mods.sodium.client.gl.shader.GlShader; +import me.jellysquid.mods.sodium.client.gl.shader.ShaderType; import me.jellysquid.mods.sodium.client.model.vertex.type.ChunkVertexType; import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPass; import me.jellysquid.mods.sodium.client.render.chunk.shader.ChunkShaderBindingPoints; @@ -35,8 +37,10 @@ private GlShader createVertexShader(IrisTerrainPass pass, SodiumTerrainPipeline if (pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT) { irisVertexShader = pipeline.getShadowVertexShaderSource(); - } else if (pass == IrisTerrainPass.GBUFFER_SOLID || pass == IrisTerrainPass.GBUFFER_CUTOUT) { - irisVertexShader = pipeline.getTerrainVertexShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_SOLID) { + irisVertexShader = pipeline.getTerrainSolidVertexShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_CUTOUT) { + irisVertexShader = pipeline.getTerrainCutoutVertexShaderSource(); } else if (pass == IrisTerrainPass.GBUFFER_TRANSLUCENT) { irisVertexShader = pipeline.getTranslucentVertexShaderSource(); } else { @@ -58,8 +62,10 @@ private GlShader createGeometryShader(IrisTerrainPass pass, SodiumTerrainPipelin if (pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT) { irisGeometryShader = pipeline.getShadowGeometryShaderSource(); - } else if (pass == IrisTerrainPass.GBUFFER_SOLID || pass == IrisTerrainPass.GBUFFER_CUTOUT) { - irisGeometryShader = pipeline.getTerrainGeometryShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_SOLID) { + irisGeometryShader = pipeline.getTerrainSolidGeometryShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_CUTOUT) { + irisGeometryShader = pipeline.getTerrainCutoutGeometryShaderSource(); } else if (pass == IrisTerrainPass.GBUFFER_TRANSLUCENT) { irisGeometryShader = pipeline.getTranslucentGeometryShaderSource(); } else { @@ -76,6 +82,56 @@ private GlShader createGeometryShader(IrisTerrainPass pass, SodiumTerrainPipelin "sodium-terrain-" + pass.toString().toLowerCase(Locale.ROOT) + ".gsh"), source); } + private GlShader createTessControlShader(IrisTerrainPass pass, SodiumTerrainPipeline pipeline) { + Optional irisTessControlShader; + + if (pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT) { + irisTessControlShader = pipeline.getShadowTessControlShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_SOLID) { + irisTessControlShader = pipeline.getTerrainSolidTessControlShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_CUTOUT) { + irisTessControlShader = pipeline.getTerrainCutoutTessControlShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_TRANSLUCENT) { + irisTessControlShader = pipeline.getTranslucentTessControlShaderSource(); + } else { + throw new IllegalArgumentException("Unknown pass type " + pass); + } + + String source = irisTessControlShader.orElse(null); + + if (source == null) { + return null; + } + + return new GlShader(IrisShaderTypes.TESS_CONTROL, new ResourceLocation("iris", + "sodium-terrain-" + pass.toString().toLowerCase(Locale.ROOT) + ".tcs"), source); + } + + private GlShader createTessEvalShader(IrisTerrainPass pass, SodiumTerrainPipeline pipeline) { + Optional irisTessEvalShader; + + if (pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT) { + irisTessEvalShader = pipeline.getShadowTessEvalShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_SOLID) { + irisTessEvalShader = pipeline.getTerrainSolidTessEvalShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_CUTOUT) { + irisTessEvalShader = pipeline.getTerrainCutoutTessEvalShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_TRANSLUCENT) { + irisTessEvalShader = pipeline.getTranslucentTessEvalShaderSource(); + } else { + throw new IllegalArgumentException("Unknown pass type " + pass); + } + + String source = irisTessEvalShader.orElse(null); + + if (source == null) { + return null; + } + + return new GlShader(IrisShaderTypes.TESS_EVAL, new ResourceLocation("iris", + "sodium-terrain-" + pass.toString().toLowerCase(Locale.ROOT) + ".tes"), source); + } + private GlShader createFragmentShader(IrisTerrainPass pass, SodiumTerrainPipeline pipeline) { Optional irisFragmentShader; @@ -84,7 +140,7 @@ private GlShader createFragmentShader(IrisTerrainPass pass, SodiumTerrainPipelin } else if (pass == IrisTerrainPass.SHADOW_CUTOUT) { irisFragmentShader = pipeline.getShadowCutoutFragmentShaderSource(); } else if (pass == IrisTerrainPass.GBUFFER_SOLID) { - irisFragmentShader = pipeline.getTerrainFragmentShaderSource(); + irisFragmentShader = pipeline.getTerrainSolidFragmentShaderSource(); } else if (pass == IrisTerrainPass.GBUFFER_CUTOUT) { irisFragmentShader = pipeline.getTerrainCutoutFragmentShaderSource(); } else if (pass == IrisTerrainPass.GBUFFER_TRANSLUCENT) { @@ -106,8 +162,10 @@ private GlShader createFragmentShader(IrisTerrainPass pass, SodiumTerrainPipelin private BlendModeOverride getBlendOverride(IrisTerrainPass pass, SodiumTerrainPipeline pipeline) { if (pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT) { return pipeline.getShadowBlendOverride(); - } else if (pass == IrisTerrainPass.GBUFFER_SOLID || pass == IrisTerrainPass.GBUFFER_CUTOUT) { - return pipeline.getTerrainBlendOverride(); + } else if (pass == IrisTerrainPass.GBUFFER_SOLID) { + return pipeline.getTerrainSolidBlendOverride(); + } else if (pass == IrisTerrainPass.GBUFFER_CUTOUT) { + return pipeline.getTerrainCutoutBlendOverride(); } else if (pass == IrisTerrainPass.GBUFFER_TRANSLUCENT) { return pipeline.getTranslucentBlendOverride(); } else { @@ -118,8 +176,10 @@ private BlendModeOverride getBlendOverride(IrisTerrainPass pass, SodiumTerrainPi private List getBufferBlendOverride(IrisTerrainPass pass, SodiumTerrainPipeline pipeline) { if (pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT) { return pipeline.getShadowBufferOverrides(); - } else if (pass == IrisTerrainPass.GBUFFER_SOLID || pass == IrisTerrainPass.GBUFFER_CUTOUT) { - return pipeline.getTerrainBufferOverrides(); + } else if (pass == IrisTerrainPass.GBUFFER_SOLID) { + return pipeline.getTerrainSolidBufferOverrides(); + } else if (pass == IrisTerrainPass.GBUFFER_CUTOUT) { + return pipeline.getTerrainCutoutBufferOverrides(); } else if (pass == IrisTerrainPass.GBUFFER_TRANSLUCENT) { return pipeline.getTranslucentBufferOverrides(); } else { @@ -131,6 +191,8 @@ private List getBufferBlendOverride(IrisTerrainPass pass, S private GlProgram createShader(IrisTerrainPass pass, SodiumTerrainPipeline pipeline) { GlShader vertShader = createVertexShader(pass, pipeline); GlShader geomShader = createGeometryShader(pass, pipeline); + GlShader tessCShader = createTessControlShader(pass, pipeline); + GlShader tessEShader = createTessEvalShader(pass, pipeline); GlShader fragShader = createFragmentShader(pass, pipeline); BlendModeOverride blendOverride = getBlendOverride(pass, pipeline); List bufferOverrides = getBufferBlendOverride(pass, pipeline); @@ -145,6 +207,14 @@ private GlProgram createShader(IrisTerrainPass pass, S geomShader.delete(); } + if (tessCShader != null) { + tessCShader.delete(); + } + + if (tessEShader != null) { + tessEShader.delete(); + } + if (fragShader != null) { fragShader.delete(); } @@ -160,6 +230,12 @@ private GlProgram createShader(IrisTerrainPass pass, S if (geomShader != null) { builder.attachShader(geomShader); } + if (tessCShader != null) { + builder.attachShader(tessCShader); + } + if (tessEShader != null) { + builder.attachShader(tessEShader); + } return builder.attachShader(vertShader) .attachShader(fragShader) @@ -179,13 +255,19 @@ private GlProgram createShader(IrisTerrainPass pass, S ShaderBindingContextExt contextExt = (ShaderBindingContextExt) shader; return new IrisChunkShaderInterface(handle, contextExt, pipeline, - pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT, blendOverride, bufferOverrides, alpha, pipeline.getCustomUniforms()); + tessCShader != null || tessEShader != null, pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT, blendOverride, bufferOverrides, alpha, pipeline.getCustomUniforms()); }); } finally { vertShader.delete(); if (geomShader != null) { geomShader.delete(); } + if (tessCShader != null) { + tessCShader.delete(); + } + if (tessEShader != null) { + tessEShader.delete(); + } fragShader.delete(); } } @@ -193,7 +275,9 @@ private GlProgram createShader(IrisTerrainPass pass, S private float getAlphaReference(IrisTerrainPass pass, SodiumTerrainPipeline pipeline) { if (pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT) { return pipeline.getShadowAlpha().orElse(AlphaTests.ONE_TENTH_ALPHA).getReference(); - } else if (pass == IrisTerrainPass.GBUFFER_SOLID || pass == IrisTerrainPass.GBUFFER_CUTOUT) { + } else if (pass == IrisTerrainPass.GBUFFER_SOLID) { + return AlphaTest.ALWAYS.getReference(); + } else if (pass == IrisTerrainPass.GBUFFER_CUTOUT) { return pipeline.getTerrainCutoutAlpha().orElse(AlphaTests.ONE_TENTH_ALPHA).getReference(); } else if (pass == IrisTerrainPass.GBUFFER_TRANSLUCENT) { return pipeline.getTranslucentAlpha().orElse(AlphaTest.ALWAYS).getReference(); @@ -286,7 +370,7 @@ public void bindFramebuffer(BlockRenderPass pass) { } else if (pass.isTranslucent()) { framebuffer = pipeline.getTranslucentFramebuffer(); } else { - framebuffer = pipeline.getTerrainFramebuffer(); + framebuffer = pipeline.getTerrainSolidFramebuffer(); } if (framebuffer != null) { diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkShaderInterface.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkShaderInterface.java index af834074b1..cf70a77219 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkShaderInterface.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkShaderInterface.java @@ -17,7 +17,9 @@ import net.coderbot.iris.samplers.IrisSamplers; import net.coderbot.iris.uniforms.CapturedRenderingState; import net.coderbot.iris.uniforms.custom.CustomUniforms; +import net.coderbot.iris.vertices.ImmediateState; import org.jetbrains.annotations.Nullable; +import repack.joml.Matrix3f; import repack.joml.Matrix4f; import org.lwjgl.opengl.GL32C; @@ -35,7 +37,7 @@ public class IrisChunkShaderInterface { @Nullable private final GlUniformFloat3v uniformRegionOffset; @Nullable - private final GlUniformMatrix4f uniformNormalMatrix; + private final GlUniformMatrix3f uniformNormalMatrix; @Nullable private final GlUniformBlock uniformBlockDrawParameters; @@ -47,18 +49,20 @@ public class IrisChunkShaderInterface { private final ProgramImages irisProgramImages; private final List bufferBlendOverrides; private final boolean hasOverrides; + private final boolean isTess; private CustomUniforms customUniforms; public IrisChunkShaderInterface(int handle, ShaderBindingContextExt contextExt, SodiumTerrainPipeline pipeline, - boolean isShadowPass, BlendModeOverride blendModeOverride, List bufferOverrides, float alpha, CustomUniforms customUniforms) { + boolean isTess, boolean isShadowPass, BlendModeOverride blendModeOverride, List bufferOverrides, float alpha, CustomUniforms customUniforms) { this.uniformModelViewMatrix = contextExt.bindUniformIfPresent("iris_ModelViewMatrix", GlUniformMatrix4f::new); this.uniformModelViewMatrixInverse = contextExt.bindUniformIfPresent("iris_ModelViewMatrixInverse", GlUniformMatrix4f::new); this.uniformProjectionMatrix = contextExt.bindUniformIfPresent("iris_ProjectionMatrix", GlUniformMatrix4f::new); this.uniformProjectionMatrixInverse = contextExt.bindUniformIfPresent("iris_ProjectionMatrixInverse", GlUniformMatrix4f::new); this.uniformRegionOffset = contextExt.bindUniformIfPresent("u_RegionOffset", GlUniformFloat3v::new); - this.uniformNormalMatrix = contextExt.bindUniformIfPresent("iris_NormalMatrix", GlUniformMatrix4f::new); + this.uniformNormalMatrix = contextExt.bindUniformIfPresent("iris_NormalMatrix", GlUniformMatrix3f::new); this.uniformBlockDrawParameters = contextExt.bindUniformBlockIfPresent("ubo_DrawParameters", 0); this.customUniforms = customUniforms; + this.isTess = isTess; this.alpha = alpha; @@ -86,6 +90,8 @@ public void setup() { blendModeOverride.apply(); } + ImmediateState.usingTessellation = isTess; + if (hasOverrides) { bufferBlendOverrides.forEach(BufferBlendOverride::apply); } @@ -101,6 +107,8 @@ public void setup() { } public void restore() { + ImmediateState.usingTessellation = false; + if (blendModeOverride != null || hasOverrides) { BlendModeOverride.restore(); } @@ -129,10 +137,10 @@ public void setModelViewMatrix(Matrix4f modelView) { this.uniformModelViewMatrixInverse.set(invertedMatrix); if (this.uniformNormalMatrix != null) { invertedMatrix.transpose(); - this.uniformNormalMatrix.set(invertedMatrix); + this.uniformNormalMatrix.set(new Matrix3f(invertedMatrix)); } } else if (this.uniformNormalMatrix != null) { - Matrix4f normalMatrix = new Matrix4f(modelView); + Matrix3f normalMatrix = new Matrix3f(modelView); normalMatrix.invert(); normalMatrix.transpose(); this.uniformNormalMatrix.set(normalMatrix); diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisShaderTypes.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisShaderTypes.java index ef30b90648..18c8980d2c 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisShaderTypes.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisShaderTypes.java @@ -7,4 +7,6 @@ */ public class IrisShaderTypes { public static ShaderType GEOMETRY; + public static ShaderType TESS_CONTROL; + public static ShaderType TESS_EVAL; } diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/EntityVertexBufferWriterNio.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/EntityVertexBufferWriterNio.java index 7cdd6f09b9..039e08d431 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/EntityVertexBufferWriterNio.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/EntityVertexBufferWriterNio.java @@ -5,8 +5,10 @@ import me.jellysquid.mods.sodium.client.model.vertex.formats.glyph.GlyphVertexSink; import me.jellysquid.mods.sodium.client.model.vertex.formats.quad.QuadVertexSink; import me.jellysquid.mods.sodium.client.util.Norm3b; +import net.coderbot.iris.uniforms.CapturedRenderingState; import net.coderbot.iris.vendored.joml.Vector3f; import net.coderbot.iris.vertices.IrisVertexFormats; +import net.coderbot.iris.vertices.NormI8; import net.coderbot.iris.vertices.NormalHelper; import net.minecraft.client.renderer.texture.OverlayTexture; @@ -43,6 +45,9 @@ public void writeQuad(float x, float y, float z, int color, float u, float v, in buffer.putFloat(i + 20, v); buffer.putInt(i + 24, overlay); buffer.putInt(i + 28, light); + buffer.putShort(i + 36, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedEntity()); + buffer.putShort(i + 38, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity()); + buffer.putShort(i + 40, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedItem()); if (vertexCount == 4) { this.endQuad(normal); @@ -74,7 +79,7 @@ private void endQuad(int normal) { normalX = saveNormal.x; normalY = saveNormal.y; normalZ = saveNormal.z; - normal = NormalHelper.packNormal(saveNormal, 0.0F); + normal = NormI8.pack(normalX, normalY, normalZ, 0.0F); } else { normalX = Norm3b.unpackX(normal); normalY = Norm3b.unpackY(normal); @@ -84,10 +89,10 @@ private void endQuad(int normal) { int tangent = NormalHelper.computeTangent(normalX, normalY, normalZ, quad); for (int vertex = 0; vertex < 4; vertex++) { - buffer.putFloat(i + 36 - STRIDE * vertex, uSum); - buffer.putFloat(i + 40 - STRIDE * vertex, vSum); + buffer.putFloat(i + 42 - STRIDE * vertex, uSum); + buffer.putFloat(i + 46 - STRIDE * vertex, vSum); buffer.putInt(i + 32 - STRIDE * vertex, normal); - buffer.putInt(i + 44 - STRIDE * vertex, tangent); + buffer.putInt(i + 50 - STRIDE * vertex, tangent); } uSum = 0; diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/EntityVertexBufferWriterUnsafe.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/EntityVertexBufferWriterUnsafe.java index 6e58e962f6..7cfc451b7a 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/EntityVertexBufferWriterUnsafe.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/EntityVertexBufferWriterUnsafe.java @@ -5,8 +5,10 @@ import me.jellysquid.mods.sodium.client.model.vertex.formats.glyph.GlyphVertexSink; import me.jellysquid.mods.sodium.client.model.vertex.formats.quad.QuadVertexSink; import me.jellysquid.mods.sodium.client.util.Norm3b; +import net.coderbot.iris.uniforms.CapturedRenderingState; import net.coderbot.iris.vendored.joml.Vector3f; import net.coderbot.iris.vertices.IrisVertexFormats; +import net.coderbot.iris.vertices.NormI8; import net.coderbot.iris.vertices.NormalHelper; import net.minecraft.client.renderer.texture.OverlayTexture; import org.lwjgl.system.MemoryUtil; @@ -41,6 +43,9 @@ public void writeQuad(float x, float y, float z, int color, float u, float v, in MemoryUtil.memPutFloat(i + 20, v); MemoryUtil.memPutInt(i + 24, overlay); MemoryUtil.memPutInt(i + 28, light); + MemoryUtil.memPutShort(i + 36, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedEntity()); + MemoryUtil.memPutShort(i + 38, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity()); + MemoryUtil.memPutShort(i + 40, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedItem()); if (vertexCount == 4) { this.endQuad(normal); @@ -71,7 +76,7 @@ private void endQuad(int normal) { normalX = saveNormal.x; normalY = saveNormal.y; normalZ = saveNormal.z; - normal = NormalHelper.packNormal(saveNormal, 0.0F); + normal = NormI8.pack(normalX, normalY, normalZ, 0.0F); } else { normalX = Norm3b.unpackX(normal); normalY = Norm3b.unpackY(normal); @@ -81,10 +86,10 @@ private void endQuad(int normal) { int tangent = NormalHelper.computeTangent(normalX, normalY, normalZ, quad); for (long vertex = 0; vertex < 4; vertex++) { - MemoryUtil.memPutFloat(i + 36 - STRIDE * vertex, uSum); - MemoryUtil.memPutFloat(i + 40 - STRIDE * vertex, vSum); + MemoryUtil.memPutFloat(i + 42 - STRIDE * vertex, uSum); + MemoryUtil.memPutFloat(i + 46 - STRIDE * vertex, vSum); MemoryUtil.memPutInt(i + 32 - STRIDE * vertex, normal); - MemoryUtil.memPutInt(i + 44 - STRIDE * vertex, tangent); + MemoryUtil.memPutInt(i + 50 - STRIDE * vertex, tangent); } uSum = 0; diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/ExtendedGlyphVertexType.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/ExtendedGlyphVertexType.java index e5a24c6c8f..fb45f9e0e3 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/ExtendedGlyphVertexType.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/ExtendedGlyphVertexType.java @@ -19,7 +19,7 @@ public GlyphVertexSink createFallbackWriter(VertexConsumer vertexConsumer) { @Override public GlyphVertexSink createBufferWriter(VertexBufferView buffer, boolean direct) { - return direct ? new GlyphVertexBufferWriterUnsafe(buffer) : new GlyphVertexBufferWriterNio(buffer); + return direct ? new EntityVertexBufferWriterUnsafe(buffer) : new EntityVertexBufferWriterNio(buffer); } @Override diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/GlyphVertexBufferWriterNio.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/GlyphVertexBufferWriterNio.java index 0d50e26589..3dd8e3174c 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/GlyphVertexBufferWriterNio.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/GlyphVertexBufferWriterNio.java @@ -7,6 +7,7 @@ import me.jellysquid.mods.sodium.client.util.Norm3b; import net.coderbot.iris.vendored.joml.Vector3f; import net.coderbot.iris.vertices.IrisVertexFormats; +import net.coderbot.iris.vertices.NormI8; import net.coderbot.iris.vertices.NormalHelper; import net.minecraft.client.renderer.texture.OverlayTexture; @@ -73,7 +74,7 @@ private void endQuad(int normal) { normalX = saveNormal.x; normalY = saveNormal.y; normalZ = saveNormal.z; - normal = NormalHelper.packNormal(saveNormal, 0.0F); + normal = NormI8.pack(normalX, normalY, normalZ, 0.0F); } else { normalX = Norm3b.unpackX(normal); normalY = Norm3b.unpackY(normal); diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/GlyphVertexBufferWriterUnsafe.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/GlyphVertexBufferWriterUnsafe.java index c412a9ef6a..216554693d 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/GlyphVertexBufferWriterUnsafe.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/GlyphVertexBufferWriterUnsafe.java @@ -7,6 +7,7 @@ import me.jellysquid.mods.sodium.client.util.Norm3b; import net.coderbot.iris.vendored.joml.Vector3f; import net.coderbot.iris.vertices.IrisVertexFormats; +import net.coderbot.iris.vertices.NormI8; import net.coderbot.iris.vertices.NormalHelper; import net.minecraft.client.renderer.texture.OverlayTexture; import org.lwjgl.system.MemoryUtil; @@ -70,7 +71,7 @@ private void endQuad(int normal) { normalX = saveNormal.x; normalY = saveNormal.y; normalZ = saveNormal.z; - normal = NormalHelper.packNormal(saveNormal, 0.0F); + normal = NormI8.pack(normalX, normalY, normalZ, 0.0F); } else { normalX = Norm3b.unpackX(normal); normalY = Norm3b.unpackY(normal); diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/terrain_xhfp/XHFPModelVertexBufferWriterNio.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/terrain_xhfp/XHFPModelVertexBufferWriterNio.java index 2dd3f80faa..f5b6b1ac03 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/terrain_xhfp/XHFPModelVertexBufferWriterNio.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/terrain_xhfp/XHFPModelVertexBufferWriterNio.java @@ -5,10 +5,10 @@ import me.jellysquid.mods.sodium.client.render.chunk.format.ModelVertexSink; import net.coderbot.iris.compat.sodium.impl.block_context.BlockContextHolder; import net.coderbot.iris.compat.sodium.impl.block_context.ContextAwareVertexWriter; -import me.jellysquid.mods.sodium.client.util.Norm3b; import net.coderbot.iris.compat.sodium.impl.vertex_format.IrisModelVertexFormats; import net.coderbot.iris.vendored.joml.Vector3f; import net.coderbot.iris.vertices.ExtendedDataHelper; +import net.coderbot.iris.vertices.NormI8; import net.coderbot.iris.vertices.NormalHelper; import java.nio.ByteBuffer; @@ -45,13 +45,13 @@ public void copyQuadAndFlipNormal() { dst.put(src); // Now flip vertex normals - int packedNormal = this.byteBuffer.getInt(this.writeOffset + 32); + int packedNormal = this.byteBuffer.getInt(this.writeOffset + 28); int inverted = NormalHelper.invertPackedNormal(packedNormal); - this.byteBuffer.putInt(this.writeOffset + 32, inverted); - this.byteBuffer.putInt(this.writeOffset + 32 + STRIDE, inverted); - this.byteBuffer.putInt(this.writeOffset + 32 + STRIDE * 2, inverted); - this.byteBuffer.putInt(this.writeOffset + 32 + STRIDE * 3, inverted); + this.byteBuffer.putInt(this.writeOffset + 28, inverted); + this.byteBuffer.putInt(this.writeOffset + 28 + STRIDE, inverted); + this.byteBuffer.putInt(this.writeOffset + 28 + STRIDE * 2, inverted); + this.byteBuffer.putInt(this.writeOffset + 28 + STRIDE * 3, inverted); // We just wrote 4 vertices, advance by 4 for (int i = 0; i < 4; i++) { @@ -99,9 +99,9 @@ private void writeQuadInternal(float posX, float posY, float posZ, int color, // block ID: We only set the first 2 values, any legacy shaders using z or w will get filled in based on the GLSL spec // https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_format // TODO: can we pack this into one short? - buffer.putShort(i + 36, materialId); - buffer.putShort(i + 38, renderType); - buffer.putInt(i + 40, packedMidBlock); + buffer.putShort(i + 32, materialId); + buffer.putShort(i + 34, renderType); + buffer.putInt(i + 36, packedMidBlock); if (vertexCount == 4) { vertexCount = 0; @@ -136,15 +136,18 @@ private void writeQuadInternal(float posX, float posY, float posZ, int color, uSum *= 0.25f; vSum *= 0.25f; - buffer.putFloat(i + 20, uSum); - buffer.putFloat(i + 20 - STRIDE, uSum); - buffer.putFloat(i + 20 - STRIDE * 2, uSum); - buffer.putFloat(i + 20 - STRIDE * 3, uSum); + short midU = XHFPModelVertexType.encodeBlockTexture(uSum); + short midV = XHFPModelVertexType.encodeBlockTexture(vSum); - buffer.putFloat(i + 24, vSum); - buffer.putFloat(i + 24 - STRIDE, vSum); - buffer.putFloat(i + 24 - STRIDE * 2, vSum); - buffer.putFloat(i + 24 - STRIDE * 3, vSum); + buffer.putShort(i + 20, midU); + buffer.putShort(i + 20 - STRIDE, midU); + buffer.putShort(i + 20 - STRIDE * 2, midU); + buffer.putShort(i + 20 - STRIDE * 3, midU); + + buffer.putShort(i + 22, midV); + buffer.putShort(i + 22 - STRIDE, midV); + buffer.putShort(i + 22 - STRIDE * 2, midV); + buffer.putShort(i + 22 - STRIDE * 3, midV); uSum = 0; vSum = 0; @@ -155,19 +158,19 @@ private void writeQuadInternal(float posX, float posY, float posZ, int color, quad.setup(buffer, i, STRIDE); NormalHelper.computeFaceNormal(normal, quad); - int packedNormal = NormalHelper.packNormal(normal, 0.0f); + int packedNormal = NormI8.pack(normal.x, normal.y, normal.z, 0.0f); - buffer.putInt(i + 32, packedNormal); - buffer.putInt(i + 32 - STRIDE, packedNormal); - buffer.putInt(i + 32 - STRIDE * 2, packedNormal); - buffer.putInt(i + 32 - STRIDE * 3, packedNormal); + buffer.putInt(i + 28, packedNormal); + buffer.putInt(i + 28 - STRIDE, packedNormal); + buffer.putInt(i + 28 - STRIDE * 2, packedNormal); + buffer.putInt(i + 28 - STRIDE * 3, packedNormal); int tangent = NormalHelper.computeTangent(normal.x, normal.y, normal.z, quad); - buffer.putInt(i + 28, tangent); - buffer.putInt(i + 28 - STRIDE, tangent); - buffer.putInt(i + 28 - STRIDE * 2, tangent); - buffer.putInt(i + 28 - STRIDE * 3, tangent); + buffer.putInt(i + 24, tangent); + buffer.putInt(i + 24 - STRIDE, tangent); + buffer.putInt(i + 24 - STRIDE * 2, tangent); + buffer.putInt(i + 24 - STRIDE * 3, tangent); } this.advance(); diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/terrain_xhfp/XHFPModelVertexBufferWriterUnsafe.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/terrain_xhfp/XHFPModelVertexBufferWriterUnsafe.java index aa5b855c55..551368c432 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/terrain_xhfp/XHFPModelVertexBufferWriterUnsafe.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/terrain_xhfp/XHFPModelVertexBufferWriterUnsafe.java @@ -8,6 +8,7 @@ import net.coderbot.iris.compat.sodium.impl.vertex_format.IrisModelVertexFormats; import net.coderbot.iris.vendored.joml.Vector3f; import net.coderbot.iris.vertices.ExtendedDataHelper; +import net.coderbot.iris.vertices.NormI8; import net.coderbot.iris.vertices.NormalHelper; import org.lwjgl.system.MemoryUtil; @@ -34,13 +35,13 @@ public void copyQuadAndFlipNormal() { MemoryUtil.memCopy(this.writePointer - STRIDE * 4, this.writePointer, STRIDE * 4); // Now flip vertex normals - int packedNormal = MemoryUtil.memGetInt(this.writePointer + 32); + int packedNormal = MemoryUtil.memGetInt(this.writePointer + 28); int inverted = NormalHelper.invertPackedNormal(packedNormal); - MemoryUtil.memPutInt(this.writePointer + 32, inverted); - MemoryUtil.memPutInt(this.writePointer + 32 + STRIDE, inverted); - MemoryUtil.memPutInt(this.writePointer + 32 + STRIDE * 2, inverted); - MemoryUtil.memPutInt(this.writePointer + 32 + STRIDE * 3, inverted); + MemoryUtil.memPutInt(this.writePointer + 28, inverted); + MemoryUtil.memPutInt(this.writePointer + 28 + STRIDE, inverted); + MemoryUtil.memPutInt(this.writePointer + 28 + STRIDE * 2, inverted); + MemoryUtil.memPutInt(this.writePointer + 28 + STRIDE * 3, inverted); // We just wrote 4 vertices, advance by 4 for (int i = 0; i < 4; i++) { @@ -56,7 +57,7 @@ public void writeVertex(float posX, float posY, float posZ, int color, float u, uSum += u; vSum += v; - this.writeQuadInternal(posX, posY, posZ, color, u, v, light, contextHolder.blockId, contextHolder.renderType, chunkId, ExtendedDataHelper.computeMidBlock(posX, posY, posZ, contextHolder.localPosX, contextHolder.localPosY, contextHolder.localPosZ)); + this.writeQuadInternal(posX, posY, posZ, color, u, v, light, contextHolder.blockId, contextHolder.renderType, chunkId, contextHolder.ignoreMidBlock ? 0 : ExtendedDataHelper.computeMidBlock(posX, posY, posZ, contextHolder.localPosX, contextHolder.localPosY, contextHolder.localPosZ)); } private void writeQuadInternal(float posX, float posY, float posZ, int color, @@ -83,9 +84,9 @@ private void writeQuadInternal(float posX, float posY, float posZ, int color, // block ID: We only set the first 2 values, any legacy shaders using z or w will get filled in based on the GLSL spec // https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_format // TODO: can we pack this into one short? - MemoryUtil.memPutShort(i + 36, materialId); - MemoryUtil.memPutShort(i + 38, renderType); - MemoryUtil.memPutInt(i + 40, packedMidBlock); + MemoryUtil.memPutShort(i + 32, materialId); + MemoryUtil.memPutShort(i + 34, renderType); + MemoryUtil.memPutInt(i + 36, packedMidBlock); if (vertexCount == 4) { vertexCount = 0; @@ -120,15 +121,18 @@ private void writeQuadInternal(float posX, float posY, float posZ, int color, uSum *= 0.25f; vSum *= 0.25f; - MemoryUtil.memPutFloat(i + 20, uSum); - MemoryUtil.memPutFloat(i + 20 - STRIDE, uSum); - MemoryUtil.memPutFloat(i + 20 - STRIDE * 2, uSum); - MemoryUtil.memPutFloat(i + 20 - STRIDE * 3, uSum); + short midU = XHFPModelVertexType.encodeBlockTexture(uSum); + short midV = XHFPModelVertexType.encodeBlockTexture(vSum); - MemoryUtil.memPutFloat(i + 24, vSum); - MemoryUtil.memPutFloat(i + 24 - STRIDE, vSum); - MemoryUtil.memPutFloat(i + 24 - STRIDE * 2, vSum); - MemoryUtil.memPutFloat(i + 24 - STRIDE * 3, vSum); + MemoryUtil.memPutShort(i + 20, midU); + MemoryUtil.memPutShort(i + 20 - STRIDE, midU); + MemoryUtil.memPutShort(i + 20 - STRIDE * 2, midU); + MemoryUtil.memPutShort(i + 20 - STRIDE * 3, midU); + + MemoryUtil.memPutShort(i + 22, midV); + MemoryUtil.memPutShort(i + 22 - STRIDE, midV); + MemoryUtil.memPutShort(i + 22 - STRIDE * 2, midV); + MemoryUtil.memPutShort(i + 22 - STRIDE * 3, midV); uSum = 0; vSum = 0; @@ -139,19 +143,19 @@ private void writeQuadInternal(float posX, float posY, float posZ, int color, quad.setup(i, STRIDE); NormalHelper.computeFaceNormal(normal, quad); - int packedNormal = NormalHelper.packNormal(normal, 0.0f); + int packedNormal = NormI8.pack(normal.x, normal.y, normal.z, 0.0f); - MemoryUtil.memPutInt(i + 32, packedNormal); - MemoryUtil.memPutInt(i + 32 - STRIDE, packedNormal); - MemoryUtil.memPutInt(i + 32 - STRIDE * 2, packedNormal); - MemoryUtil.memPutInt(i + 32 - STRIDE * 3, packedNormal); + MemoryUtil.memPutInt(i + 28, packedNormal); + MemoryUtil.memPutInt(i + 28 - STRIDE, packedNormal); + MemoryUtil.memPutInt(i + 28 - STRIDE * 2, packedNormal); + MemoryUtil.memPutInt(i + 28 - STRIDE * 3, packedNormal); int tangent = NormalHelper.computeTangent(normal.x, normal.y, normal.z, quad); - MemoryUtil.memPutInt(i + 28, tangent); - MemoryUtil.memPutInt(i + 28 - STRIDE, tangent); - MemoryUtil.memPutInt(i + 28 - STRIDE * 2, tangent); - MemoryUtil.memPutInt(i + 28 - STRIDE * 3, tangent); + MemoryUtil.memPutInt(i + 24, tangent); + MemoryUtil.memPutInt(i + 24 - STRIDE, tangent); + MemoryUtil.memPutInt(i + 24 - STRIDE * 2, tangent); + MemoryUtil.memPutInt(i + 24 - STRIDE * 3, tangent); } this.advance(); diff --git a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/terrain_xhfp/XHFPModelVertexType.java b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/terrain_xhfp/XHFPModelVertexType.java index 155416e474..c9d56512d3 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/terrain_xhfp/XHFPModelVertexType.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/impl/vertex_format/terrain_xhfp/XHFPModelVertexType.java @@ -15,17 +15,17 @@ * Like HFPModelVertexType, but extended to support Iris. The extensions aren't particularly efficient right now. */ public class XHFPModelVertexType implements ChunkVertexType { - public static final int STRIDE = 44; + public static final int STRIDE = 40; public static final GlVertexFormat VERTEX_FORMAT = GlVertexFormat.builder(ChunkMeshAttribute.class, STRIDE) .addElement(ChunkMeshAttribute.POSITION_ID, 0, GlVertexAttributeFormat.UNSIGNED_SHORT, 4, false) .addElement(ChunkMeshAttribute.COLOR, 8, GlVertexAttributeFormat.UNSIGNED_BYTE, 4, true) .addElement(ChunkMeshAttribute.BLOCK_TEXTURE, 12, GlVertexAttributeFormat.UNSIGNED_SHORT, 2, false) .addElement(ChunkMeshAttribute.LIGHT_TEXTURE, 16, GlVertexAttributeFormat.UNSIGNED_SHORT, 2, false) - .addElement(IrisChunkMeshAttributes.MID_TEX_COORD, 20, GlVertexAttributeFormat.FLOAT, 2, false) - .addElement(IrisChunkMeshAttributes.TANGENT, 28, IrisGlVertexAttributeFormat.BYTE, 4, true) - .addElement(IrisChunkMeshAttributes.NORMAL, 32, IrisGlVertexAttributeFormat.BYTE, 3, true) - .addElement(IrisChunkMeshAttributes.BLOCK_ID, 36, IrisGlVertexAttributeFormat.SHORT, 2, false) - .addElement(IrisChunkMeshAttributes.MID_BLOCK, 40, IrisGlVertexAttributeFormat.BYTE, 3, false) + .addElement(IrisChunkMeshAttributes.MID_TEX_COORD, 20, GlVertexAttributeFormat.UNSIGNED_SHORT, 2, false) + .addElement(IrisChunkMeshAttributes.TANGENT, 24, IrisGlVertexAttributeFormat.BYTE, 4, true) + .addElement(IrisChunkMeshAttributes.NORMAL, 28, IrisGlVertexAttributeFormat.BYTE, 3, true) + .addElement(IrisChunkMeshAttributes.BLOCK_ID, 32, IrisGlVertexAttributeFormat.SHORT, 2, false) + .addElement(IrisChunkMeshAttributes.MID_BLOCK, 36, IrisGlVertexAttributeFormat.BYTE, 3, false) .build(); private static final int POSITION_MAX_VALUE = 65536; diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/IrisSodiumCompatMixinPlugin.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/IrisSodiumCompatMixinPlugin.java index 519842c223..9cfd422b53 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/IrisSodiumCompatMixinPlugin.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/IrisSodiumCompatMixinPlugin.java @@ -1,7 +1,6 @@ package net.coderbot.iris.compat.sodium.mixin; import net.minecraftforge.fml.loading.FMLLoader; - import org.objectweb.asm.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; @@ -15,12 +14,12 @@ * spamming the log if Sodium isn't present. */ public class IrisSodiumCompatMixinPlugin implements IMixinConfigPlugin { - - public static boolean isRubidiumLoaded; + + public static boolean isEmbeddiumLoaded; @Override public void onLoad(String mixinPackage) { - isRubidiumLoaded = FMLLoader.getLoadingModList().getModFileById("rubidium") != null; + isEmbeddiumLoaded = FMLLoader.getLoadingModList().getModFileById("embeddium") != null; } @Override @@ -30,7 +29,7 @@ public String getRefMapperConfig() { @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { - return isRubidiumLoaded; + return isEmbeddiumLoaded; } @Override @@ -52,4 +51,4 @@ public void preApply(String targetClassName, ClassNode targetClass, String mixin public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } -} \ No newline at end of file +} diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/block_id/MixinChunkBuildBuffers.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/block_id/MixinChunkBuildBuffers.java index d7b61fd8ae..dd2bc038ae 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/block_id/MixinChunkBuildBuffers.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/block_id/MixinChunkBuildBuffers.java @@ -65,4 +65,9 @@ public class MixinChunkBuildBuffers implements ChunkBuildBuffersExt { public void iris$resetBlockContext() { this.contextHolder.reset(); } + + @Override + public void iris$ignoreMidBlock(boolean state) { + this.contextHolder.ignoreMidBlock = state; + } } diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/block_id/MixinChunkRenderRebuildTask.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/block_id/MixinChunkRenderRebuildTask.java index f429aad4fa..71c2344fef 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/block_id/MixinChunkRenderRebuildTask.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/block_id/MixinChunkRenderRebuildTask.java @@ -1,83 +1,164 @@ package net.coderbot.iris.compat.sodium.mixin.block_id; -import java.util.Map; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - +import com.llamalad7.mixinextras.sugar.Local; import me.jellysquid.mods.sodium.client.gl.compile.ChunkBuildContext; +import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing; +import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadWinding; import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildResult; import me.jellysquid.mods.sodium.client.render.chunk.compile.buffers.ChunkModelBuilder; import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkRenderBounds; import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkRenderData; import me.jellysquid.mods.sodium.client.render.chunk.tasks.ChunkRenderRebuildTask; -import me.jellysquid.mods.sodium.client.render.pipeline.FluidRenderer; import me.jellysquid.mods.sodium.client.render.pipeline.context.ChunkRenderCacheLocal; import me.jellysquid.mods.sodium.client.util.task.CancellationSource; import me.jellysquid.mods.sodium.client.world.WorldSlice; +import net.coderbot.iris.block_rendering.BlockRenderingSettings; import net.coderbot.iris.compat.sodium.impl.block_context.ChunkBuildBuffersExt; import net.coderbot.iris.vertices.ExtendedDataHelper; +import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.chunk.VisGraph; import net.minecraft.core.BlockPos; -import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.LightBlock; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateHolder; import net.minecraft.world.level.material.FluidState; import net.minecraftforge.client.model.data.IModelData; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.Map; /** - * Passes additional information indirectly to the vertex writer to support the mc_Entity and at_midBlock parts of the vertex format. + * Passes additional information indirectly to the vertex writer to support the mc_Entity and at_midBlock parts of + * the vertex format. */ -@Mixin(ChunkRenderRebuildTask.class) +@Mixin(value = ChunkRenderRebuildTask.class, remap = false) public class MixinChunkRenderRebuildTask { - @Inject(method = "performBuild", at = @At(value = "INVOKE", - target = "net/minecraft/world/level/block/state/BlockState.getRenderShape()" + - "Lnet/minecraft/world/level/block/RenderShape;"), - locals = LocalCapture.CAPTURE_FAILHARD) - private void iris$setLocalPos(ChunkBuildContext context, - CancellationSource cancellationSource, CallbackInfoReturnable cir, - ChunkRenderData.Builder renderData, VisGraph occluder, ChunkRenderBounds.Builder bounds, ChunkBuildBuffers buffers, - ChunkRenderCacheLocal cacheLocal, - WorldSlice slice, int baseX, int baseY, int baseZ, int maxX, int maxY, int maxZ, - Map modelDataMap, - BlockPos.MutableBlockPos pos, BlockPos.MutableBlockPos renderOffset, - int relY, int relZ, int relX) { - if (context.buffers instanceof ChunkBuildBuffersExt) { - ((ChunkBuildBuffersExt) context.buffers).iris$setLocalPos(relX, relY, relZ); - } - } + @Inject( + method = "performBuild", at = @At( + value = "INVOKE", + target = "net/minecraft/world/level/block/state/BlockState.getRenderShape()" + + "Lnet/minecraft/world/level/block/RenderShape;" + ), + locals = LocalCapture.CAPTURE_FAILHARD + ) + private void iris$setLocalPos( + ChunkBuildContext context, + CancellationSource cancellationSource, + CallbackInfoReturnable cir, + ChunkRenderData.Builder renderData, + VisGraph occluder, + ChunkRenderBounds.Builder bounds, + ChunkBuildBuffers buffers, + ChunkRenderCacheLocal cacheLocal, + WorldSlice slice, + int baseX, + int baseY, + int baseZ, + int maxX, + int maxY, + int maxZ, + Map modelDataMap, + BlockPos.MutableBlockPos pos, + BlockPos.MutableBlockPos renderOffset, + int relY, + int relZ, + int relX, + BlockState blockState + ) { + if (BlockRenderingSettings.INSTANCE.shouldVoxelizeLightBlocks() && + blockState.getBlock() instanceof LightBlock) { + ChunkModelBuilder buildBuffers = buffers.get(RenderType.cutout()); + ((ChunkBuildBuffersExt) buffers).iris$setLocalPos(0, 0, 0); + ((ChunkBuildBuffersExt) buffers).iris$ignoreMidBlock(true); + ((ChunkBuildBuffersExt) buffers).iris$setMaterialId(blockState, (short) 0); + + int vertexStart = buildBuffers.getVertexSink().getVertexCount(); + + for (int i = 0; i < 4; i++) { + float x = (float) ((relX & 15)) + 0.25f; + float y = (float) ((relY & 15)) + 0.25f; + float z = (float) ((relZ & 15)) + 0.25f; + float u = 0; + float v = 0; + int color = 0; + int light = blockState.getLightEmission() << 4 | blockState.getLightEmission() << 20; + bounds.addBlock(relX & 15, relY & 15, relZ & 15); + + buildBuffers.getVertexSink().writeVertex(x, y, z, color, u, v, light, buildBuffers.getChunkId()); + } + buildBuffers.getIndexBufferBuilder(ModelQuadFacing.UNASSIGNED).add(vertexStart, ModelQuadWinding.CLOCKWISE); - @Redirect(method = "performBuild", at = @At(value = "INVOKE", - target = "net/minecraft/world/level/block/state/BlockState.getSeed(Lnet/minecraft/core/BlockPos;)J")) - private long iris$wrapGetBlockLayer(BlockState blockState, BlockPos pos, ChunkBuildContext context) { - if (context.buffers instanceof ChunkBuildBuffersExt) { - ((ChunkBuildBuffersExt) context.buffers).iris$setMaterialId(blockState, ExtendedDataHelper.BLOCK_RENDER_TYPE); - } + buildBuffers.getVertexSink().flush(); + ((ChunkBuildBuffersExt) buffers).iris$ignoreMidBlock(false); + return; + } - return blockState.getSeed(pos); - } + if (context.buffers instanceof ChunkBuildBuffersExt) { + ((ChunkBuildBuffersExt) context.buffers).iris$setLocalPos(relX, relY, relZ); + } + } - @Redirect(method = "performBuild", at = @At(value = "INVOKE", - target = "me/jellysquid/mods/sodium/client/render/pipeline/FluidRenderer.render(" + - "Lnet/minecraft/world/level/BlockAndTintGetter;Lnet/minecraft/world/level/material/FluidState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/BlockPos;Lme/jellysquid/mods/sodium/client/render/chunk/compile/buffers/ChunkModelBuilder;" + - ")Z"), remap = false) - private boolean iris$wrapGetFluidLayer(FluidRenderer renderer, BlockAndTintGetter world, FluidState fluidState, BlockPos pos, BlockPos offset, ChunkModelBuilder buffers, ChunkBuildContext context) { - if (context.buffers instanceof ChunkBuildBuffersExt) { - ((ChunkBuildBuffersExt) context.buffers).iris$setMaterialId(fluidState.createLegacyBlock(), ExtendedDataHelper.FLUID_RENDER_TYPE); - } + @ModifyArg( + method = "performBuild", + at = @At( + value = "INVOKE", + ordinal = 0, + target = "Lorg/embeddedt/embeddium/render/EmbeddiumRenderLayerCache;forState" + + "(Lnet/minecraft/world/level/block/state/StateHolder;)Ljava/util/List;" + ) + ) + private > H iris$wrapGetBlockLayer( + H state, + @Local(argsOnly = true) ChunkBuildContext context + ) { + if (context.buffers instanceof ChunkBuildBuffersExt) { + ((ChunkBuildBuffersExt) context.buffers).iris$setMaterialId( + (BlockState) state, + ExtendedDataHelper.BLOCK_RENDER_TYPE + ); + } + return state; + } - return renderer.render(world, fluidState, pos, offset, buffers); - } + @ModifyArg( + method = "performBuild", + at = @At( + value = "INVOKE", + ordinal = 1, + target = "Lorg/embeddedt/embeddium/render/EmbeddiumRenderLayerCache;forState" + + "(Lnet/minecraft/world/level/block/state/StateHolder;)Ljava/util/List;" + ) + ) + private > H iris$wrapGetFluidLayer( + H state, + @Local(argsOnly = true) ChunkBuildContext context + ) { + if (context.buffers instanceof ChunkBuildBuffersExt) { + ((ChunkBuildBuffersExt) context.buffers).iris$setMaterialId( + ((FluidState) state).createLegacyBlock(), + ExtendedDataHelper.BLOCK_RENDER_TYPE + ); + } + return state; + } - @Inject(method = "performBuild", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;hasBlockEntity()Z")) - private void iris$resetContext(ChunkBuildContext buildContext, CancellationSource cancellationSource, CallbackInfoReturnable cir) { - if (buildContext.buffers instanceof ChunkBuildBuffersExt) { - ((ChunkBuildBuffersExt) buildContext.buffers).iris$resetBlockContext(); - } - } + @Inject( + method = "performBuild", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;hasBlockEntity()Z") + ) + private void iris$resetContext( + ChunkBuildContext buildContext, + CancellationSource cancellationSource, + CallbackInfoReturnable cir + ) { + if (buildContext.buffers instanceof ChunkBuildBuffersExt) { + ((ChunkBuildBuffersExt) buildContext.buffers).iris$resetBlockContext(); + } + } } diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/directional_shading/MixinSmoothLightPipeline.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/directional_shading/MixinSmoothLightPipeline.java index 39ed530a89..e6f5d19449 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/directional_shading/MixinSmoothLightPipeline.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/directional_shading/MixinSmoothLightPipeline.java @@ -9,9 +9,9 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(SmoothLightPipeline.class) +@Mixin(value = SmoothLightPipeline.class, remap = false) public class MixinSmoothLightPipeline { - @Inject(method = "applySidedBrightness", at = @At("HEAD"), cancellable = true, remap = false) + @Inject(method = "applySidedBrightness", at = @At("HEAD"), cancellable = true) private void iris$disableDirectionalShading(QuadLightData out, Direction face, boolean shade, CallbackInfo ci) { if (BlockRenderingSettings.INSTANCE.shouldDisableDirectionalShading()) { ci.cancel(); diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/options/MixinSodiumGameOptionPages.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/options/MixinSodiumGameOptionPages.java index b34da36f73..57353d0c1d 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/options/MixinSodiumGameOptionPages.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/options/MixinSodiumGameOptionPages.java @@ -43,6 +43,24 @@ public class MixinSodiumGameOptionPages { return builder; } + @Redirect(method = "quality", remap = false, + slice = @Slice( + from = @At(value = "CONSTANT", args = "stringValue=options.graphics"), + to = @At(value = "CONSTANT", args = "stringValue=options.renderClouds") + ), + at = @At(value = "INVOKE", remap = false, + target = "me/jellysquid/mods/sodium/client/gui/options/OptionGroup$Builder.add (" + + "Lme/jellysquid/mods/sodium/client/gui/options/Option;" + + ")Lme/jellysquid/mods/sodium/client/gui/options/OptionGroup$Builder;"), + allow = 1) + private static OptionGroup.Builder iris$addColorSpaceOption(OptionGroup.Builder builder, + Option candidate) { + builder.add(candidate); + builder.add(IrisSodiumOptions.createColorSpaceButton(vanillaOpts)); + + return builder; + } + @ModifyArg(method = "quality", remap = false, slice = @Slice( from = @At(value = "CONSTANT", args = "stringValue=options.graphics"), diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/separate_ao/MixinBlockRenderer.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/separate_ao/MixinBlockRenderer.java index 773d9cba89..2fd203387a 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/separate_ao/MixinBlockRenderer.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/separate_ao/MixinBlockRenderer.java @@ -1,20 +1,19 @@ package net.coderbot.iris.compat.sodium.mixin.separate_ao; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import me.jellysquid.mods.sodium.client.render.chunk.compile.buffers.ChunkModelBuilder; import me.jellysquid.mods.sodium.client.render.pipeline.BlockRenderer; -import me.jellysquid.mods.sodium.client.util.color.ColorABGR; import net.coderbot.iris.block_rendering.BlockRenderingSettings; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.BlockPos; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.client.model.data.IModelData; - import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; /** @@ -27,22 +26,35 @@ public class MixinBlockRenderer { private boolean useSeparateAo; @Inject(method = "renderModel", remap = false, at = @At("HEAD")) - private void renderModel(BlockAndTintGetter world, BlockState state, BlockPos pos, BlockPos origin, - BakedModel model, ChunkModelBuilder buffers, boolean cull, long seed, IModelData modelData, - CallbackInfoReturnable cir) { + private void renderModel( + final BlockAndTintGetter world, + final BlockState state, + final BlockPos pos, + final BlockPos origin, + final BakedModel model, + final ChunkModelBuilder buffers, + final boolean cull, + final long seed, + final IModelData modelData, + final CallbackInfoReturnable cir + ) { this.useSeparateAo = BlockRenderingSettings.INSTANCE.shouldUseSeparateAo(); } - @Redirect(method = "renderQuad", remap = false, - at = @At(value = "INVOKE", - target = "me/jellysquid/mods/sodium/client/util/color/ColorABGR.mul (IF)I", - remap = false)) - private int iris$applySeparateAo(int color, float ao) { + @WrapOperation( + method = "renderQuad", remap = false, + at = @At( + value = "INVOKE", + target = "me/jellysquid/mods/sodium/client/util/color/ColorABGR.mul (IF)I", + remap = false + ) + ) + private int iris$applySeparateAo(int color, final float ao, final Operation original) { if (useSeparateAo) { color &= 0x00FFFFFF; color |= ((int) (ao * 255.0f)) << 24; } else { - color = ColorABGR.mul(color, ao); + color = original.call(color, ao); } return color; diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/separate_ao/MixinBufferBuilder_IntrinsicSeparateAo.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/separate_ao/MixinBufferBuilder_IntrinsicSeparateAo.java new file mode 100644 index 0000000000..3cb17b4ec3 --- /dev/null +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/separate_ao/MixinBufferBuilder_IntrinsicSeparateAo.java @@ -0,0 +1,123 @@ +package net.coderbot.iris.compat.sodium.mixin.separate_ao; + +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.DefaultedVertexConsumer; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix3f; +import com.mojang.math.Matrix4f; +import com.mojang.math.Vector4f; +import me.jellysquid.mods.sodium.client.model.quad.ModelQuadView; +import me.jellysquid.mods.sodium.client.model.vertex.VanillaVertexTypes; +import me.jellysquid.mods.sodium.client.model.vertex.VertexDrain; +import me.jellysquid.mods.sodium.client.model.vertex.formats.quad.QuadVertexSink; +import me.jellysquid.mods.sodium.client.util.color.ColorABGR; +import me.jellysquid.mods.sodium.client.util.color.ColorU8; +import me.jellysquid.mods.sodium.client.util.math.MatrixUtil; +import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.minecraft.client.renderer.block.model.BakedQuad; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Arrays; + +@Mixin(value = BufferBuilder.class, priority = 1010) +public abstract class MixinBufferBuilder_IntrinsicSeparateAo extends DefaultedVertexConsumer { + @Shadow + private boolean fastFormat; + private float[] brightnessTable; + private int brightnessIndex; + + @Overwrite + public void putBulkData(PoseStack.Pose matrices, BakedQuad quad, float[] brightnessTable, float red, float green, + float blue, int[] lights, int overlay, boolean useQuadColorData) { + if (!this.fastFormat) { + if (BlockRenderingSettings.INSTANCE.shouldUseSeparateAo()) { + this.brightnessTable = brightnessTable; + this.brightnessIndex = 0; + + brightnessTable = new float[brightnessTable.length]; + Arrays.fill(brightnessTable, 1.0f); + } + + super.putBulkData(matrices, quad, brightnessTable, red, green, blue, lights, overlay, useQuadColorData); + + return; + } + + if (this.defaultColorSet) { + throw new IllegalStateException(); + } + + ModelQuadView quadView = (ModelQuadView) quad; + + Matrix4f positionMatrix = matrices.pose(); + Matrix3f normalMatrix = matrices.normal(); + + int norm = MatrixUtil.computeNormal(normalMatrix, quad.getDirection()); + + QuadVertexSink drain = VertexDrain.of(this) + .createSink(VanillaVertexTypes.QUADS); + drain.ensureCapacity(4); + + for (int i = 0; i < 4; i++) { + float x = quadView.getX(i); + float y = quadView.getY(i); + float z = quadView.getZ(i); + + float fR; + float fG; + float fB; + + float brightness = brightnessTable[i]; + float alpha = 1.0F; + + if (BlockRenderingSettings.INSTANCE.shouldUseSeparateAo()) { + alpha = brightness; + if (useQuadColorData) { + int color = quadView.getColor(i); + + float oR = ColorU8.normalize(ColorABGR.unpackRed(color)); + float oG = ColorU8.normalize(ColorABGR.unpackGreen(color)); + float oB = ColorU8.normalize(ColorABGR.unpackBlue(color)); + + fR = oR * red; + fG = oG * green; + fB = oB * blue; + } else { + fR = red; + fG = green; + fB = blue; + } + } else { + if (useQuadColorData) { + int color = quadView.getColor(i); + + float oR = ColorU8.normalize(ColorABGR.unpackRed(color)); + float oG = ColorU8.normalize(ColorABGR.unpackGreen(color)); + float oB = ColorU8.normalize(ColorABGR.unpackBlue(color)); + + fR = oR * brightness * red; + fG = oG * brightness * green; + fB = oB * brightness * blue; + } else { + fR = brightness * red; + fG = brightness * green; + fB = brightness * blue; + } + } + + float u = quadView.getTexU(i); + float v = quadView.getTexV(i); + + int color = ColorABGR.pack(fR, fG, fB, alpha); + + Vector4f pos = new Vector4f(x, y, z, 1.0F); + pos.transform(positionMatrix); + + drain.writeQuad(pos.x(), pos.y(), pos.z(), color, u, v, lights[i], overlay, norm); + } + + drain.flush(); + } +} diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinChunkProgram.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinChunkProgram.java deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinChunkRenderShaderBackend.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinChunkRenderShaderBackend.java deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlProgram.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlProgram.java index 8c7603e187..4944c5e183 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlProgram.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlProgram.java @@ -8,10 +8,12 @@ import net.coderbot.iris.compat.sodium.impl.shader_overrides.ShaderBindingContextExt; import net.coderbot.iris.gl.IrisRenderSystem; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; import java.util.function.IntFunction; -@Mixin(GlProgram.class) +@Mixin(value = GlProgram.class, remap = false) public class MixinGlProgram extends GlObject implements ShaderBindingContextExt { public > U bindUniformIfPresent(String name, IntFunction factory) { int index = GlStateManager._glGetUniformLocation(this.handle(), name); diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlRenderDevice.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlRenderDevice.java new file mode 100644 index 0000000000..ca9dd80f2b --- /dev/null +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlRenderDevice.java @@ -0,0 +1,18 @@ +package net.coderbot.iris.compat.sodium.mixin.shader_overrides; + +import me.jellysquid.mods.sodium.client.gl.tessellation.GlPrimitiveType; +import net.coderbot.iris.vertices.ImmediateState; +import org.lwjgl.opengl.GL43C; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(targets = "me.jellysquid.mods.sodium.client.gl.device.GLRenderDevice$ImmediateDrawCommandList", remap = false) +public class MixinGlRenderDevice { + @Redirect(method = "multiDrawElementsBaseVertex", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/gl/tessellation/GlPrimitiveType;getId()I")) + private int replaceId(GlPrimitiveType instance) { + if (ImmediateState.usingTessellation) return GL43C.GL_PATCHES; + + return instance.getId(); + } +} diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinRegionChunkRenderer.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinRegionChunkRenderer.java index dd9df08961..690d9cea4d 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinRegionChunkRenderer.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinRegionChunkRenderer.java @@ -5,16 +5,16 @@ import me.jellysquid.mods.sodium.client.render.chunk.RegionChunkRenderer; import me.jellysquid.mods.sodium.client.render.chunk.shader.ChunkShaderInterface; import net.coderbot.iris.compat.sodium.impl.shader_overrides.ShaderChunkRendererExt; -import repack.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import repack.joml.Matrix4f; @Mixin(RegionChunkRenderer.class) public abstract class MixinRegionChunkRenderer implements ShaderChunkRendererExt { @Redirect(method = "render", remap = false, at = @At(value = "INVOKE", - target = "me/jellysquid/mods/sodium/client/gl/shader/GlProgram.getInterface()Ljava/lang/Object;")) + target = "me/jellysquid/mods/sodium/client/gl/shader/GlProgram.getInterface ()Ljava/lang/Object;")) private Object iris$getInterface(GlProgram program) { if (program == null) { // Iris sentinel null @@ -48,7 +48,7 @@ public abstract class MixinRegionChunkRenderer implements ShaderChunkRendererExt @Redirect(method = "render", remap = false, at = @At(value = "INVOKE", - target = "me/jellysquid/mods/sodium/client/render/chunk/shader/ChunkShaderInterface.setDrawUniforms(Lme/jellysquid/mods/sodium/client/gl/buffer/GlMutableBuffer;)V")) + target = "me/jellysquid/mods/sodium/client/render/chunk/shader/ChunkShaderInterface.setDrawUniforms (Lme/jellysquid/mods/sodium/client/gl/buffer/GlMutableBuffer;)V")) private void iris$setDrawUniforms(ChunkShaderInterface itf, GlMutableBuffer buffer) { if (itf != null) { itf.setDrawUniforms(buffer); diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinShaderChunkRenderer.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinShaderChunkRenderer.java index 3f461fa12d..438b4bbb79 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinShaderChunkRenderer.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinShaderChunkRenderer.java @@ -2,16 +2,12 @@ import com.mojang.blaze3d.systems.RenderSystem; import me.jellysquid.mods.sodium.client.gl.device.RenderDevice; -import me.jellysquid.mods.sodium.client.gl.shader.GlProgram; -import me.jellysquid.mods.sodium.client.gl.shader.GlShader; -import me.jellysquid.mods.sodium.client.gl.shader.ShaderConstants; -import me.jellysquid.mods.sodium.client.gl.shader.ShaderLoader; -import me.jellysquid.mods.sodium.client.gl.shader.ShaderParser; -import me.jellysquid.mods.sodium.client.gl.shader.ShaderType; +import me.jellysquid.mods.sodium.client.gl.shader.*; import me.jellysquid.mods.sodium.client.model.vertex.type.ChunkVertexType; import me.jellysquid.mods.sodium.client.render.chunk.ShaderChunkRenderer; import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPass; import me.jellysquid.mods.sodium.client.render.chunk.shader.ChunkShaderInterface; +import net.coderbot.iris.compat.sodium.impl.shader_overrides.IrisChunkProgramOverrides; import net.coderbot.iris.compat.sodium.impl.shader_overrides.IrisChunkShaderInterface; import net.coderbot.iris.compat.sodium.impl.shader_overrides.ShaderChunkRendererExt; import net.coderbot.iris.compat.sodium.impl.vertex_format.IrisModelVertexFormats; @@ -20,7 +16,6 @@ import net.coderbot.iris.shaderpack.transform.StringTransformations; import net.coderbot.iris.shaderpack.transform.Transformations; import net.coderbot.iris.shadows.ShadowRenderingState; -import net.coderbot.iris.compat.sodium.impl.shader_overrides.IrisChunkProgramOverrides; import net.minecraft.resources.ResourceLocation; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -31,12 +26,10 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.List; - /** * Overrides shaders in {@link ShaderChunkRenderer} with our own as needed. */ -@Mixin(ShaderChunkRenderer.class) +@Mixin(value = ShaderChunkRenderer.class, remap = false) public class MixinShaderChunkRenderer implements ShaderChunkRendererExt { @Unique private IrisChunkProgramOverrides irisChunkProgramOverrides; @@ -56,17 +49,20 @@ public class MixinShaderChunkRenderer implements ShaderChunkRendererExt { irisChunkProgramOverrides = new IrisChunkProgramOverrides(); } - @Redirect(method = "createShader", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/gl/shader/ShaderLoader;loadShader(Lme/jellysquid/mods/sodium/client/gl/shader/ShaderType;Lnet/minecraft/resources/ResourceLocation;Lme/jellysquid/mods/sodium/client/gl/shader/ShaderConstants;)Lme/jellysquid/mods/sodium/client/gl/shader/GlShader;", ordinal = 0), remap = false) + @Redirect(method = "createShader", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/gl/shader/ShaderLoader;loadShader(Lme/jellysquid/mods/sodium/client/gl/shader/ShaderType;Lnet/minecraft/resources/ResourceLocation;Lme/jellysquid/mods/sodium/client/gl/shader/ShaderConstants;)Lme/jellysquid/mods/sodium/client/gl/shader/GlShader;", ordinal = 0)) private GlShader iris$redirectOriginalShader(ShaderType type, ResourceLocation name, ShaderConstants constants) { if (this.vertexType == IrisModelVertexFormats.MODEL_VERTEX_XHFP) { - String shader = ShaderLoader.getShaderSource(name); + String shader = ShaderParser.parseShader(ShaderLoader.getShaderSource(name), constants); + shader = shader.replace("in vec2 a_LightCoord", "in ivec2 a_LightCoord"); + shader = shader.replace("vec2 _vert_tex_light_coord", "ivec2 _vert_tex_light_coord"); shader = shader.replace("v_LightCoord = _vert_tex_light_coord", "v_LightCoord = (iris_LightmapTextureMatrix * vec4(_vert_tex_light_coord, 0, 1)).xy"); StringTransformations transformations = new StringTransformations(shader); transformations.injectLine(Transformations.InjectionPoint.BEFORE_CODE, "mat4 iris_LightmapTextureMatrix = mat4(vec4(0.00390625, 0.0, 0.0, 0.0), vec4(0.0, 0.00390625, 0.0, 0.0), vec4(0.0, 0.0, 0.00390625, 0.0), vec4(0.03125, 0.03125, 0.03125, 1.0));"); - return new GlShader(type, name, ShaderParser.parseShader(transformations.toString(), constants)); + // Iris.logger.warn(transformations.toString()); + return new GlShader(type, name, transformations.toString()); } else { return ShaderLoader.loadShader(type, name, constants); } diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinShaderType.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinShaderType.java index 56af4d60d0..0b42012993 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinShaderType.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinShaderType.java @@ -4,6 +4,7 @@ import net.coderbot.iris.compat.sodium.impl.shader_overrides.IrisShaderTypes; import org.apache.commons.lang3.ArrayUtils; import org.lwjgl.opengl.GL32C; +import org.lwjgl.opengl.GL42C; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; @@ -22,7 +23,11 @@ public class MixinShaderType { IrisShaderTypes.GEOMETRY = ShaderTypeAccessor.createShaderType("GEOMETRY", baseOrdinal, GL32C.GL_GEOMETRY_SHADER); + IrisShaderTypes.TESS_CONTROL + = ShaderTypeAccessor.createShaderType("TESS_CONTROL", baseOrdinal + 1, GL42C.GL_TESS_CONTROL_SHADER); + IrisShaderTypes.TESS_EVAL + = ShaderTypeAccessor.createShaderType("TESS_EVAL", baseOrdinal + 2, GL42C.GL_TESS_EVALUATION_SHADER); - $VALUES = ArrayUtils.addAll($VALUES, IrisShaderTypes.GEOMETRY); + $VALUES = ArrayUtils.addAll($VALUES, IrisShaderTypes.GEOMETRY, IrisShaderTypes.TESS_CONTROL, IrisShaderTypes.TESS_EVAL); } } diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shadow_map/MixinRenderSectionManager.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shadow_map/MixinRenderSectionManager.java index 7ba4154d5c..26686de280 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shadow_map/MixinRenderSectionManager.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shadow_map/MixinRenderSectionManager.java @@ -10,17 +10,13 @@ import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager; import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPassManager; import me.jellysquid.mods.sodium.client.util.frustum.Frustum; +import net.coderbot.iris.compat.sodium.impl.shadow_map.SwappableRenderSectionManager; import net.coderbot.iris.pipeline.ShadowRenderer; import net.coderbot.iris.shadows.ShadowRenderingState; -import net.coderbot.iris.compat.sodium.impl.shadow_map.SwappableRenderSectionManager; import net.minecraft.client.Camera; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.level.block.entity.BlockEntity; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -34,7 +30,7 @@ * Modifies {@link RenderSectionManager} to support maintaining a separate visibility list for the shadow camera, as well * as disabling chunk rebuilds when computing visibility for the shadow camera. */ -@Mixin(RenderSectionManager.class) +@Mixin(value = RenderSectionManager.class, remap = false) public class MixinRenderSectionManager implements SwappableRenderSectionManager { @Shadow(remap = false) @Final @@ -97,7 +93,7 @@ public class MixinRenderSectionManager implements SwappableRenderSectionManager needsUpdateSwap = needsUpdateTmp; } - @Inject(method = "update", at = @At("RETURN"), remap = false) + @Inject(method = "update", at = @At("RETURN")) private void iris$captureVisibleBlockEntities(Camera camera, Frustum frustum, int frame, boolean spectator, CallbackInfo ci) { if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { ShadowRenderer.visibleBlockEntities = visibleBlockEntities; diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shadow_map/MixinSodiumWorldRenderer.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shadow_map/MixinSodiumWorldRenderer.java index 24694919ba..ad7d1e7b9d 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/shadow_map/MixinSodiumWorldRenderer.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/shadow_map/MixinSodiumWorldRenderer.java @@ -3,11 +3,10 @@ import com.mojang.blaze3d.vertex.PoseStack; import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer; import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager; -import net.coderbot.iris.shadows.ShadowRenderingState; import net.coderbot.iris.compat.sodium.impl.shadow_map.SwappableRenderSectionManager; +import net.coderbot.iris.shadows.ShadowRenderingState; import net.minecraft.client.Camera; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.culling.Frustum; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinGlAbstractTesselation.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinGlAbstractTesselation.java new file mode 100644 index 0000000000..e1fb743ba8 --- /dev/null +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinGlAbstractTesselation.java @@ -0,0 +1,19 @@ +package net.coderbot.iris.compat.sodium.mixin.vertex_format; + +import me.jellysquid.mods.sodium.client.gl.tessellation.GlAbstractTessellation; +import org.lwjgl.opengl.GL30C; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(GlAbstractTessellation.class) +public class MixinGlAbstractTesselation { + @Redirect(method = "bindAttributes", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_vertexAttribPointer(IIIZIJ)V")) + private void redirect(int index, int size, int type, boolean normalized, int stride, long pointer) { + if (type == GL30C.GL_UNSIGNED_SHORT && size == 2 && !normalized && pointer == 16) { + GL30C.glVertexAttribIPointer(index, size, type, stride, pointer); + } else { + GL30C.glVertexAttribPointer(index, size, type, normalized, stride, pointer); + } + } +} diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinRegionChunkRenderer.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinRegionChunkRenderer.java index 31244134b5..25bb97351a 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinRegionChunkRenderer.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinRegionChunkRenderer.java @@ -6,7 +6,6 @@ import me.jellysquid.mods.sodium.client.model.vertex.type.ChunkVertexType; import me.jellysquid.mods.sodium.client.render.chunk.RegionChunkRenderer; import me.jellysquid.mods.sodium.client.render.chunk.format.ChunkMeshAttribute; -import net.coderbot.iris.Iris; import net.coderbot.iris.block_rendering.BlockRenderingSettings; import net.coderbot.iris.compat.sodium.impl.IrisChunkShaderBindingPoints; import net.coderbot.iris.compat.sodium.impl.vertex_format.IrisChunkMeshAttributes; diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinRenderRegionArenas.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinRenderRegionArenas.java index a4f31e9dff..d28522421b 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinRenderRegionArenas.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinRenderRegionArenas.java @@ -3,7 +3,6 @@ import me.jellysquid.mods.sodium.client.gl.attribute.BufferVertexFormat; import me.jellysquid.mods.sodium.client.render.chunk.format.ChunkModelVertexFormats; import me.jellysquid.mods.sodium.client.render.chunk.region.RenderRegion; -import net.coderbot.iris.Iris; import net.coderbot.iris.block_rendering.BlockRenderingSettings; import net.coderbot.iris.compat.sodium.impl.vertex_format.IrisModelVertexFormats; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinRenderSectionManager.java b/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinRenderSectionManager.java index e2cbe53378..a2f556d291 100644 --- a/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinRenderSectionManager.java +++ b/src/main/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/MixinRenderSectionManager.java @@ -2,7 +2,6 @@ import me.jellysquid.mods.sodium.client.model.vertex.type.ChunkVertexType; import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager; -import net.coderbot.iris.Iris; import net.coderbot.iris.block_rendering.BlockRenderingSettings; import net.coderbot.iris.compat.sodium.impl.vertex_format.IrisModelVertexFormats; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/net/coderbot/iris/compliance/ComplianceVersion.java b/src/main/java/net/coderbot/iris/compliance/ComplianceVersion.java new file mode 100644 index 0000000000..a0a3c16d4a --- /dev/null +++ b/src/main/java/net/coderbot/iris/compliance/ComplianceVersion.java @@ -0,0 +1,30 @@ +package net.coderbot.iris.compliance; + +import net.coderbot.iris.Iris; + +public enum ComplianceVersion { + NO_COMPLIANCE, + v1; + + public int getInternalComplianceLevel() { + switch (this) { + case NO_COMPLIANCE -> { + return 0; + } + case v1 -> { + return 1; + } + default -> throw new IllegalStateException("Impossible, compliance is not existing? " + this.name()); + } + } + + public static ComplianceVersion getComplianceLevel(String compliance) { + try { + int complianceL = Integer.parseInt(compliance); + return ComplianceVersion.valueOf("v" + complianceL); + } catch (IllegalArgumentException e) { + Iris.logger.warn("Unknown compliance: " + compliance + "; defaulting to NONCOMPLIANT."); + return NO_COMPLIANCE; + } + } +} diff --git a/src/main/java/net/coderbot/iris/config/IrisConfig.java b/src/main/java/net/coderbot/iris/config/IrisConfig.java index 576997a548..48e5fb0044 100644 --- a/src/main/java/net/coderbot/iris/config/IrisConfig.java +++ b/src/main/java/net/coderbot/iris/config/IrisConfig.java @@ -1,6 +1,7 @@ package net.coderbot.iris.config; import net.coderbot.iris.Iris; +import net.coderbot.iris.colorspace.ColorSpace; import net.coderbot.iris.gui.option.IrisVideoSettings; import java.io.IOException; @@ -139,9 +140,11 @@ public void load() throws IOException { disableUpdateMessage = "true".equals(properties.getProperty("disableUpdateMessage")); try { IrisVideoSettings.shadowDistance = Integer.parseInt(properties.getProperty("maxShadowRenderDistance", "32")); - } catch (NumberFormatException e) { + IrisVideoSettings.colorSpace = ColorSpace.valueOf(properties.getProperty("colorSpace", "SRGB")); + } catch (IllegalArgumentException e) { Iris.logger.error("Shadow distance setting reset; value is invalid."); IrisVideoSettings.shadowDistance = 32; + IrisVideoSettings.colorSpace = ColorSpace.SRGB; save(); } @@ -164,6 +167,7 @@ public void save() throws IOException { properties.setProperty("enableDebugOptions", enableDebugOptions ? "true" : "false"); properties.setProperty("disableUpdateMessage", disableUpdateMessage ? "true" : "false"); properties.setProperty("maxShadowRenderDistance", String.valueOf(IrisVideoSettings.shadowDistance)); + properties.setProperty("colorSpace", IrisVideoSettings.colorSpace.name()); // NB: This uses ISO-8859-1 with unicode escapes as the encoding try (OutputStream os = Files.newOutputStream(propertiesPath)) { properties.store(os, COMMENT); diff --git a/src/main/java/net/coderbot/iris/features/FeatureFlags.java b/src/main/java/net/coderbot/iris/features/FeatureFlags.java index a5ab6a2b96..01ca0059ff 100644 --- a/src/main/java/net/coderbot/iris/features/FeatureFlags.java +++ b/src/main/java/net/coderbot/iris/features/FeatureFlags.java @@ -5,13 +5,19 @@ import org.apache.commons.lang3.text.WordUtils; import java.util.List; +import java.util.Locale; import java.util.function.BooleanSupplier; public enum FeatureFlags { SEPARATE_HARDWARE_SAMPLERS(() -> true, () -> true), + HIGHER_SHADOWCOLOR(() -> true, () -> true), + CUSTOM_IMAGES(() -> true, IrisRenderSystem::supportsImageLoadStore), PER_BUFFER_BLENDING(() -> true, IrisRenderSystem::supportsBufferBlending), COMPUTE_SHADERS(() -> true, IrisRenderSystem::supportsCompute), + TESSELATION_SHADERS(() -> true, IrisRenderSystem::supportsTesselation), ENTITY_TRANSLUCENT(() -> true, () -> true), + REVERSED_CULLING(() -> true, () -> true), + SSBO(() -> true, IrisRenderSystem::supportsSSBO), UNKNOWN(() -> false, () -> false); private final BooleanSupplier irisRequirement; @@ -53,7 +59,7 @@ public boolean isUsable() { public static boolean isInvalid(String name) { try { - return !FeatureFlags.valueOf(name).isUsable(); + return !FeatureFlags.valueOf(name.toUpperCase(Locale.US)).isUsable(); } catch (IllegalArgumentException e) { return true; } @@ -61,7 +67,7 @@ public static boolean isInvalid(String name) { public static FeatureFlags getValue(String value) { try { - return FeatureFlags.valueOf(value); + return FeatureFlags.valueOf(value.toUpperCase(Locale.US)); } catch (IllegalArgumentException e) { return FeatureFlags.UNKNOWN; } diff --git a/src/main/java/net/coderbot/iris/gbuffer_overrides/matching/InputAvailability.java b/src/main/java/net/coderbot/iris/gbuffer_overrides/matching/InputAvailability.java index cf0899196c..8d53f374b6 100644 --- a/src/main/java/net/coderbot/iris/gbuffer_overrides/matching/InputAvailability.java +++ b/src/main/java/net/coderbot/iris/gbuffer_overrides/matching/InputAvailability.java @@ -6,6 +6,7 @@ public class InputAvailability { public final boolean texture; public final boolean lightmap; public final boolean overlay; + // WARNING: adding new fields requires updating hashCode and equals methods! public InputAvailability(boolean texture, boolean lightmap, boolean overlay) { this.texture = texture; @@ -42,19 +43,19 @@ public int pack() { @Override public String toString() { return "InputAvailability{" + - "texture=" + texture + - ", lightmap=" + lightmap + - ", overlay=" + overlay + - '}'; + "texture=" + texture + + ", lightmap=" + lightmap + + ", overlay=" + overlay + + '}'; } @Override public int hashCode() { final int prime = 31; int result = 1; + result = prime * result + (texture ? 1231 : 1237); result = prime * result + (lightmap ? 1231 : 1237); result = prime * result + (overlay ? 1231 : 1237); - result = prime * result + (texture ? 1231 : 1237); return result; } @@ -67,12 +68,12 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; InputAvailability other = (InputAvailability) obj; + if (texture != other.texture) + return false; if (lightmap != other.lightmap) return false; if (overlay != other.overlay) return false; - if (texture != other.texture) - return false; return true; } } diff --git a/src/main/java/net/coderbot/iris/gl/BooleanStateExtended.java b/src/main/java/net/coderbot/iris/gl/BooleanStateExtended.java new file mode 100644 index 0000000000..6abb45414d --- /dev/null +++ b/src/main/java/net/coderbot/iris/gl/BooleanStateExtended.java @@ -0,0 +1,5 @@ +package net.coderbot.iris.gl; + +public interface BooleanStateExtended { + void setUnknownState(); +} diff --git a/src/main/java/net/coderbot/iris/gl/IrisRenderSystem.java b/src/main/java/net/coderbot/iris/gl/IrisRenderSystem.java index 522d49fc64..91827d0a87 100644 --- a/src/main/java/net/coderbot/iris/gl/IrisRenderSystem.java +++ b/src/main/java/net/coderbot/iris/gl/IrisRenderSystem.java @@ -4,6 +4,8 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.math.Matrix4f; import net.coderbot.iris.Iris; +import net.coderbot.iris.gl.sampler.GlSampler; +import net.coderbot.iris.gl.sampler.SamplerLimits; import net.coderbot.iris.mixin.GlStateManagerAccessor; import net.coderbot.iris.vendored.joml.Vector3i; import org.jetbrains.annotations.Nullable; @@ -16,8 +18,14 @@ import org.lwjgl.opengl.GL11C; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30C; +import org.lwjgl.opengl.GL32C; +import org.lwjgl.opengl.GL33C; import org.lwjgl.opengl.GL40C; import org.lwjgl.opengl.GL42C; +import org.lwjgl.opengl.GL43C; +import org.lwjgl.opengl.GL45C; +import org.lwjgl.opengl.GL46C; +import org.lwjgl.opengl.NVXGPUMemoryInfo; import org.lwjgl.opengl.GL45C; import org.lwjgl.system.MemoryUtil; @@ -34,6 +42,10 @@ public class IrisRenderSystem { private static DSAAccess dsaState; private static boolean hasMultibind; private static boolean supportsCompute; + private static boolean supportsTesselation; + private static int polygonMode = GL43C.GL_FILL; + private static int backupPolygonMode = GL43C.GL_FILL; + private static int[] samplers; public static void initRenderer() { if (GL.getCapabilities().OpenGL45) { @@ -50,6 +62,9 @@ public static void initRenderer() { hasMultibind = GL.getCapabilities().OpenGL45 || GL.getCapabilities().GL_ARB_multi_bind; supportsCompute = GL.getCapabilities().glDispatchCompute != MemoryUtil.NULL; + supportsTesselation = GL.getCapabilities().GL_ARB_tessellation_shader || GL.getCapabilities().OpenGL40; + + samplers = new int[SamplerLimits.get().getMaxTextureUnits()]; } public static void getIntegerv(int pname, int[] params) { @@ -120,6 +135,11 @@ public static void uniform3f(int location, float v0, float v1, float v2) { GL32C.glUniform3f(location, v0, v1, v2); } + public static void uniform3i(int location, int v0, int v1, int v2) { + RenderSystem.assertOnRenderThreadOrInit(); + GL32C.glUniform3i(location, v0, v1, v2); + } + public static void uniform4f(int location, float v0, float v1, float v2, float v3) { RenderSystem.assertOnRenderThreadOrInit(); GL32C.glUniform4f(location, v0, v1, v2, v3); @@ -197,6 +217,17 @@ public static int bufferStorage(int target, float[] data, int usage) { return dsaState.bufferStorage(target, data, usage); } + public static void bufferStorage(int target, long size, int flags) { + RenderSystem.assertOnRenderThreadOrInit(); + // The ARB version is identical to GL44 and redirects, so this should work on ARB as well. + GL45C.glBufferStorage(target, size, flags); + } + + public static void bindBufferBase(int target, Integer index, int buffer) { + RenderSystem.assertOnRenderThreadOrInit(); + GL43C.glBindBufferBase(target, index, buffer); + } + public static void vertexAttrib4f(int index, float v0, float v1, float v2, float v3) { RenderSystem.assertOnRenderThreadOrInit(); GL32C.glVertexAttrib4f(index, v0, v1, v2, v3); @@ -218,7 +249,7 @@ public static int getTexParameteri(int texture, int target, int pname) { public static void bindImageTexture(int unit, int texture, int level, boolean layered, int layer, int access, int format) { RenderSystem.assertOnRenderThreadOrInit(); - if (GL.getCapabilities().OpenGL42) { + if (GL.getCapabilities().OpenGL42 || GL.getCapabilities().GL_ARB_shader_image_load_store) { GL42C.glBindImageTexture(unit, texture, level, layered, layer, access, format); } else { EXTShaderImageLoadStore.glBindImageTextureEXT(unit, texture, level, layered, layer, access, format); @@ -226,7 +257,7 @@ public static void bindImageTexture(int unit, int texture, int level, boolean la } public static int getMaxImageUnits() { - if (GL.getCapabilities().OpenGL42) { + if (GL.getCapabilities().OpenGL42 || GL.getCapabilities().GL_ARB_shader_image_load_store) { return GlStateManager._getInteger(GL42C.GL_MAX_IMAGE_UNITS); } else if (GL.getCapabilities().GL_EXT_shader_image_load_store) { return GlStateManager._getInteger(EXTShaderImageLoadStore.GL_MAX_IMAGE_UNITS_EXT); @@ -235,6 +266,22 @@ public static int getMaxImageUnits() { } } + public static boolean supportsSSBO() { + return GL.getCapabilities().OpenGL44 || (GL.getCapabilities().GL_ARB_shader_storage_buffer_object && GL.getCapabilities().GL_ARB_buffer_storage); + } + + public static boolean supportsImageLoadStore() { + return GL.getCapabilities().glBindImageTexture != 0L || GL.getCapabilities().OpenGL42 || ((GL.getCapabilities().GL_ARB_shader_image_load_store || GL.getCapabilities().GL_EXT_shader_image_load_store) && GL.getCapabilities().GL_ARB_buffer_storage); + } + + public static void genBuffers(int[] buffers) { + GL43C.glGenBuffers(buffers); + } + + public static void clearBufferSubData(int glShaderStorageBuffer, int glR8, long offset, long size, int glRed, int glByte, int[] ints) { + GL43C.glClearBufferSubData(glShaderStorageBuffer, glR8, offset, size, glRed, glByte, ints); + } + public static void getProgramiv(int program, int value, int[] storage) { GL32C.glGetProgramiv(program, value, storage); } @@ -262,11 +309,13 @@ public static boolean supportsBufferBlending() { public static void disableBufferBlend(int buffer) { RenderSystem.assertOnRenderThreadOrInit(); GL32C.glDisablei(GL32C.GL_BLEND, buffer); + ((BooleanStateExtended) GlStateManagerAccessor.getBLEND().mode).setUnknownState(); } public static void enableBufferBlend(int buffer) { RenderSystem.assertOnRenderThreadOrInit(); GL32C.glEnablei(GL32C.GL_BLEND, buffer); + ((BooleanStateExtended) GlStateManagerAccessor.getBLEND().mode).setUnknownState(); } public static void blendFuncSeparatei(int buffer, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) { @@ -320,6 +369,95 @@ public static boolean supportsCompute() { return supportsCompute; } + public static boolean supportsTesselation() { + return supportsTesselation; + } + + public static int genSampler() { + return GL33C.glGenSamplers(); + } + + public static void destroySampler(int glId) { + GL33C.glDeleteSamplers(glId); + } + + public static void bindSamplerToUnit(int unit, int sampler) { + if (samplers[unit] == sampler) { + return; + } + + GL33C.glBindSampler(unit, sampler); + + samplers[unit] = sampler; + } + + private static int[] emptyArray = new int[SamplerLimits.get().getMaxTextureUnits()]; + + public static void unbindAllSamplers() { + boolean usedASampler = false; + for (int i = 0; i < samplers.length; i++) { + if (samplers[i] != 0) { + usedASampler = true; + if (!hasMultibind) GL33C.glBindSampler(i, 0); + samplers[i] = 0; + } + } + if (usedASampler && hasMultibind) { + GL45C.glBindSamplers(0, emptyArray); + } + } + + + public static void samplerParameteri(int sampler, int pname, int param) { + GL33C.glSamplerParameteri(sampler, pname, param); + } + + public static void samplerParameterf(int sampler, int pname, float param) { + GL33C.glSamplerParameterf(sampler, pname, param); + } + + public static void samplerParameteriv(int sampler, int pname, int[] params) { + GL33C.glSamplerParameteriv(sampler, pname, params); + } + + public static long getVRAM() { + if (GL.getCapabilities().GL_NVX_gpu_memory_info) { + return GL32C.glGetInteger(NVXGPUMemoryInfo.GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX) * 1024L; + } else { + return 4294967296L; + } + } + + public static void deleteBuffers(int glId) { + RenderSystem.assertOnRenderThreadOrInit(); + GL43C.glDeleteBuffers(glId); + } + + public static void setPolygonMode(int mode) { + if (mode != polygonMode) { + polygonMode = mode; + GL43C.glPolygonMode(GL43C.GL_FRONT_AND_BACK, mode); + } + } + + public static void overridePolygonMode() { + backupPolygonMode = polygonMode; + setPolygonMode(GL43C.GL_FILL); + } + + public static void restorePolygonMode() { + setPolygonMode(backupPolygonMode); + backupPolygonMode = GL43C.GL_FILL; + } + + public static void dispatchComputeIndirect(long offset) { + GL43C.glDispatchComputeIndirect(offset); + } + + public static void bindBuffer(int target, int buffer) { + GL46C.glBindBuffer(target, buffer); + } + public interface DSAAccess { void generateMipmaps(int texture, int target); @@ -395,6 +533,10 @@ public void copyTexSubImage2D(int destTexture, int target, int i, int i1, int i2 @Override public void bindTextureToUnit(int target, int unit, int texture) { + if (GlStateManagerAccessor.getTEXTURES()[unit].binding == texture) { + return; + } + ARBDirectStateAccess.glBindTextureUnit(unit, texture); // Manually fix GLStateManager bindings... diff --git a/src/main/java/net/coderbot/iris/gl/blending/AlphaTest.java b/src/main/java/net/coderbot/iris/gl/blending/AlphaTest.java index b4e455e6e7..d1d2e12ebf 100644 --- a/src/main/java/net/coderbot/iris/gl/blending/AlphaTest.java +++ b/src/main/java/net/coderbot/iris/gl/blending/AlphaTest.java @@ -7,6 +7,7 @@ public class AlphaTest { private final AlphaTestFunction function; private final float reference; + // WARNING: adding new fields requires updating hashCode and equals methods! public AlphaTest(AlphaTestFunction function, float reference) { this.function = function; @@ -23,16 +24,16 @@ public String toExpression(String alphaAccessor, String alphaThreshold, String i if (function == AlphaTestFunction.ALWAYS) { return "// alpha test disabled\n"; } else if (this == AlphaTests.VERTEX_ALPHA) { - return indentation + "if (!(" + alphaAccessor + " > iris_vertexColor.a)) {\n" + - indentation + " discard;\n" + - indentation + "}\n"; + return indentation + "if (!(" + alphaAccessor + " > iris_vertexColorAlpha)) {\n" + + indentation + " discard;\n" + + indentation + "}\n"; } else if (function == AlphaTestFunction.NEVER) { return "discard;\n"; } return indentation + "if (!(" + alphaAccessor + " " + expr + " " + alphaThreshold + ")) {\n" + - indentation + " discard;\n" + - indentation + "}\n"; + indentation + " discard;\n" + + indentation + "}\n"; } public AlphaTestFunction getFunction() { diff --git a/src/main/java/net/coderbot/iris/gl/buffer/ShaderStorageBuffer.java b/src/main/java/net/coderbot/iris/gl/buffer/ShaderStorageBuffer.java new file mode 100644 index 0000000000..0fc06b5b25 --- /dev/null +++ b/src/main/java/net/coderbot/iris/gl/buffer/ShaderStorageBuffer.java @@ -0,0 +1,57 @@ +package net.coderbot.iris.gl.buffer; + +import com.mojang.blaze3d.platform.GlStateManager; +import net.coderbot.iris.gl.IrisRenderSystem; +import org.lwjgl.opengl.GL43C; + +// Do not extend GlResource, this is immutable. +public class ShaderStorageBuffer { + protected int id; + protected final int index; + protected final ShaderStorageInfo info; + + public ShaderStorageBuffer(int index, ShaderStorageInfo info) { + this.id = GlStateManager._glGenBuffers(); + this.index = index; + this.info = info; + } + + public final int getIndex() { + return index; + } + + public final long getSize() { + return info.size(); + } + + protected void destroy() { + IrisRenderSystem.bindBufferBase(GL43C.GL_SHADER_STORAGE_BUFFER, index, 0); + // DO NOT use the GlStateManager version here! On Linux, it will attempt to clear the data using BufferData and cause GL errors. + IrisRenderSystem.deleteBuffers(id); + } + + public void bind() { + IrisRenderSystem.bindBufferBase(GL43C.GL_SHADER_STORAGE_BUFFER, index, id); + } + + public void resizeIfRelative(int width, int height) { + if (!info.relative()) return; + + IrisRenderSystem.deleteBuffers(id); + int newId = GlStateManager._glGenBuffers(); + GlStateManager._glBindBuffer(GL43C.GL_SHADER_STORAGE_BUFFER, newId); + + // Calculation time + int newWidth = (int) (width * info.scaleX()); + int newHeight = (int) (height * info.scaleY()); + int finalSize = (newHeight * newWidth) * info.size(); + IrisRenderSystem.bufferStorage(GL43C.GL_SHADER_STORAGE_BUFFER, finalSize, 0); + IrisRenderSystem.clearBufferSubData(GL43C.GL_SHADER_STORAGE_BUFFER, GL43C.GL_R8, 0, finalSize, GL43C.GL_RED, GL43C.GL_BYTE, new int[] {0}); + IrisRenderSystem.bindBufferBase(GL43C.GL_SHADER_STORAGE_BUFFER, index, newId); + id = newId; + } + + public int getId() { + return id; + } +} diff --git a/src/main/java/net/coderbot/iris/gl/buffer/ShaderStorageBufferHolder.java b/src/main/java/net/coderbot/iris/gl/buffer/ShaderStorageBufferHolder.java new file mode 100644 index 0000000000..3ea5cf1258 --- /dev/null +++ b/src/main/java/net/coderbot/iris/gl/buffer/ShaderStorageBufferHolder.java @@ -0,0 +1,89 @@ +package net.coderbot.iris.gl.buffer; + +import com.mojang.blaze3d.platform.GlStateManager; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; +import net.coderbot.iris.gl.IrisRenderSystem; +import net.coderbot.iris.gl.sampler.SamplerLimits; +import org.lwjgl.opengl.GL43C; + +import java.util.Collections; + +public class ShaderStorageBufferHolder { + private int cachedWidth; + private int cachedHeight; + private ShaderStorageBuffer[] buffers; + private boolean destroyed; + + public ShaderStorageBufferHolder(Int2ObjectArrayMap overrides, int width, int height) { + destroyed = false; + cachedWidth = width; + cachedHeight = height; + buffers = new ShaderStorageBuffer[Collections.max(overrides.keySet()) + 1]; + overrides.forEach((index, bufferInfo) -> { + if (bufferInfo.size() > IrisRenderSystem.getVRAM()) { + throw new OutOfVideoMemoryError("We only have " + toMib(IrisRenderSystem.getVRAM()) + "MiB of RAM to work with, but the pack is requesting " + bufferInfo.size() + "! Can't continue."); + } + + if (index > SamplerLimits.get().getMaxShaderStorageUnits()) { + throw new IllegalStateException("We don't have enough SSBO units??? (index: " + index + ", max: " + SamplerLimits.get().getMaxShaderStorageUnits()); + } + + buffers[index] = new ShaderStorageBuffer(index, bufferInfo); + int buffer = buffers[index].getId(); + + if (bufferInfo.relative()) { + buffers[index].resizeIfRelative(width, height); + } else { + GlStateManager._glBindBuffer(GL43C.GL_SHADER_STORAGE_BUFFER, buffer); + IrisRenderSystem.bufferStorage(GL43C.GL_SHADER_STORAGE_BUFFER, bufferInfo.size(), 0); + IrisRenderSystem.clearBufferSubData(GL43C.GL_SHADER_STORAGE_BUFFER, GL43C.GL_R8, 0, bufferInfo.size(), GL43C.GL_RED, GL43C.GL_BYTE, new int[] {0}); + IrisRenderSystem.bindBufferBase(GL43C.GL_SHADER_STORAGE_BUFFER, index, buffer); + } + }); + GlStateManager._glBindBuffer(GL43C.GL_SHADER_STORAGE_BUFFER, 0); + } + + public void hasResizedScreen(int width, int height) { + if (width != cachedWidth || height != cachedHeight) { + cachedWidth = width; + cachedHeight = height; + for (ShaderStorageBuffer buffer : buffers) { + buffer.resizeIfRelative(width, height); + } + } + } + + private static long toMib(long x) { + return x / 1024L / 1024L; + } + + public void setupBuffers() { + if (destroyed) { + throw new IllegalStateException("Tried to use destroyed buffer objects"); + } + + for (ShaderStorageBuffer buffer : buffers) { + buffer.bind(); + } + } + + public int getBufferIndex(int index) { + if (buffers.length < index || buffers[index] == null) throw new RuntimeException("Tried to query a buffer for indirect dispatch that doesn't exist!"); + + return buffers[index].getId(); + } + + public void destroyBuffers() { + for (ShaderStorageBuffer buffer : buffers) { + buffer.destroy(); + } + buffers = null; + destroyed = true; + } + + private static class OutOfVideoMemoryError extends RuntimeException { + public OutOfVideoMemoryError(String s) { + super(s); + } + } +} diff --git a/src/main/java/net/coderbot/iris/gl/buffer/ShaderStorageInfo.java b/src/main/java/net/coderbot/iris/gl/buffer/ShaderStorageInfo.java new file mode 100644 index 0000000000..5f7e78aead --- /dev/null +++ b/src/main/java/net/coderbot/iris/gl/buffer/ShaderStorageInfo.java @@ -0,0 +1,4 @@ +package net.coderbot.iris.gl.buffer; + +public record ShaderStorageInfo(int size, boolean relative, float scaleX, float scaleY) { +} diff --git a/src/main/java/net/coderbot/iris/gl/framebuffer/ViewportData.java b/src/main/java/net/coderbot/iris/gl/framebuffer/ViewportData.java new file mode 100644 index 0000000000..0b33fdbd69 --- /dev/null +++ b/src/main/java/net/coderbot/iris/gl/framebuffer/ViewportData.java @@ -0,0 +1,9 @@ +package net.coderbot.iris.gl.framebuffer; + +public record ViewportData(float scale, float viewportX, float viewportY) { + private static ViewportData DEFAULT = new ViewportData(1.0f, 0.0f, 0.0f); + + public static ViewportData defaultValue() { + return DEFAULT; + } +} diff --git a/src/main/java/net/coderbot/iris/gl/image/GlImage.java b/src/main/java/net/coderbot/iris/gl/image/GlImage.java new file mode 100644 index 0000000000..f6728d00dd --- /dev/null +++ b/src/main/java/net/coderbot/iris/gl/image/GlImage.java @@ -0,0 +1,138 @@ +package net.coderbot.iris.gl.image; + +import com.mojang.blaze3d.platform.GlStateManager; +import net.coderbot.iris.gl.GlResource; +import net.coderbot.iris.gl.IrisRenderSystem; +import net.coderbot.iris.gl.texture.InternalTextureFormat; +import net.coderbot.iris.gl.texture.PixelFormat; +import net.coderbot.iris.gl.texture.PixelType; +import net.coderbot.iris.gl.texture.TextureType; +import org.lwjgl.opengl.*; + +public class GlImage extends GlResource { + protected final String name; + protected final String samplerName; + protected final TextureType target; + protected final PixelFormat format; + protected final InternalTextureFormat internalTextureFormat; + protected final PixelType pixelType; + private final boolean clear; + + public GlImage(String name, String samplerName, TextureType target, PixelFormat format, InternalTextureFormat internalFormat, PixelType pixelType, boolean clear, int width, int height, int depth) { + super(IrisRenderSystem.createTexture(target.getGlType())); + + this.name = name; + this.samplerName = samplerName; + this.target = target; + this.format = format; + this.internalTextureFormat = internalFormat; + this.pixelType = pixelType; + this.clear = clear; + + IrisRenderSystem.bindTextureForSetup(target.getGlType(), getGlId()); + target.apply(getGlId(), width, height, depth, internalFormat.getGlFormat(), format.getGlFormat(), pixelType.getGlFormat(), null); + + int texture = getGlId(); + + setup(texture, width, height, depth); + + IrisRenderSystem.bindTextureForSetup(target.getGlType(), 0); + } + + protected void setup(int texture, int width, int height, int depth) { + IrisRenderSystem.texParameteri(texture, target.getGlType(), GL11C.GL_TEXTURE_MIN_FILTER, GL11C.GL_LINEAR); + IrisRenderSystem.texParameteri(texture, target.getGlType(), GL11C.GL_TEXTURE_MAG_FILTER, GL11C.GL_LINEAR); + IrisRenderSystem.texParameteri(texture, target.getGlType(), GL11C.GL_TEXTURE_WRAP_S, GL13C.GL_CLAMP_TO_EDGE); + + if (height > 0) { + IrisRenderSystem.texParameteri(texture, target.getGlType(), GL11C.GL_TEXTURE_WRAP_T, GL13C.GL_CLAMP_TO_EDGE); + } + + if (depth > 0) { + IrisRenderSystem.texParameteri(texture, target.getGlType(), GL30C.GL_TEXTURE_WRAP_R, GL13C.GL_CLAMP_TO_EDGE); + } + + IrisRenderSystem.texParameteri(texture, target.getGlType(), GL20C.GL_TEXTURE_MAX_LEVEL, 0); + IrisRenderSystem.texParameteri(texture, target.getGlType(), GL20C.GL_TEXTURE_MIN_LOD, 0); + IrisRenderSystem.texParameteri(texture, target.getGlType(), GL20C.GL_TEXTURE_MAX_LOD,0); + IrisRenderSystem.texParameterf(texture, target.getGlType(), GL20C.GL_TEXTURE_LOD_BIAS, 0.0F); + + ARBClearTexture.glClearTexImage(texture, 0, format.getGlFormat(), pixelType.getGlFormat(), (int[]) null); + } + + public String getName() { + return name; + } + + public String getSamplerName() { + return samplerName; + } + + public TextureType getTarget() { + return target; + } + + public boolean shouldClear() { + return clear; + } + + public int getId() { + return getGlId(); + } + + /** + * This makes the image aware of a new render target. Depending on the image's properties, it may not follow these targets. + * @param width The width of the main render target. + * @param height The height of the main render target. + */ + public void updateNewSize(int width, int height) { + + } + + @Override + protected void destroyInternal() { + GlStateManager._deleteTexture(getGlId()); + } + + public InternalTextureFormat getInternalFormat() { + return internalTextureFormat; + } + + @Override + public String toString() { + return "GlImage name " + name + " format " + format + "internalformat " + internalTextureFormat + " pixeltype " + pixelType; + } + + public PixelFormat getFormat() { + return format; + } + + public PixelType getPixelType() { + return pixelType; + } + + public static class Relative extends GlImage { + + private final float relativeHeight; + private final float relativeWidth; + + public Relative(String name, String samplerName, PixelFormat format, InternalTextureFormat internalFormat, PixelType pixelType, boolean clear, float relativeWidth, float relativeHeight, int currentWidth, int currentHeight) { + super(name, samplerName, TextureType.TEXTURE_2D, format, internalFormat, pixelType, clear, (int) (currentWidth * relativeWidth), (int) (currentHeight * relativeHeight), 0); + + this.relativeWidth = relativeWidth; + this.relativeHeight = relativeHeight; + } + + @Override + public void updateNewSize(int width, int height) { + IrisRenderSystem.bindTextureForSetup(target.getGlType(), getGlId()); + target.apply(getGlId(), (int) (width * relativeWidth), (int) (height * relativeHeight), 0, internalTextureFormat.getGlFormat(), format.getGlFormat(), pixelType.getGlFormat(), null); + + int texture = getGlId(); + + setup(texture, width, height, 0); + + IrisRenderSystem.bindTextureForSetup(target.getGlType(), 0); + } + } +} diff --git a/src/main/java/net/coderbot/iris/gl/image/ImageBinding.java b/src/main/java/net/coderbot/iris/gl/image/ImageBinding.java index f643051879..d6feb02418 100644 --- a/src/main/java/net/coderbot/iris/gl/image/ImageBinding.java +++ b/src/main/java/net/coderbot/iris/gl/image/ImageBinding.java @@ -19,6 +19,7 @@ public ImageBinding(int imageUnit, int internalFormat, IntSupplier textureID) { public void update() { // We can assume that image bindings are supported here as either the EXT extension or 4.2 core, as otherwise ImageLimits // would report that zero image units are supported. - IrisRenderSystem.bindImageTexture(imageUnit, textureID.getAsInt(), 0, false, 0, GL42C.GL_READ_WRITE, internalFormat); + // RRe36: I'm not sure if its perfectly fine to always have it be layered, but according to Balint its *probably* fine. Still might need to verify that though. + IrisRenderSystem.bindImageTexture(imageUnit, textureID.getAsInt(), 0, true, 0, GL42C.GL_READ_WRITE, internalFormat); } } diff --git a/src/main/java/net/coderbot/iris/gl/program/ComputeProgram.java b/src/main/java/net/coderbot/iris/gl/program/ComputeProgram.java index cca71b346d..8e0a650bc6 100644 --- a/src/main/java/net/coderbot/iris/gl/program/ComputeProgram.java +++ b/src/main/java/net/coderbot/iris/gl/program/ComputeProgram.java @@ -6,10 +6,13 @@ import net.coderbot.iris.gl.GlResource; import net.coderbot.iris.gl.IrisRenderSystem; import net.coderbot.iris.pipeline.WorldRenderingPipeline; +import net.coderbot.iris.shaderpack.FilledIndirectPointer; +import net.coderbot.iris.shaderpack.IndirectPointer; import net.coderbot.iris.uniforms.custom.CustomUniforms; import net.coderbot.iris.vendored.joml.Vector2f; import net.coderbot.iris.vendored.joml.Vector3i; import org.lwjgl.opengl.GL43C; +import org.lwjgl.opengl.GL46C; public final class ComputeProgram extends GlResource { private final ProgramUniforms uniforms; @@ -21,6 +24,7 @@ public final class ComputeProgram extends GlResource { private float cachedWidth; private float cachedHeight; private Vector3i cachedWorkGroups; + private FilledIndirectPointer indirectPointer; ComputeProgram(int program, ProgramUniforms uniforms, ProgramSamplers samplers, ProgramImages images) { super(program); @@ -32,12 +36,15 @@ public final class ComputeProgram extends GlResource { this.images = images; } - public void setWorkGroupInfo(Vector2f relativeWorkGroups, Vector3i absoluteWorkGroups) { + public void setWorkGroupInfo(Vector2f relativeWorkGroups, Vector3i absoluteWorkGroups, FilledIndirectPointer indirectPointer) { this.relativeWorkGroups = relativeWorkGroups; this.absoluteWorkGroups = absoluteWorkGroups; + this.indirectPointer = indirectPointer; } public Vector3i getWorkGroups(float width, float height) { + if (indirectPointer != null) return null; + if (cachedWidth != width || cachedHeight != height || cachedWorkGroups == null) { this.cachedWidth = width; this.cachedHeight = height; @@ -65,10 +72,15 @@ public void use() { public void dispatch(float width, float height) { if (!Iris.getPipelineManager().getPipeline().map(WorldRenderingPipeline::allowConcurrentCompute).orElse(false)) { - IrisRenderSystem.memoryBarrier(40); + IrisRenderSystem.memoryBarrier(GL43C.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL43C.GL_TEXTURE_FETCH_BARRIER_BIT | GL43C.GL_SHADER_STORAGE_BARRIER_BIT); } - IrisRenderSystem.dispatchCompute(getWorkGroups(width, height)); + if (indirectPointer != null) { + IrisRenderSystem.bindBuffer(GL46C.GL_DISPATCH_INDIRECT_BUFFER, indirectPointer.buffer()); + IrisRenderSystem.dispatchComputeIndirect(indirectPointer.offset()); + } else { + IrisRenderSystem.dispatchCompute(getWorkGroups(width, height)); + } } public static void unbind() { diff --git a/src/main/java/net/coderbot/iris/gl/program/Program.java b/src/main/java/net/coderbot/iris/gl/program/Program.java index 051bb1d474..b84a6060c2 100644 --- a/src/main/java/net/coderbot/iris/gl/program/Program.java +++ b/src/main/java/net/coderbot/iris/gl/program/Program.java @@ -3,6 +3,8 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.shaders.ProgramManager; import net.coderbot.iris.gl.GlResource; +import net.coderbot.iris.gl.IrisRenderSystem; +import org.lwjgl.opengl.GL43C; public final class Program extends GlResource { private final ProgramUniforms uniforms; @@ -18,8 +20,10 @@ public final class Program extends GlResource { } public void use() { + IrisRenderSystem.memoryBarrier(GL43C.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL43C.GL_TEXTURE_FETCH_BARRIER_BIT | GL43C.GL_SHADER_STORAGE_BARRIER_BIT); ProgramManager.glUseProgram(getGlId()); + uniforms.update(); samplers.update(); images.update(); diff --git a/src/main/java/net/coderbot/iris/gl/program/ProgramBuilder.java b/src/main/java/net/coderbot/iris/gl/program/ProgramBuilder.java index 33135e62a8..20b39ef916 100644 --- a/src/main/java/net/coderbot/iris/gl/program/ProgramBuilder.java +++ b/src/main/java/net/coderbot/iris/gl/program/ProgramBuilder.java @@ -4,6 +4,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import net.coderbot.iris.gl.IrisRenderSystem; import net.coderbot.iris.gl.image.ImageHolder; +import net.coderbot.iris.gl.sampler.GlSampler; import net.coderbot.iris.gl.sampler.SamplerHolder; import net.coderbot.iris.gl.shader.GlShader; import net.coderbot.iris.gl.shader.ProgramCreator; @@ -116,14 +117,19 @@ public boolean addDefaultSampler(IntSupplier sampler, String... names) { return samplers.addDefaultSampler(sampler, names); } + @Override + public boolean addDefaultSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, GlSampler sampler, String... names) { + return samplers.addDefaultSampler(type, texture, notifier, sampler, names); + } + @Override public boolean addDynamicSampler(IntSupplier sampler, String... names) { return samplers.addDynamicSampler(sampler, names); } @Override - public boolean addDynamicSampler(TextureType type, IntSupplier sampler, String... names) { - return samplers.addDynamicSampler(type, sampler, names); + public boolean addDynamicSampler(TextureType type, IntSupplier texture, GlSampler sampler, String... names) { + return samplers.addDynamicSampler(type, texture, sampler, names); } public boolean addDynamicSampler(IntSupplier sampler, ValueUpdateNotifier notifier, String... names) { @@ -131,8 +137,8 @@ public boolean addDynamicSampler(IntSupplier sampler, ValueUpdateNotifier notifi } @Override - public boolean addDynamicSampler(TextureType type, IntSupplier sampler, ValueUpdateNotifier notifier, String... names) { - return samplers.addDynamicSampler(type, sampler, notifier, names); + public boolean addDynamicSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, GlSampler sampler, String... names) { + return samplers.addDynamicSampler(type, texture, notifier, sampler, names); } @Override diff --git a/src/main/java/net/coderbot/iris/gl/program/ProgramSamplers.java b/src/main/java/net/coderbot/iris/gl/program/ProgramSamplers.java index 74e759e463..4187cfadc1 100644 --- a/src/main/java/net/coderbot/iris/gl/program/ProgramSamplers.java +++ b/src/main/java/net/coderbot/iris/gl/program/ProgramSamplers.java @@ -8,6 +8,8 @@ import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.gl.IrisRenderSystem; +import net.coderbot.iris.gl.sampler.GlSampler; import net.coderbot.iris.gl.sampler.SamplerBinding; import net.coderbot.iris.gl.sampler.SamplerHolder; import net.coderbot.iris.gl.sampler.SamplerLimits; @@ -73,6 +75,8 @@ public static void clearActiveSamplers() { if (active != null) { active.removeListeners(); } + + IrisRenderSystem.unbindAllSamplers(); } public static Builder builder(int program, Set reservedTextureUnits) { @@ -150,13 +154,13 @@ public boolean hasSampler(String name) { } @Override - public boolean addDefaultSampler(IntSupplier sampler, String... names) { + public boolean addDefaultSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, GlSampler sampler, String... names) { if (nextUnit != 0) { // TODO: Relax this restriction! throw new IllegalStateException("Texture unit 0 is already used."); } - return addDynamicSampler(TextureType.TEXTURE_2D, sampler, true, null, names); + return addDynamicSampler(TextureType.TEXTURE_2D, texture, sampler, true, notifier, names); } /** @@ -164,20 +168,20 @@ public boolean addDefaultSampler(IntSupplier sampler, String... names) { * @return false if this sampler is not active, true if at least one of the names referred to an active sampler */ @Override - public boolean addDynamicSampler(TextureType type, IntSupplier sampler, String... names) { - return addDynamicSampler(type, sampler, false, null, names); + public boolean addDynamicSampler(TextureType type, IntSupplier texture, GlSampler sampler, String... names) { + return addDynamicSampler(type, texture, sampler, false, null, names); } @Override - public boolean addDynamicSampler(TextureType type, IntSupplier sampler, ValueUpdateNotifier notifier, String... names) { - return addDynamicSampler(type, sampler, false, notifier, names); + public boolean addDynamicSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, GlSampler sampler, String... names) { + return addDynamicSampler(type, texture, sampler, false, notifier, names); } /** * Adds a sampler * @return false if this sampler is not active, true if at least one of the names referred to an active sampler */ - private boolean addDynamicSampler(TextureType type, IntSupplier sampler, boolean used, ValueUpdateNotifier notifier, String... names) { + private boolean addDynamicSampler(TextureType type, IntSupplier texture, GlSampler sampler, boolean used, ValueUpdateNotifier notifier, String... names) { if (notifier != null) { notifiersToReset.add(notifier); } @@ -208,7 +212,7 @@ private boolean addDynamicSampler(TextureType type, IntSupplier sampler, boolean return false; } - samplers.add(new SamplerBinding(type, nextUnit, sampler, notifier)); + samplers.add(new SamplerBinding(type, nextUnit, texture, sampler, notifier)); remainingUnits--; nextUnit++; @@ -286,6 +290,13 @@ public boolean addDefaultSampler(IntSupplier sampler, String... names) { return samplerHolder.addDefaultSampler(sampler, names); } + @Override + public boolean addDefaultSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, GlSampler sampler, String... names) { + texture = getOverride(texture, names); + + return samplerHolder.addDefaultSampler(type, texture, notifier, sampler, names); + } + @Override public boolean addDynamicSampler(IntSupplier sampler, String... names) { sampler = getOverride(sampler, names); @@ -294,10 +305,10 @@ public boolean addDynamicSampler(IntSupplier sampler, String... names) { } @Override - public boolean addDynamicSampler(TextureType type, IntSupplier sampler, String... names) { - sampler = getOverride(sampler, names); + public boolean addDynamicSampler(TextureType type, IntSupplier texture, GlSampler sampler, String... names) { + texture = getOverride(texture, names); - return samplerHolder.addDynamicSampler(type, sampler, names); + return samplerHolder.addDynamicSampler(type, texture, sampler, names); } @Override @@ -308,10 +319,8 @@ public boolean addDynamicSampler(IntSupplier sampler, ValueUpdateNotifier notifi } @Override - public boolean addDynamicSampler(TextureType type, IntSupplier sampler, ValueUpdateNotifier notifier, String... names) { - sampler = getOverride(sampler, names); - - return samplerHolder.addDynamicSampler(type, sampler, notifier, names); + public boolean addDynamicSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, GlSampler sampler, String... names) { + return false; } } } diff --git a/src/main/java/net/coderbot/iris/gl/program/ProgramUniforms.java b/src/main/java/net/coderbot/iris/gl/program/ProgramUniforms.java index e4860f952b..72ffd17fa4 100644 --- a/src/main/java/net/coderbot/iris/gl/program/ProgramUniforms.java +++ b/src/main/java/net/coderbot/iris/gl/program/ProgramUniforms.java @@ -4,12 +4,8 @@ import com.mojang.blaze3d.platform.GlStateManager; import net.coderbot.iris.Iris; import net.coderbot.iris.gl.IrisRenderSystem; -import net.coderbot.iris.gl.uniform.DynamicLocationalUniformHolder; -import net.coderbot.iris.gl.uniform.Uniform; -import net.coderbot.iris.gl.uniform.UniformHolder; -import net.coderbot.iris.gl.uniform.UniformType; -import net.coderbot.iris.gl.uniform.UniformUpdateFrequency; import net.coderbot.iris.gl.state.ValueUpdateNotifier; +import net.coderbot.iris.gl.uniform.*; import net.coderbot.iris.uniforms.SystemTimeUniforms; import net.minecraft.client.Minecraft; import org.lwjgl.BufferUtils; @@ -18,12 +14,7 @@ import org.lwjgl.opengl.GL30C; import java.nio.IntBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.OptionalInt; +import java.util.*; public class ProgramUniforms { private static ProgramUniforms active; @@ -52,7 +43,11 @@ private void updateStage(ImmutableList uniforms) { } private static long getCurrentTick() { - return Objects.requireNonNull(Minecraft.getInstance().level).getGameTime(); + if (Minecraft.getInstance().level == null) { + return 0L; + } else { + return Minecraft.getInstance().level.getGameTime(); + } } public void update() { @@ -198,53 +193,6 @@ public ProgramUniforms buildUniforms() { UniformType provided = uniformNames.get(name); UniformType expected = getExpectedType(type); - if (provided == null && !name.startsWith("gl_")) { - String typeName = getTypeName(type); - - if (isSampler(type) || isImage(type)) { - // don't print a warning, samplers and images are managed elsewhere. - // TODO: Detect unsupported samplers/images? - continue; - } - - UniformType externalProvided = externalUniformNames.get(name); - - if (externalProvided != null) { - if (externalProvided != expected) { - String expectedName; - - if (expected != null) { - expectedName = expected.toString(); - } else { - expectedName = "(unsupported type: " + getTypeName(type) + ")"; - } - - Iris.logger.error("[" + this.name + "] Wrong uniform type for externally-managed uniform " + name + ": " + externalProvided + " is provided but the program expects " + expectedName + "."); - } - - continue; - } - - if (name.startsWith("Chunks[")) { - // explicitly filter out Chunks[] UBO stuff - continue; - } - - if (size == 1) { - Iris.logger.warn("[" + this.name + "] Unsupported uniform: " + typeName + " " + name); - } else { - Iris.logger.warn("[" + this.name + "] Unsupported uniform: " + name + " of size " + size + " and type " + typeName); - } - - continue; - } - - // TODO: This is an absolutely horrific hack, but is needed until custom uniforms work. - if ("framemod8".equals(name) && expected == UniformType.FLOAT && provided == UniformType.INT) { - SystemTimeUniforms.addFloatFrameMod8Uniform(this); - provided = UniformType.FLOAT; - } - if (provided != null && provided != expected) { String expectedName; @@ -264,7 +212,7 @@ public ProgramUniforms buildUniforms() { } return new ProgramUniforms(ImmutableList.copyOf(once.values()), ImmutableList.copyOf(perTick.values()), ImmutableList.copyOf(perFrame.values()), - ImmutableList.copyOf(dynamic.values()), ImmutableList.copyOf(notifiersToReset)); + ImmutableList.copyOf(dynamic.values()), ImmutableList.copyOf(notifiersToReset)); } @Override @@ -323,10 +271,24 @@ private static String getTypeName(int type) { typeName = "sampler2DShadow"; } else if (type == GL20C.GL_SAMPLER_1D_SHADOW) { typeName = "sampler1DShadow"; + } else if (type == ARBShaderImageLoadStore.GL_IMAGE_1D) { + typeName = "image1D"; } else if (type == ARBShaderImageLoadStore.GL_IMAGE_2D) { typeName = "image2D"; } else if (type == ARBShaderImageLoadStore.GL_IMAGE_3D) { typeName = "image3D"; + } else if (type == ARBShaderImageLoadStore.GL_INT_IMAGE_1D) { + typeName = "iimage1D"; + } else if (type == ARBShaderImageLoadStore.GL_INT_IMAGE_2D) { + typeName = "iimage2D"; + } else if (type == ARBShaderImageLoadStore.GL_INT_IMAGE_3D) { + typeName = "iimage3D"; + } else if (type == ARBShaderImageLoadStore.GL_UNSIGNED_INT_IMAGE_1D) { + typeName = "uimage1D"; + } else if (type == ARBShaderImageLoadStore.GL_UNSIGNED_INT_IMAGE_2D) { + typeName = "uimage2D"; + } else if (type == ARBShaderImageLoadStore.GL_UNSIGNED_INT_IMAGE_3D) { + typeName = "uimage3D"; } else { typeName = "(unknown:" + type + ")"; } @@ -352,7 +314,7 @@ private static UniformType getExpectedType(int type) { } else if (type == GL20C.GL_FLOAT_VEC3) { return UniformType.VEC3; } else if (type == GL20C.GL_INT_VEC3) { - return null; + return UniformType.VEC3I; } else if (type == GL20C.GL_FLOAT_MAT2) { return null; } else if (type == GL20C.GL_FLOAT_VEC2) { @@ -380,20 +342,25 @@ private static UniformType getExpectedType(int type) { private static boolean isSampler(int type) { return type == GL20C.GL_SAMPLER_1D - || type == GL20C.GL_SAMPLER_2D - || type == GL30C.GL_UNSIGNED_INT_SAMPLER_2D - || type == GL30C.GL_UNSIGNED_INT_SAMPLER_3D - || type == GL20C.GL_SAMPLER_3D - || type == GL20C.GL_SAMPLER_1D_SHADOW - || type == GL20C.GL_SAMPLER_2D_SHADOW; + || type == GL20C.GL_SAMPLER_2D + || type == GL30C.GL_UNSIGNED_INT_SAMPLER_2D + || type == GL30C.GL_UNSIGNED_INT_SAMPLER_3D + || type == GL20C.GL_SAMPLER_3D + || type == GL20C.GL_SAMPLER_1D_SHADOW + || type == GL20C.GL_SAMPLER_2D_SHADOW; } private static boolean isImage(int type) { return type == ARBShaderImageLoadStore.GL_IMAGE_1D - || type == ARBShaderImageLoadStore.GL_IMAGE_2D - || type == ARBShaderImageLoadStore.GL_UNSIGNED_INT_IMAGE_2D - || type == ARBShaderImageLoadStore.GL_IMAGE_3D - || type == ARBShaderImageLoadStore.GL_IMAGE_1D_ARRAY - || type == ARBShaderImageLoadStore.GL_IMAGE_2D_ARRAY; + || type == ARBShaderImageLoadStore.GL_IMAGE_2D + || type == ARBShaderImageLoadStore.GL_UNSIGNED_INT_IMAGE_1D + || type == ARBShaderImageLoadStore.GL_UNSIGNED_INT_IMAGE_2D + || type == ARBShaderImageLoadStore.GL_UNSIGNED_INT_IMAGE_3D + || type == ARBShaderImageLoadStore.GL_INT_IMAGE_1D + || type == ARBShaderImageLoadStore.GL_INT_IMAGE_2D + || type == ARBShaderImageLoadStore.GL_INT_IMAGE_3D + || type == ARBShaderImageLoadStore.GL_IMAGE_3D + || type == ARBShaderImageLoadStore.GL_IMAGE_1D_ARRAY + || type == ARBShaderImageLoadStore.GL_IMAGE_2D_ARRAY; } } diff --git a/src/main/java/net/coderbot/iris/gl/sampler/GlSampler.java b/src/main/java/net/coderbot/iris/gl/sampler/GlSampler.java new file mode 100644 index 0000000000..8e6239393c --- /dev/null +++ b/src/main/java/net/coderbot/iris/gl/sampler/GlSampler.java @@ -0,0 +1,36 @@ +package net.coderbot.iris.gl.sampler; + +import net.coderbot.iris.gl.GlResource; +import net.coderbot.iris.gl.IrisRenderSystem; +import org.lwjgl.opengl.GL11C; +import org.lwjgl.opengl.GL13C; +import org.lwjgl.opengl.GL20C; +import org.lwjgl.opengl.GL30C; + +public class GlSampler extends GlResource { + public GlSampler(boolean linear, boolean mipmapped, boolean shadow, boolean hardwareShadow) { + super(IrisRenderSystem.genSampler()); + + IrisRenderSystem.samplerParameteri(getId(), GL11C.GL_TEXTURE_MIN_FILTER, linear ? GL11C.GL_LINEAR : GL11C.GL_NEAREST); + IrisRenderSystem.samplerParameteri(getId(), GL11C.GL_TEXTURE_MAG_FILTER, linear ? GL11C.GL_LINEAR : GL11C.GL_NEAREST); + IrisRenderSystem.samplerParameteri(getId(), GL11C.GL_TEXTURE_WRAP_S, GL13C.GL_CLAMP_TO_EDGE); + IrisRenderSystem.samplerParameteri(getId(), GL11C.GL_TEXTURE_WRAP_T, GL13C.GL_CLAMP_TO_EDGE); + + if (mipmapped) { + IrisRenderSystem.samplerParameteri(getId(), GL11C.GL_TEXTURE_MIN_FILTER, linear ? GL11C.GL_LINEAR_MIPMAP_LINEAR : GL11C.GL_NEAREST_MIPMAP_NEAREST); + } + + if (hardwareShadow) { + IrisRenderSystem.samplerParameteri(getId(), GL20C.GL_TEXTURE_COMPARE_MODE, GL30C.GL_COMPARE_REF_TO_TEXTURE); + } + } + + @Override + protected void destroyInternal() { + IrisRenderSystem.destroySampler(getGlId()); + } + + public int getId() { + return getGlId(); + } +} diff --git a/src/main/java/net/coderbot/iris/gl/sampler/SamplerBinding.java b/src/main/java/net/coderbot/iris/gl/sampler/SamplerBinding.java index be38ae6e6e..7c3b669676 100644 --- a/src/main/java/net/coderbot/iris/gl/sampler/SamplerBinding.java +++ b/src/main/java/net/coderbot/iris/gl/sampler/SamplerBinding.java @@ -14,11 +14,13 @@ public class SamplerBinding { private final IntSupplier texture; private final ValueUpdateNotifier notifier; private final TextureType textureType; + private final int sampler; - public SamplerBinding(TextureType type, int textureUnit, IntSupplier texture, ValueUpdateNotifier notifier) { + public SamplerBinding(TextureType type, int textureUnit, IntSupplier texture, GlSampler sampler, ValueUpdateNotifier notifier) { this.textureType = type; this.textureUnit = textureUnit; this.texture = texture; + this.sampler = sampler == null ? 0 : sampler.getId(); this.notifier = notifier; } @@ -31,6 +33,7 @@ public void update() { } private void updateSampler() { + IrisRenderSystem.bindSamplerToUnit(textureUnit, sampler); IrisRenderSystem.bindTextureToUnit(textureType.getGlType(), textureUnit, texture.getAsInt()); } } diff --git a/src/main/java/net/coderbot/iris/gl/sampler/SamplerHolder.java b/src/main/java/net/coderbot/iris/gl/sampler/SamplerHolder.java index fe6a18baab..1ef4a6b4f0 100644 --- a/src/main/java/net/coderbot/iris/gl/sampler/SamplerHolder.java +++ b/src/main/java/net/coderbot/iris/gl/sampler/SamplerHolder.java @@ -16,17 +16,22 @@ public interface SamplerHolder { * Throws an exception if texture unit 0 is already allocated or reserved in some way. Do not call this * function after calls to addDynamicSampler, it must be called before any calls to addDynamicSampler. */ - boolean addDefaultSampler(IntSupplier sampler, String... names); + default boolean addDefaultSampler(IntSupplier sampler, String... names) { + return addDefaultSampler(TextureType.TEXTURE_2D, sampler, null, null, names); + } + + boolean addDefaultSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, GlSampler sampler, String... names); + - default boolean addDynamicSampler(IntSupplier sampler, String... names) { - return addDynamicSampler(TextureType.TEXTURE_2D, sampler, names); + default boolean addDynamicSampler(IntSupplier texture, String... names) { + return addDynamicSampler(TextureType.TEXTURE_2D, texture, null, names); } - boolean addDynamicSampler(TextureType type, IntSupplier sampler, String... names); + boolean addDynamicSampler(TextureType type, IntSupplier texture, GlSampler sampler, String... names); - default boolean addDynamicSampler(IntSupplier sampler, ValueUpdateNotifier notifier, String... names) { - return addDynamicSampler(TextureType.TEXTURE_2D, sampler, notifier, names); + default boolean addDynamicSampler(IntSupplier texture, ValueUpdateNotifier notifier, String... names) { + return addDynamicSampler(TextureType.TEXTURE_2D, texture, notifier, null, names); } - boolean addDynamicSampler(TextureType type, IntSupplier sampler, ValueUpdateNotifier notifier, String... names); + boolean addDynamicSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, GlSampler sampler, String... names); } diff --git a/src/main/java/net/coderbot/iris/gl/sampler/SamplerLimits.java b/src/main/java/net/coderbot/iris/gl/sampler/SamplerLimits.java index 820f37d8c4..6ffb4be43a 100644 --- a/src/main/java/net/coderbot/iris/gl/sampler/SamplerLimits.java +++ b/src/main/java/net/coderbot/iris/gl/sampler/SamplerLimits.java @@ -1,16 +1,20 @@ package net.coderbot.iris.gl.sampler; import com.mojang.blaze3d.platform.GlStateManager; +import net.coderbot.iris.gl.IrisRenderSystem; import org.lwjgl.opengl.GL20C; +import org.lwjgl.opengl.GL45C; public class SamplerLimits { private final int maxTextureUnits; private final int maxDrawBuffers; + private final int maxShaderStorageUnits; private static SamplerLimits instance; private SamplerLimits() { this.maxTextureUnits = GlStateManager._getInteger(GL20C.GL_MAX_TEXTURE_IMAGE_UNITS); this.maxDrawBuffers = GlStateManager._getInteger(GL20C.GL_MAX_DRAW_BUFFERS); + this.maxShaderStorageUnits = IrisRenderSystem.supportsSSBO() ? GlStateManager._getInteger(GL45C.GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS) : 0; } public int getMaxTextureUnits() { @@ -21,6 +25,10 @@ public int getMaxDrawBuffers() { return maxDrawBuffers; } + public int getMaxShaderStorageUnits() { + return maxShaderStorageUnits; + } + public static SamplerLimits get() { if (instance == null) { instance = new SamplerLimits(); diff --git a/src/main/java/net/coderbot/iris/gl/shader/GlShader.java b/src/main/java/net/coderbot/iris/gl/shader/GlShader.java index 4830f53b81..72a4f5e0ab 100644 --- a/src/main/java/net/coderbot/iris/gl/shader/GlShader.java +++ b/src/main/java/net/coderbot/iris/gl/shader/GlShader.java @@ -43,7 +43,7 @@ private static int createShader(ShaderType type, String name, String src) { int result = GlStateManager.glGetShaderi(handle, GL20C.GL_COMPILE_STATUS); if (result != GL20C.GL_TRUE) { - throw new RuntimeException("Shader compilation failed, see log for details"); + throw new RuntimeException("Shader compilation failed for " + name + ", see log for details"); } return handle; diff --git a/src/main/java/net/coderbot/iris/gl/shader/ProgramCreator.java b/src/main/java/net/coderbot/iris/gl/shader/ProgramCreator.java index a47e799246..3534c6976b 100644 --- a/src/main/java/net/coderbot/iris/gl/shader/ProgramCreator.java +++ b/src/main/java/net/coderbot/iris/gl/shader/ProgramCreator.java @@ -18,6 +18,7 @@ public static int create(String name, GlShader... shaders) { // TODO: This is *really* hardcoded, we need to refactor this to support external calls // to glBindAttribLocation + GlStateManager._glBindAttribLocation(program, 11, "iris_Entity"); GlStateManager._glBindAttribLocation(program, 11, "mc_Entity"); GlStateManager._glBindAttribLocation(program, 12, "mc_midTexCoord"); GlStateManager._glBindAttribLocation(program, 13, "at_tangent"); diff --git a/src/main/java/net/coderbot/iris/gl/shader/ShaderType.java b/src/main/java/net/coderbot/iris/gl/shader/ShaderType.java index 8368c41b22..0bcc1c52f7 100644 --- a/src/main/java/net/coderbot/iris/gl/shader/ShaderType.java +++ b/src/main/java/net/coderbot/iris/gl/shader/ShaderType.java @@ -13,7 +13,9 @@ public enum ShaderType { VERTEX(GL20.GL_VERTEX_SHADER), GEOMETRY(GL32C.GL_GEOMETRY_SHADER), FRAGMENT(GL20.GL_FRAGMENT_SHADER), - COMPUTE(GL43C.GL_COMPUTE_SHADER); + COMPUTE(GL43C.GL_COMPUTE_SHADER), + TESSELATION_CONTROL(GL43C.GL_TESS_CONTROL_SHADER), + TESSELATION_EVAL(GL43C.GL_TESS_EVALUATION_SHADER); public final int id; diff --git a/src/main/java/net/coderbot/iris/gl/shader/StandardMacros.java b/src/main/java/net/coderbot/iris/gl/shader/StandardMacros.java index 8f2b4e7159..ec984571b6 100644 --- a/src/main/java/net/coderbot/iris/gl/shader/StandardMacros.java +++ b/src/main/java/net/coderbot/iris/gl/shader/StandardMacros.java @@ -14,14 +14,7 @@ import org.lwjgl.opengl.GL20C; import org.lwjgl.opengl.GL30C; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.Set; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -37,7 +30,7 @@ private static void define(List defines, String key, String value) { defines.add(new StringPair(key, value)); } - public static Iterable createStandardEnvironmentDefines() { + public static ImmutableList createStandardEnvironmentDefines() { ArrayList standardDefines = new ArrayList<>(); define(standardDefines, "MC_VERSION", getMcVersion()); @@ -46,6 +39,7 @@ public static Iterable createStandardEnvironmentDefines() { define(standardDefines, getOsString()); define(standardDefines, getVendor()); define(standardDefines, getRenderer()); + define(standardDefines, "IS_IRIS"); for (String glExtension : getGlExtensions()) { define(standardDefines, glExtension); @@ -81,9 +75,9 @@ public static Iterable createStandardEnvironmentDefines() { */ public static String getMcVersion() { String version = SharedConstants.getCurrentVersion().getReleaseTarget(); - // release target so snapshots are set to the higher version - // - // For example if we were running iris on 21w07a, getReleaseTarget() would return 1.17 + // release target so snapshots are set to the higher version + // + // For example if we were running iris on 21w07a, getReleaseTarget() would return 1.17 if (version == null) { throw new IllegalStateException("Could not get the current minecraft version!"); diff --git a/src/main/java/net/coderbot/iris/gl/state/StateUpdateNotifiers.java b/src/main/java/net/coderbot/iris/gl/state/StateUpdateNotifiers.java index 43f8df8d75..e9230d7ca4 100644 --- a/src/main/java/net/coderbot/iris/gl/state/StateUpdateNotifiers.java +++ b/src/main/java/net/coderbot/iris/gl/state/StateUpdateNotifiers.java @@ -1,5 +1,7 @@ package net.coderbot.iris.gl.state; +import java.util.function.IntSupplier; + /** * Holds some standard update notifiers for various elements of GL state. Currently, this class has a few listeners for * fog-related values. @@ -12,4 +14,5 @@ public class StateUpdateNotifiers { public static ValueUpdateNotifier normalTextureChangeNotifier; public static ValueUpdateNotifier specularTextureChangeNotifier; public static ValueUpdateNotifier phaseChangeNotifier; + public static ValueUpdateNotifier fallbackEntityNotifier; } diff --git a/src/main/java/net/coderbot/iris/gl/texture/InternalTextureFormat.java b/src/main/java/net/coderbot/iris/gl/texture/InternalTextureFormat.java index 4dc00b76c0..f22d59bf6b 100644 --- a/src/main/java/net/coderbot/iris/gl/texture/InternalTextureFormat.java +++ b/src/main/java/net/coderbot/iris/gl/texture/InternalTextureFormat.java @@ -5,6 +5,7 @@ import org.lwjgl.opengl.GL30C; import org.lwjgl.opengl.GL31C; +import java.util.Locale; import java.util.Optional; public enum InternalTextureFormat { @@ -90,7 +91,7 @@ public enum InternalTextureFormat { public static Optional fromString(String name) { try { - return Optional.of(InternalTextureFormat.valueOf(name)); + return Optional.of(InternalTextureFormat.valueOf(name.toUpperCase(Locale.US))); } catch (IllegalArgumentException e) { return Optional.empty(); } diff --git a/src/main/java/net/coderbot/iris/gl/texture/PixelFormat.java b/src/main/java/net/coderbot/iris/gl/texture/PixelFormat.java index 3b086aa5c7..6966917304 100644 --- a/src/main/java/net/coderbot/iris/gl/texture/PixelFormat.java +++ b/src/main/java/net/coderbot/iris/gl/texture/PixelFormat.java @@ -5,6 +5,7 @@ import org.lwjgl.opengl.GL12C; import org.lwjgl.opengl.GL30C; +import java.util.Locale; import java.util.Optional; public enum PixelFormat { @@ -33,7 +34,7 @@ public enum PixelFormat { public static Optional fromString(String name) { try { - return Optional.of(PixelFormat.valueOf(name)); + return Optional.of(PixelFormat.valueOf(name.toUpperCase(Locale.US))); } catch (IllegalArgumentException e) { return Optional.empty(); } diff --git a/src/main/java/net/coderbot/iris/gl/texture/PixelType.java b/src/main/java/net/coderbot/iris/gl/texture/PixelType.java index 1a468cffc6..f0c2e09254 100644 --- a/src/main/java/net/coderbot/iris/gl/texture/PixelType.java +++ b/src/main/java/net/coderbot/iris/gl/texture/PixelType.java @@ -5,6 +5,7 @@ import org.lwjgl.opengl.GL12C; import org.lwjgl.opengl.GL30C; +import java.util.Locale; import java.util.Optional; public enum PixelType { @@ -23,7 +24,7 @@ public enum PixelType { UNSIGNED_SHORT_4_4_4_4_REV(GL12C.GL_UNSIGNED_SHORT_4_4_4_4_REV, GlVersion.GL_12), UNSIGNED_SHORT_5_5_5_1(GL12C.GL_UNSIGNED_SHORT_5_5_5_1, GlVersion.GL_12), UNSIGNED_SHORT_1_5_5_5_REV(GL12C.GL_UNSIGNED_SHORT_1_5_5_5_REV, GlVersion.GL_12), - UNSIGNED_INT(GL11C.GL_UNSIGNED_BYTE, GlVersion.GL_11), + UNSIGNED_INT(GL11C.GL_UNSIGNED_INT, GlVersion.GL_11), UNSIGNED_INT_8_8_8_8(GL12C.GL_UNSIGNED_INT_8_8_8_8, GlVersion.GL_12), UNSIGNED_INT_8_8_8_8_REV(GL12C.GL_UNSIGNED_INT_8_8_8_8_REV, GlVersion.GL_12), UNSIGNED_INT_10_10_10_2(GL12C.GL_UNSIGNED_INT_10_10_10_2, GlVersion.GL_12), @@ -39,7 +40,7 @@ public enum PixelType { public static Optional fromString(String name) { try { - return Optional.of(PixelType.valueOf(name)); + return Optional.of(PixelType.valueOf(name.toUpperCase(Locale.US))); } catch (IllegalArgumentException e) { return Optional.empty(); } diff --git a/src/main/java/net/coderbot/iris/gl/texture/TextureType.java b/src/main/java/net/coderbot/iris/gl/texture/TextureType.java index 6d61bbdfe0..35d26c978e 100644 --- a/src/main/java/net/coderbot/iris/gl/texture/TextureType.java +++ b/src/main/java/net/coderbot/iris/gl/texture/TextureType.java @@ -4,6 +4,7 @@ import org.lwjgl.opengl.GL30C; import java.nio.ByteBuffer; +import java.util.Optional; public enum TextureType { TEXTURE_1D(GL30C.GL_TEXTURE_1D), @@ -34,4 +35,12 @@ public void apply(int texture, int sizeX, int sizeY, int sizeZ, int internalForm break; } } + + public static Optional fromString(String name) { + try { + return Optional.of(TextureType.valueOf(name)); + } catch (IllegalArgumentException e) { + return Optional.empty(); + } + } } diff --git a/src/main/java/net/coderbot/iris/gl/uniform/LocationalUniformHolder.java b/src/main/java/net/coderbot/iris/gl/uniform/LocationalUniformHolder.java index fe59c417fe..b87a4cb0ee 100644 --- a/src/main/java/net/coderbot/iris/gl/uniform/LocationalUniformHolder.java +++ b/src/main/java/net/coderbot/iris/gl/uniform/LocationalUniformHolder.java @@ -5,6 +5,7 @@ import net.coderbot.iris.vendored.joml.Vector2i; import net.coderbot.iris.vendored.joml.Vector3d; import net.coderbot.iris.vendored.joml.Vector3f; +import net.coderbot.iris.vendored.joml.Vector3i; import net.coderbot.iris.vendored.joml.Vector4f; import java.util.OptionalInt; @@ -74,6 +75,13 @@ default LocationalUniformHolder uniform3f(UniformUpdateFrequency updateFrequency return this; } + @Override + default LocationalUniformHolder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier value) { + location(name, UniformType.VEC3I).ifPresent(id -> addUniform(updateFrequency, new Vector3IntegerUniform(id, value))); + + return this; + } + @Override default LocationalUniformHolder uniformVanilla3f(UniformUpdateFrequency updateFrequency, String name, Supplier value) { location(name, UniformType.VEC3).ifPresent(id -> addUniform(updateFrequency, new VanillaVector3Uniform(id, value))); diff --git a/src/main/java/net/coderbot/iris/gl/uniform/UniformHolder.java b/src/main/java/net/coderbot/iris/gl/uniform/UniformHolder.java index dde9c93e3a..c600a24c69 100644 --- a/src/main/java/net/coderbot/iris/gl/uniform/UniformHolder.java +++ b/src/main/java/net/coderbot/iris/gl/uniform/UniformHolder.java @@ -5,6 +5,7 @@ import net.coderbot.iris.vendored.joml.Vector2i; import net.coderbot.iris.vendored.joml.Vector3d; import net.coderbot.iris.vendored.joml.Vector3f; +import net.coderbot.iris.vendored.joml.Vector3i; import net.coderbot.iris.vendored.joml.Vector4f; import java.util.function.BooleanSupplier; @@ -28,6 +29,7 @@ public interface UniformHolder { UniformHolder uniform2i(UniformUpdateFrequency updateFrequency, String name, Supplier value); UniformHolder uniform3f(UniformUpdateFrequency updateFrequency, String name, Supplier value); + UniformHolder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier value); UniformHolder uniformVanilla3f(UniformUpdateFrequency updateFrequency, String name, Supplier value); diff --git a/src/main/java/net/coderbot/iris/gl/uniform/UniformType.java b/src/main/java/net/coderbot/iris/gl/uniform/UniformType.java index 6f6d9430ed..47f9c73316 100644 --- a/src/main/java/net/coderbot/iris/gl/uniform/UniformType.java +++ b/src/main/java/net/coderbot/iris/gl/uniform/UniformType.java @@ -8,6 +8,7 @@ public enum UniformType { VEC2, VEC2I, VEC3, + VEC3I, VEC4, VEC4I } diff --git a/src/main/java/net/coderbot/iris/gl/uniform/Vector3IntegerUniform.java b/src/main/java/net/coderbot/iris/gl/uniform/Vector3IntegerUniform.java new file mode 100644 index 0000000000..dd564d8d32 --- /dev/null +++ b/src/main/java/net/coderbot/iris/gl/uniform/Vector3IntegerUniform.java @@ -0,0 +1,46 @@ +package net.coderbot.iris.gl.uniform; + +import net.coderbot.iris.gl.IrisRenderSystem; +import net.coderbot.iris.gl.state.ValueUpdateNotifier; +import net.coderbot.iris.vendored.joml.Vector3d; +import net.coderbot.iris.vendored.joml.Vector3f; +import net.coderbot.iris.vendored.joml.Vector3i; +import net.coderbot.iris.vendored.joml.Vector4f; + +import java.util.function.Supplier; + +public class Vector3IntegerUniform extends Uniform { + private final Vector3i cachedValue; + private final Supplier value; + + Vector3IntegerUniform(int location, Supplier value) { + super(location); + + this.cachedValue = new Vector3i(); + this.value = value; + } + + Vector3IntegerUniform(int location, Supplier value, ValueUpdateNotifier notifier) { + super(location, notifier); + + this.cachedValue = new Vector3i(); + this.value = value; + } + @Override + public void update() { + updateValue(); + + if (notifier != null) { + notifier.setListener(this::updateValue); + } + } + + private void updateValue() { + Vector3i newValue = value.get(); + + if (!newValue.equals(cachedValue)) { + cachedValue.set(newValue.x(), newValue.y(), newValue.z()); + IrisRenderSystem.uniform3i(location, cachedValue.x(), cachedValue.y(), cachedValue.z()); + } + } +} diff --git a/src/main/java/net/coderbot/iris/gui/element/widget/StringElementWidget.java b/src/main/java/net/coderbot/iris/gui/element/widget/StringElementWidget.java index 173de0ee0a..eb55b91072 100644 --- a/src/main/java/net/coderbot/iris/gui/element/widget/StringElementWidget.java +++ b/src/main/java/net/coderbot/iris/gui/element/widget/StringElementWidget.java @@ -7,7 +7,9 @@ import net.coderbot.iris.gui.screen.ShaderPackScreen; import net.coderbot.iris.shaderpack.option.StringOption; import net.coderbot.iris.shaderpack.option.menu.OptionMenuStringOptionElement; +import net.minecraft.locale.Language; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.TextColor; import net.minecraft.network.chat.TextComponent; @@ -19,6 +21,7 @@ public class StringElementWidget extends BaseOptionElementWidget values = this.option.getAllowedValues(); @@ -61,9 +67,9 @@ private void increment(int amount) { @Override protected Component createValueLabel() { - return GuiUtil.translateOrDefault( - new TextComponent(getValue()).withStyle(style -> style.withColor(TextColor.fromRgb(0x6688ff))), - "value." + this.option.getName() + "." + getValue()); + return prefix.copy().append(GuiUtil.translateOrDefault( + new TextComponent(getValue()).append(suffix), + "value." + this.option.getName() + "." + getValue())).withStyle(style -> style.withColor(TextColor.fromRgb(0x6688ff))); } @Override diff --git a/src/main/java/net/coderbot/iris/gui/option/IrisVideoSettings.java b/src/main/java/net/coderbot/iris/gui/option/IrisVideoSettings.java index 75d2e87780..67bf295f76 100644 --- a/src/main/java/net/coderbot/iris/gui/option/IrisVideoSettings.java +++ b/src/main/java/net/coderbot/iris/gui/option/IrisVideoSettings.java @@ -1,6 +1,7 @@ package net.coderbot.iris.gui.option; import net.coderbot.iris.Iris; +import net.coderbot.iris.colorspace.ColorSpace; import net.coderbot.iris.pipeline.WorldRenderingPipeline; import net.minecraft.client.Minecraft; import net.minecraft.client.ProgressOption; @@ -14,8 +15,9 @@ public class IrisVideoSettings { // TODO: Tell the user to check in the shader options once that's supported. private static final Component DISABLED_TOOLTIP = new TranslatableComponent("options.iris.shadowDistance.disabled"); private static final Component ENABLED_TOOLTIP = new TranslatableComponent("options.iris.shadowDistance.enabled"); + public static ColorSpace colorSpace = ColorSpace.SRGB; - public static int getOverriddenShadowDistance(int base) { + public static int getOverriddenShadowDistance(int base) { return Iris.getPipelineManager().getPipeline() .map(pipeline -> pipeline.getForcedShadowRenderDistanceChunksForDisplay().orElse(base)) .orElse(base); diff --git a/src/main/java/net/coderbot/iris/gui/screen/ShaderPackScreen.java b/src/main/java/net/coderbot/iris/gui/screen/ShaderPackScreen.java index 6128bc3dc3..4577ea6ee1 100644 --- a/src/main/java/net/coderbot/iris/gui/screen/ShaderPackScreen.java +++ b/src/main/java/net/coderbot/iris/gui/screen/ShaderPackScreen.java @@ -1,25 +1,7 @@ package net.coderbot.iris.gui.screen; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.FileAlreadyExistsException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Properties; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; - -import org.jetbrains.annotations.Nullable; -import org.lwjgl.glfw.GLFW; - +import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.vertex.PoseStack; - import net.coderbot.iris.Iris; import net.coderbot.iris.gui.GuiUtil; import net.coderbot.iris.gui.NavigationController; @@ -31,8 +13,11 @@ import net.irisshaders.iris.api.v0.IrisApi; import net.minecraft.ChatFormatting; import net.minecraft.Util; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.ImageButton; +import net.minecraft.client.gui.screens.ConfirmLinkScreen; +import net.minecraft.client.gui.screens.ConfirmScreen; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; @@ -40,6 +25,23 @@ import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.util.FormattedCharSequence; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.glfw.GLFW; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; public class ShaderPackScreen extends Screen implements HudHideable { /** @@ -73,6 +75,7 @@ public class ShaderPackScreen extends Screen implements HudHideable { private boolean dropChanges = false; private static String development = "Development Environment"; private MutableComponent developmentComponent; + private MutableComponent updateComponent; private boolean guiHidden = false; private float guiButtonHoverTimer = 0.0f; @@ -102,6 +105,16 @@ public void render(PoseStack poseStack, int mouseX, int mouseY, float delta) { this.fillGradient(poseStack, 0, 0, width, height, 0x4F232323, 0x4F232323); } + if (Screen.hasControlDown() && InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_D)) { + Minecraft.getInstance().setScreen(new ConfirmScreen((option) -> { + Iris.setDebug(option); + Minecraft.getInstance().setScreen(this); + }, new TextComponent("Shader debug mode toggle"), + new TextComponent("Debug mode helps investigate problems and shows shader errors. Would you like to enable it?"), + new TextComponent("Yes"), + new TextComponent("No"))); + } + if (!this.guiHidden) { if (optionMenuOpen && this.shaderOptionList != null) { this.shaderOptionList.render(poseStack, mouseX, mouseY, delta); @@ -154,6 +167,9 @@ public void render(PoseStack poseStack, int mouseX, int mouseY, float delta) { if (this.developmentComponent != null) { this.font.drawShadow(poseStack, developmentComponent, 2, this.height - 10, 0xFFFFFF); this.font.drawShadow(poseStack, irisTextComponent, 2, this.height - 20, 0xFFFFFF); + } else if (this.updateComponent != null) { + this.font.drawShadow(poseStack, updateComponent, 2, this.height - 10, 0xFFFFFF); + this.font.drawShadow(poseStack, irisTextComponent, 2, this.height - 20, 0xFFFFFF); } else { this.font.drawShadow(poseStack, irisTextComponent, 2, this.height - 10, 0xFFFFFF); } diff --git a/src/main/java/net/coderbot/iris/layer/BlockEntityRenderStateShard.java b/src/main/java/net/coderbot/iris/layer/BlockEntityRenderStateShard.java index c498762f50..713bc33a05 100644 --- a/src/main/java/net/coderbot/iris/layer/BlockEntityRenderStateShard.java +++ b/src/main/java/net/coderbot/iris/layer/BlockEntityRenderStateShard.java @@ -1,42 +1,11 @@ package net.coderbot.iris.layer; -import net.coderbot.iris.uniforms.CapturedRenderingState; import net.minecraft.client.renderer.RenderStateShard; public final class BlockEntityRenderStateShard extends RenderStateShard { - private static final BlockEntityRenderStateShard UNIDENTIFIED = new BlockEntityRenderStateShard(-1); + public static final BlockEntityRenderStateShard INSTANCE = new BlockEntityRenderStateShard(); - private final int entityId; - - private BlockEntityRenderStateShard(int entityId) { - super("iris:is_block_entity", () -> { - CapturedRenderingState.INSTANCE.setCurrentBlockEntity(entityId); - GbufferPrograms.beginBlockEntities(); - }, () -> { - CapturedRenderingState.INSTANCE.setCurrentBlockEntity(-1); - GbufferPrograms.endBlockEntities(); - }); - - this.entityId = entityId; - } - - public static BlockEntityRenderStateShard forId(int entityId) { - if (entityId == -1) { - return UNIDENTIFIED; - } else { - // TODO: Cache all created render phases to avoid allocations? - return new BlockEntityRenderStateShard(entityId); - } - } - - @Override - public boolean equals(Object object) { - if (object == null || object.getClass() != this.getClass()) { - return false; - } - - BlockEntityRenderStateShard other = (BlockEntityRenderStateShard) object; - - return this.entityId == other.entityId; + private BlockEntityRenderStateShard() { + super("iris:is_block_entity", GbufferPrograms::beginBlockEntities, GbufferPrograms::endBlockEntities); } } diff --git a/src/main/java/net/coderbot/iris/layer/EntityRenderStateShard.java b/src/main/java/net/coderbot/iris/layer/EntityRenderStateShard.java index e16305e672..6646a7d509 100644 --- a/src/main/java/net/coderbot/iris/layer/EntityRenderStateShard.java +++ b/src/main/java/net/coderbot/iris/layer/EntityRenderStateShard.java @@ -1,42 +1,11 @@ package net.coderbot.iris.layer; -import net.coderbot.iris.uniforms.CapturedRenderingState; import net.minecraft.client.renderer.RenderStateShard; public final class EntityRenderStateShard extends RenderStateShard { - private static final EntityRenderStateShard UNIDENTIFIED = new EntityRenderStateShard(-1); + public static final EntityRenderStateShard INSTANCE = new EntityRenderStateShard(); - private final int entityId; - - private EntityRenderStateShard(int entityId) { - super("iris:is_entity", () -> { - CapturedRenderingState.INSTANCE.setCurrentEntity(entityId); - GbufferPrograms.beginEntities(); - }, () -> { - CapturedRenderingState.INSTANCE.setCurrentEntity(-1); - GbufferPrograms.endEntities(); - }); - - this.entityId = entityId; - } - - public static EntityRenderStateShard forId(int entityId) { - if (entityId == -1) { - return UNIDENTIFIED; - } else { - // TODO: Cache all created render phases to avoid allocations? - return new EntityRenderStateShard(entityId); - } - } - - @Override - public boolean equals(Object object) { - if (object == null || object.getClass() != this.getClass()) { - return false; - } - - EntityRenderStateShard other = (EntityRenderStateShard) object; - - return this.entityId == other.entityId; + private EntityRenderStateShard() { + super("iris:is_entity", GbufferPrograms::beginEntities, GbufferPrograms::endEntities); } } diff --git a/src/main/java/net/coderbot/iris/layer/GbufferPrograms.java b/src/main/java/net/coderbot/iris/layer/GbufferPrograms.java index 42f0480998..4bb458598b 100644 --- a/src/main/java/net/coderbot/iris/layer/GbufferPrograms.java +++ b/src/main/java/net/coderbot/iris/layer/GbufferPrograms.java @@ -11,6 +11,7 @@ public class GbufferPrograms { private static boolean blockEntities; private static boolean outline; private static Runnable phaseChangeListener; + private static Runnable fallbackEntityListener; private static void checkReentrancy() { if (entities || blockEntities || outline) { @@ -96,6 +97,12 @@ public static void runPhaseChangeNotifier() { } } + public static void runFallbackEntityListener() { + if (fallbackEntityListener != null) { + fallbackEntityListener.run(); + } + } + public static void setupSpecialRenderCondition(SpecialCondition override) { Iris.getPipelineManager().getPipeline().ifPresent(p -> p.setSpecialCondition(override)); } @@ -106,6 +113,7 @@ public static void teardownSpecialRenderCondition(SpecialCondition override) { static { StateUpdateNotifiers.phaseChangeNotifier = listener -> phaseChangeListener = listener; + StateUpdateNotifiers.fallbackEntityNotifier = listener -> fallbackEntityListener = listener; } public static void init() { diff --git a/src/main/java/net/coderbot/iris/layer/InnerWrappedRenderType.java b/src/main/java/net/coderbot/iris/layer/InnerWrappedRenderType.java new file mode 100644 index 0000000000..7a8a647974 --- /dev/null +++ b/src/main/java/net/coderbot/iris/layer/InnerWrappedRenderType.java @@ -0,0 +1,98 @@ +package net.coderbot.iris.layer; + +import net.coderbot.batchedentityrendering.impl.BlendingStateHolder; +import net.coderbot.batchedentityrendering.impl.TransparencyType; +import net.coderbot.batchedentityrendering.impl.WrappableRenderType; +import net.coderbot.iris.mixin.rendertype.RenderTypeAccessor; +import net.minecraft.client.renderer.RenderStateShard; +import net.minecraft.client.renderer.RenderType; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; +import java.util.Optional; + +public class InnerWrappedRenderType extends RenderType implements WrappableRenderType, BlendingStateHolder { + private final RenderStateShard extra; + private final RenderType wrapped; + + public InnerWrappedRenderType(String name, RenderType wrapped, RenderStateShard extra) { + super(name, wrapped.format(), wrapped.mode(), wrapped.bufferSize(), + wrapped.affectsCrumbling(), shouldSortOnUpload(wrapped), wrapped::setupRenderState, wrapped::clearRenderState); + + this.extra = extra; + this.wrapped = wrapped; + } + + public static InnerWrappedRenderType wrapExactlyOnce(String name, RenderType wrapped, RenderStateShard extra) { + if (wrapped instanceof InnerWrappedRenderType) { + wrapped = ((InnerWrappedRenderType) wrapped).unwrap(); + } + + return new InnerWrappedRenderType(name, wrapped, extra); + } + + @Override + public void setupRenderState() { + super.setupRenderState(); + + extra.setupRenderState(); + } + + @Override + public void clearRenderState() { + extra.clearRenderState(); + + super.clearRenderState(); + } + + @Override + public RenderType unwrap() { + return this.wrapped; + } + + @Override + public Optional outline() { + return this.wrapped.outline(); + } + + @Override + public boolean isOutline() { + return this.wrapped.isOutline(); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == null) { + return false; + } + + if (object.getClass() != this.getClass()) { + return false; + } + + InnerWrappedRenderType other = (InnerWrappedRenderType) object; + + return Objects.equals(this.wrapped, other.wrapped) && Objects.equals(this.extra, other.extra); + } + + @Override + public int hashCode() { + // Add two so that we don't have the exact same hash as the wrapped object. + // This means that we won't have a guaranteed collision if we're inserted to a map alongside the unwrapped object. + return this.wrapped.hashCode() + 2; + } + + @Override + public String toString() { + return "iris_wrapped:" + this.wrapped.toString(); + } + + private static boolean shouldSortOnUpload(RenderType type) { + return ((RenderTypeAccessor) type).shouldSortOnUpload(); + } + + @Override + public TransparencyType getTransparencyType() { + return ((BlendingStateHolder) wrapped).getTransparencyType(); + } +} diff --git a/src/main/java/net/coderbot/iris/layer/IsBlockEntityRenderStateShard.java b/src/main/java/net/coderbot/iris/layer/IsBlockEntityRenderStateShard.java deleted file mode 100644 index 340aa44c28..0000000000 --- a/src/main/java/net/coderbot/iris/layer/IsBlockEntityRenderStateShard.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.coderbot.iris.layer; - -import net.minecraft.client.renderer.RenderStateShard; - -public class IsBlockEntityRenderStateShard extends RenderStateShard { - public static final IsBlockEntityRenderStateShard INSTANCE = new IsBlockEntityRenderStateShard(); - - private IsBlockEntityRenderStateShard() { - super("iris:is_block_entity", GbufferPrograms::beginBlockEntities, GbufferPrograms::endBlockEntities); - } -} diff --git a/src/main/java/net/coderbot/iris/layer/IsEntityRenderStateShard.java b/src/main/java/net/coderbot/iris/layer/IsEntityRenderStateShard.java deleted file mode 100644 index b6253b4846..0000000000 --- a/src/main/java/net/coderbot/iris/layer/IsEntityRenderStateShard.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.coderbot.iris.layer; - -import net.minecraft.client.renderer.RenderStateShard; - -public class IsEntityRenderStateShard extends RenderStateShard { - public static final IsEntityRenderStateShard INSTANCE = new IsEntityRenderStateShard(); - - private IsEntityRenderStateShard() { - super("iris:is_entity", GbufferPrograms::beginEntities, GbufferPrograms::endEntities); - } -} diff --git a/src/main/java/net/coderbot/iris/layer/LightningRenderStateShard.java b/src/main/java/net/coderbot/iris/layer/LightningRenderStateShard.java new file mode 100644 index 0000000000..309b3f17ce --- /dev/null +++ b/src/main/java/net/coderbot/iris/layer/LightningRenderStateShard.java @@ -0,0 +1,29 @@ +package net.coderbot.iris.layer; + +import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.coderbot.iris.shaderpack.materialmap.NamespacedId; +import net.coderbot.iris.uniforms.CapturedRenderingState; +import net.minecraft.client.renderer.RenderStateShard; + +public class LightningRenderStateShard extends RenderStateShard { + public static final LightningRenderStateShard INSTANCE = new LightningRenderStateShard(); + private static int backupValue = 0; + + private static final NamespacedId LIGHT = new NamespacedId("minecraft", "lightning_bolt"); + + public LightningRenderStateShard() { + super("iris:lightning", () -> { + if (BlockRenderingSettings.INSTANCE.getEntityIds() != null) { + backupValue = CapturedRenderingState.INSTANCE.getCurrentRenderedEntity(); + CapturedRenderingState.INSTANCE.setCurrentEntity(BlockRenderingSettings.INSTANCE.getEntityIds().applyAsInt(LIGHT)); + GbufferPrograms.runFallbackEntityListener(); + } + }, () -> { + if (BlockRenderingSettings.INSTANCE.getEntityIds() != null) { + CapturedRenderingState.INSTANCE.setCurrentEntity(backupValue); + backupValue = 0; + GbufferPrograms.runFallbackEntityListener(); + } + }); + } +} diff --git a/src/main/java/net/coderbot/iris/layer/OuterWrappedRenderType.java b/src/main/java/net/coderbot/iris/layer/OuterWrappedRenderType.java index 484f5057ad..8e8510e50a 100644 --- a/src/main/java/net/coderbot/iris/layer/OuterWrappedRenderType.java +++ b/src/main/java/net/coderbot/iris/layer/OuterWrappedRenderType.java @@ -1,5 +1,7 @@ package net.coderbot.iris.layer; +import net.coderbot.batchedentityrendering.impl.BlendingStateHolder; +import net.coderbot.batchedentityrendering.impl.TransparencyType; import net.coderbot.batchedentityrendering.impl.WrappableRenderType; import net.coderbot.iris.mixin.rendertype.RenderTypeAccessor; import net.minecraft.client.renderer.RenderStateShard; @@ -9,7 +11,7 @@ import java.util.Objects; import java.util.Optional; -public class OuterWrappedRenderType extends RenderType implements WrappableRenderType { +public class OuterWrappedRenderType extends RenderType implements WrappableRenderType, BlendingStateHolder { private final RenderStateShard extra; private final RenderType wrapped; @@ -88,4 +90,9 @@ public String toString() { private static boolean shouldSortOnUpload(RenderType type) { return ((RenderTypeAccessor) type).shouldSortOnUpload(); } + + @Override + public TransparencyType getTransparencyType() { + return ((BlendingStateHolder) wrapped).getTransparencyType(); + } } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinBiomes.java b/src/main/java/net/coderbot/iris/mixin/MixinBiomes.java new file mode 100644 index 0000000000..ced624948c --- /dev/null +++ b/src/main/java/net/coderbot/iris/mixin/MixinBiomes.java @@ -0,0 +1,20 @@ +package net.coderbot.iris.mixin; + +import net.coderbot.iris.uniforms.BiomeParameters; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.Biomes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Biomes.class) +public class MixinBiomes { + private static int currentId = 0; + + @Inject(method = "register", at = @At("TAIL")) + private static void iris$registerBiome(String string, CallbackInfoReturnable> cir) { + BiomeParameters.getBiomeMap().put(cir.getReturnValue(), currentId++); + } +} diff --git a/src/main/java/net/coderbot/iris/mixin/MixinBooleanState.java b/src/main/java/net/coderbot/iris/mixin/MixinBooleanState.java new file mode 100644 index 0000000000..edb1815624 --- /dev/null +++ b/src/main/java/net/coderbot/iris/mixin/MixinBooleanState.java @@ -0,0 +1,42 @@ +package net.coderbot.iris.mixin; + +import com.mojang.blaze3d.platform.GlStateManager; +import net.coderbot.iris.gl.BooleanStateExtended; +import org.lwjgl.opengl.GL11; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(GlStateManager.BooleanState.class) +public class MixinBooleanState implements BooleanStateExtended { + @Shadow + @Final + private int state; + @Shadow + public boolean enabled; + @Unique + private boolean stateUnknown; + + @Inject(method = "setEnabled", at = @At("HEAD"), cancellable = true) + private void iris$setUnknownState(boolean enable, CallbackInfo ci) { + if (stateUnknown) { + ci.cancel(); + this.enabled = enable; + stateUnknown = false; + if (enable) { + GL11.glEnable(this.state); + } else { + GL11.glDisable(this.state); + } + } + } + + @Override + public void setUnknownState() { + stateUnknown = true; + } +} diff --git a/src/main/java/net/coderbot/iris/mixin/MixinDebugScreenOverlay.java b/src/main/java/net/coderbot/iris/mixin/MixinDebugScreenOverlay.java index 149a0ab473..15c411263c 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinDebugScreenOverlay.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinDebugScreenOverlay.java @@ -1,6 +1,7 @@ package net.coderbot.iris.mixin; import net.coderbot.iris.Iris; +import net.coderbot.iris.gui.option.IrisVideoSettings; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.components.DebugScreenOverlay; import org.spongepowered.asm.mixin.Mixin; @@ -50,25 +51,26 @@ public abstract class MixinDebugScreenOverlay { Iris.getCurrentPack().ifPresent(pack -> { messages.add("[" + Iris.MODNAME + "] " + pack.getProfileInfo()); }); + messages.add("[" + Iris.MODNAME + "] Color space: " + IrisVideoSettings.colorSpace.name()); } else { messages.add("[" + Iris.MODNAME + "] Shaders are disabled"); } messages.add(3, "Direct Buffers: +" + iris$humanReadableByteCountBin(iris$directPool.getMemoryUsed())); - if (!Iris.isSodiumInstalled()) { - messages.add(3, "Native Memory: +" + iris$humanReadableByteCountBin(iris$getNativeMemoryUsage())); - } + //if (!Iris.isSodiumInstalled()) { + // messages.add(3, "Native Memory: +" + iris$humanReadableByteCountBin(iris$getNativeMemoryUsage())); + //} } @Inject(method = "getGameInformation", at = @At("RETURN")) private void iris$appendShadowDebugText(CallbackInfoReturnable> cir) { List messages = cir.getReturnValue(); - if (!Iris.isSodiumInstalled() && Iris.getCurrentPack().isPresent()) { - messages.add(1, ChatFormatting.YELLOW + "[" + Iris.MODNAME + "] Sodium isn't installed; you will have poor performance."); - messages.add(2, ChatFormatting.YELLOW + "[" + Iris.MODNAME + "] Install Sodium if you want to run benchmarks or get higher FPS!"); - } + //if (!Iris.isSodiumInstalled() && Iris.getCurrentPack().isPresent()) { + // messages.add(1, ChatFormatting.YELLOW + "[" + Iris.MODNAME + "] Sodium isn't installed; you will have poor performance."); + // messages.add(2, ChatFormatting.YELLOW + "[" + Iris.MODNAME + "] Install Sodium if you want to run benchmarks or get higher FPS!"); + //} Iris.getPipelineManager().getPipeline().ifPresent(pipeline -> pipeline.addDebugText(messages)); } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinEntityRenderDispatcher.java b/src/main/java/net/coderbot/iris/mixin/MixinEntityRenderDispatcher.java index 35b125acfb..218ab9bb7f 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinEntityRenderDispatcher.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinEntityRenderDispatcher.java @@ -2,8 +2,12 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import it.unimi.dsi.fastutil.objects.Object2IntFunction; import net.coderbot.iris.Iris; +import net.coderbot.iris.block_rendering.BlockRenderingSettings; import net.coderbot.iris.pipeline.WorldRenderingPipeline; +import net.coderbot.iris.shaderpack.materialmap.NamespacedId; +import net.coderbot.iris.uniforms.CapturedRenderingState; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.core.BlockPos; @@ -23,11 +27,53 @@ public class MixinEntityRenderDispatcher { private static final String RENDER_BLOCK_SHADOW = "renderBlockShadow(Lcom/mojang/blaze3d/vertex/PoseStack$Pose;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/world/level/LevelReader;Lnet/minecraft/core/BlockPos;DDDFF)V"; + @Unique + private static final NamespacedId shadowId = new NamespacedId("minecraft", "entity_shadow"); + + @Unique + private static final NamespacedId flameId = new NamespacedId("minecraft", "entity_flame"); + + @Unique + private static int cachedId; + @Inject(method = RENDER_SHADOW, at = @At("HEAD"), cancellable = true) private static void iris$maybeSuppressEntityShadow(PoseStack poseStack, MultiBufferSource bufferSource, Entity entity, float opacity, float tickDelta, LevelReader level, float radius, CallbackInfo ci) { - iris$maybeSuppressShadow(ci); + if (!iris$maybeSuppressShadow(ci)) { + Object2IntFunction entityIds = BlockRenderingSettings.INSTANCE.getEntityIds(); + + if (entityIds == null) { + return; + } + + cachedId = CapturedRenderingState.INSTANCE.getCurrentRenderedEntity(); + CapturedRenderingState.INSTANCE.setCurrentEntity(entityIds.getInt(shadowId)); + } + } + + @Inject(method = RENDER_SHADOW, at = @At("RETURN")) + private static void restoreShadow(PoseStack pPoseStack0, MultiBufferSource pMultiBufferSource1, Entity pEntity2, float pFloat3, float pFloat4, LevelReader pLevelReader5, float pFloat6, CallbackInfo ci) { + CapturedRenderingState.INSTANCE.setCurrentEntity(cachedId); + cachedId = 0; + } + + @Inject(method = "renderFlame", at = @At("HEAD")) + private void iris$setFlameId(PoseStack pEntityRenderDispatcher0, MultiBufferSource pMultiBufferSource1, Entity pEntity2, CallbackInfo ci) { + Object2IntFunction entityIds = BlockRenderingSettings.INSTANCE.getEntityIds(); + + if (entityIds == null) { + return; + } + + cachedId = CapturedRenderingState.INSTANCE.getCurrentRenderedEntity(); + CapturedRenderingState.INSTANCE.setCurrentEntity(entityIds.getInt(flameId)); + } + + @Inject(method = "renderFlame", at = @At("RETURN")) + private void restoreFlameId(PoseStack pEntityRenderDispatcher0, MultiBufferSource pMultiBufferSource1, Entity pEntity2, CallbackInfo ci) { + CapturedRenderingState.INSTANCE.setCurrentEntity(cachedId); + cachedId = 0; } // The underlying method called by renderShadow. @@ -49,11 +95,14 @@ private static void renderBlockShadow(PoseStack.Pose pose, VertexConsumer vc, Le } @Unique - private static void iris$maybeSuppressShadow(CallbackInfo ci) { + private static boolean iris$maybeSuppressShadow(CallbackInfo ci) { WorldRenderingPipeline pipeline = Iris.getPipelineManager().getPipelineNullable(); if (pipeline != null && pipeline.shouldDisableVanillaEntityShadows()) { ci.cancel(); + return true; } + + return false; } } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinGameRenderer.java b/src/main/java/net/coderbot/iris/mixin/MixinGameRenderer.java index 15360bddd1..96ea827e8c 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinGameRenderer.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinGameRenderer.java @@ -4,7 +4,6 @@ import com.mojang.blaze3d.platform.GlUtil; import com.mojang.blaze3d.shaders.Program; import com.mojang.blaze3d.vertex.PoseStack; - import net.coderbot.iris.Iris; import net.coderbot.iris.pipeline.HandRenderer; import net.coderbot.iris.pipeline.ShadowRenderer; @@ -13,23 +12,21 @@ import net.coderbot.iris.pipeline.newshader.CoreWorldRenderingPipeline; import net.coderbot.iris.pipeline.newshader.IrisProgramTypes; import net.coderbot.iris.pipeline.newshader.ShaderKey; - import net.irisshaders.iris.api.v0.IrisApi; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.ItemInHandRenderer; -import net.minecraft.client.renderer.RenderBuffers; import net.minecraft.client.renderer.MultiBufferSource.BufferSource; +import net.minecraft.client.renderer.RenderBuffers; import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.server.packs.resources.ResourceManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.ArrayList; @@ -57,13 +54,27 @@ public class MixinGameRenderer { itemInHandRenderer.renderHandsWithItems(tickDelta, poseStack, bufferSource, localPlayer, light); } - @Redirect(method = "reloadShaders", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Lists;newArrayList()Ljava/util/ArrayList;")) - private ArrayList iris$reloadGeometryShaders() { - ArrayList programs = Lists.newArrayList(); - programs.addAll(IrisProgramTypes.GEOMETRY.getPrograms().values()); - return programs; + @Inject(method = "renderLevel", at = @At("TAIL")) + private void iris$runColorSpace(float pGameRenderer0, long pLong1, PoseStack pPoseStack2, CallbackInfo ci) { + Iris.getPipelineManager().getPipeline().ifPresent(WorldRenderingPipeline::finalizeGameRendering); } + @Redirect( + method = "reloadShaders", + at = @At( + value = "INVOKE", + remap = false, + target = "Lcom/google/common/collect/Lists;newArrayList()Ljava/util/ArrayList;" + ) + ) + private ArrayList iris$reloadGeometryShaders() { + ArrayList programs = Lists.newArrayList(); + programs.addAll(IrisProgramTypes.GEOMETRY.getPrograms().values()); + programs.addAll(IrisProgramTypes.TESS_CONTROL.getPrograms().values()); + programs.addAll(IrisProgramTypes.TESS_EVAL.getPrograms().values()); + return programs; + } + //TODO: check cloud phase @Inject(method = "getPositionShader", at = @At("HEAD"), cancellable = true) @@ -164,19 +175,10 @@ public class MixinGameRenderer { } } - @Inject(method = "getRendertypeCutoutMippedShader", at = @At("HEAD"), cancellable = true) - private static void iris$overrideCutoutMippedShader(CallbackInfoReturnable cir) { - if (ShadowRenderer.ACTIVE) { - // TODO: Wrong program - override(ShaderKey.SHADOW_TERRAIN_CUTOUT, cir); - } else if (isBlockEntities() || isEntities()) { - override(ShaderKey.MOVING_BLOCK, cir); - } else if (shouldOverrideShaders()) { - override(ShaderKey.TERRAIN_CUTOUT_MIPPED, cir); - } - } - - @Inject(method = "getRendertypeCutoutShader", at = @At("HEAD"), cancellable = true) + @Inject(method = { + "getRendertypeCutoutShader", + "getRendertypeCutoutMippedShader" + }, at = @At("HEAD"), cancellable = true) private static void iris$overrideCutoutShader(CallbackInfoReturnable cir) { if (ShadowRenderer.ACTIVE) { override(ShaderKey.SHADOW_TERRAIN_CUTOUT, cir); @@ -229,6 +231,7 @@ public class MixinGameRenderer { "getRendertypeEntityTranslucentShader", "getRendertypeEntityTranslucentCullShader", "getRendertypeItemEntityTranslucentCullShader", + "getRendertypeEntityNoOutlineShader" }, at = @At("HEAD"), cancellable = true) private static void iris$overrideEntityTranslucentShader(CallbackInfoReturnable cir) { if (ShadowRenderer.ACTIVE) { @@ -236,16 +239,17 @@ public class MixinGameRenderer { } else if (HandRenderer.INSTANCE.isActive()) { override(HandRenderer.INSTANCE.isRenderingSolid() ? ShaderKey.HAND_CUTOUT_DIFFUSE : ShaderKey.HAND_WATER_DIFFUSE, cir); } else if (isBlockEntities()) { - override(ShaderKey.BLOCK_ENTITY_DIFFUSE, cir); + override(ShaderKey.BE_TRANSLUCENT, cir); } else if (shouldOverrideShaders()) { override(ShaderKey.ENTITIES_TRANSLUCENT, cir); } } @Inject(method = { - "getRendertypeEnergySwirlShader" - }, at = @At("HEAD"), cancellable = true) - private static void iris$overrideEnergySwirlShader(CallbackInfoReturnable cir) { + "getRendertypeEnergySwirlShader", + "getRendertypeEntityShadowShader" + }, at = @At("HEAD"), cancellable = true) + private static void iris$overrideEnergySwirlShadowShader(CallbackInfoReturnable cir) { if (ShadowRenderer.ACTIVE) { // TODO: Wrong program override(ShaderKey.SHADOW_ENTITIES_CUTOUT, cir); @@ -274,8 +278,7 @@ public class MixinGameRenderer { } @Inject(method = { - "getRendertypeEntitySolidShader", - "getRendertypeEntityNoOutlineShader", + "getRendertypeEntitySolidShader" }, at = @At("HEAD"), cancellable = true) private static void iris$overrideEntitySolidDiffuseShader(CallbackInfoReturnable cir) { if (ShadowRenderer.ACTIVE) { @@ -291,8 +294,7 @@ public class MixinGameRenderer { } @Inject(method = { - "getRendertypeWaterMaskShader", - "getRendertypeEntityShadowShader" + "getRendertypeWaterMaskShader" }, at = @At("HEAD"), cancellable = true) private static void iris$overrideEntitySolidShader(CallbackInfoReturnable cir) { if (ShadowRenderer.ACTIVE) { diff --git a/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_DepthColorOverride.java b/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_DepthColorOverride.java index 20264fddca..3d759312b1 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_DepthColorOverride.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_DepthColorOverride.java @@ -2,9 +2,12 @@ import com.mojang.blaze3d.platform.GlStateManager; import net.coderbot.iris.gl.blending.DepthColorStorage; +import net.coderbot.iris.vertices.ImmediateState; +import org.lwjgl.opengl.GL43C; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(GlStateManager.class) @@ -24,4 +27,18 @@ public class MixinGlStateManager_DepthColorOverride { ci.cancel(); } } + + @Redirect(method = "_drawElements", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glDrawElements(IIIJ)V")) + private static void iris$modify(int mode, int count, int type, long indices) { + if (mode == GL43C.GL_TRIANGLES && ImmediateState.usingTessellation) { + mode = GL43C.GL_PATCHES; + } + + GL43C.glDrawElements(mode, count, type, indices); + } + + @Inject(method = "_glUseProgram", at = @At("TAIL")) + private static void iris$resetTessellation(int pInt0, CallbackInfo ci) { + ImmediateState.usingTessellation = false; + } } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_FramebufferBinding.java b/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_FramebufferBinding.java index 7f81fa77fb..12bc5928e8 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_FramebufferBinding.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_FramebufferBinding.java @@ -16,6 +16,7 @@ public class MixinGlStateManager_FramebufferBinding { private static int iris$drawFramebuffer = 0; private static int iris$readFramebuffer = 0; + private static int iris$program = 0; @Inject(method = "_glBindFramebuffer(II)V", at = @At("HEAD"), cancellable = true) private static void iris$avoidRedundantBind(int target, int framebuffer, CallbackInfo ci) { @@ -43,6 +44,15 @@ public class MixinGlStateManager_FramebufferBinding { } } + @Inject(method = "_glUseProgram", at = @At("HEAD"), cancellable = true) + private static void iris$avoidRedundantBind2(int pInt0, CallbackInfo ci) { + if (iris$program == pInt0) { + ci.cancel(); + } else { + iris$program = pInt0; + } + } + @Inject(method = "_glDeleteFramebuffers(I)V", at = @At("HEAD")) private static void iris$trackFramebufferDelete(int framebuffer, CallbackInfo ci) { if (iris$drawFramebuffer == framebuffer) { diff --git a/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java b/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java index a608e41ea3..e3099da7d6 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java @@ -1,36 +1,33 @@ package net.coderbot.iris.mixin; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.Slice; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix4f; import com.mojang.math.Vector3f; - import net.coderbot.iris.Iris; +import net.coderbot.iris.gl.IrisRenderSystem; import net.coderbot.iris.layer.IsOutlineRenderStateShard; import net.coderbot.iris.layer.OuterWrappedRenderType; import net.coderbot.iris.pipeline.HandRenderer; import net.coderbot.iris.pipeline.WorldRenderingPhase; import net.coderbot.iris.pipeline.WorldRenderingPipeline; +import net.coderbot.iris.shadows.frustum.fallback.NonCullingFrustum; import net.coderbot.iris.uniforms.CapturedRenderingState; +import net.coderbot.iris.uniforms.IrisTimeUniforms; import net.coderbot.iris.uniforms.SystemTimeUniforms; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.RenderBuffers; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.culling.Frustum; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.opengl.GL43C; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(LevelRenderer.class) public class MixinLevelRenderer { @@ -50,6 +47,34 @@ public class MixinLevelRenderer { @Shadow private RenderBuffers renderBuffers; + @Shadow + private Frustum cullingFrustum; + + @Shadow + private @Nullable ClientLevel level; + + @Inject(method = "renderLevel", at = @At("HEAD")) + private void iris$setupPipeline(PoseStack poseStack, float tickDelta, long startTime, boolean renderBlockOutline, + Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, + Matrix4f projection, CallbackInfo callback) { + IrisTimeUniforms.updateTime(); + CapturedRenderingState.INSTANCE.setGbufferModelView(poseStack.last().pose()); + CapturedRenderingState.INSTANCE.setGbufferProjection(projection); + CapturedRenderingState.INSTANCE.setTickDelta(tickDelta); + SystemTimeUniforms.COUNTER.beginFrame(); + SystemTimeUniforms.TIMER.beginFrame(startTime); + + pipeline = Iris.getPipelineManager().preparePipeline(Iris.getCurrentDimension()); + + if (pipeline.shouldDisableFrustumCulling()) { + this.cullingFrustum = new NonCullingFrustum(); + } + + if (Iris.shouldActivateWireframe() && this.minecraft.isLocalServer()) { + IrisRenderSystem.setPolygonMode(GL43C.GL_LINE); + } + } + // Begin shader rendering after buffers have been cleared. // At this point we've ensured that Minecraft's main framebuffer is cleared. // This is important or else very odd issues will happen with shaders that have a final pass that doesn't write to @@ -58,17 +83,11 @@ public class MixinLevelRenderer { private void iris$beginLevelRender(PoseStack poseStack, float tickDelta, long startTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projection, CallbackInfo callback) { - CapturedRenderingState.INSTANCE.setGbufferModelView(poseStack.last().pose()); - CapturedRenderingState.INSTANCE.setGbufferProjection(projection); - CapturedRenderingState.INSTANCE.setTickDelta(tickDelta); - SystemTimeUniforms.COUNTER.beginFrame(); - SystemTimeUniforms.TIMER.beginFrame(startTime); - - pipeline = Iris.getPipelineManager().preparePipeline(Iris.getCurrentDimension()); pipeline.beginLevelRendering(); pipeline.setPhase(WorldRenderingPhase.NONE); } + // Inject a bit early so that we can end our rendering before mods like VoxelMap (which inject at RETURN) // render their waypoint beams. @Inject(method = RENDER, at = @At(value = "RETURN", shift = At.Shift.BEFORE)) @@ -77,6 +96,10 @@ public class MixinLevelRenderer { Minecraft.getInstance().getProfiler().popPush("iris_final"); pipeline.finalizeLevelRendering(); pipeline = null; + + if (Iris.shouldActivateWireframe() && this.minecraft.isLocalServer()) { + IrisRenderSystem.setPolygonMode(GL43C.GL_FILL); + } } // Setup shadow terrain & render shadows before the main terrain setup. We need to do things in this order to diff --git a/src/main/java/net/coderbot/iris/mixin/MixinLightningBoltRenderer.java b/src/main/java/net/coderbot/iris/mixin/MixinLightningBoltRenderer.java new file mode 100644 index 0000000000..27906aa35a --- /dev/null +++ b/src/main/java/net/coderbot/iris/mixin/MixinLightningBoltRenderer.java @@ -0,0 +1,23 @@ +package net.coderbot.iris.mixin; + +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Matrix4f; +import net.coderbot.iris.pipeline.LightningHandler; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.LightningBoltRenderer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(LightningBoltRenderer.class) +public class MixinLightningBoltRenderer { + @Redirect(method = "render(Lnet/minecraft/world/entity/LightningBolt;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderType;lightning()Lnet/minecraft/client/renderer/RenderType;")) + private RenderType iris$overrideTex() { + return LightningHandler.IRIS_LIGHTNING; + } +} diff --git a/src/main/java/net/coderbot/iris/mixin/MixinMinecraft_PipelineManagement.java b/src/main/java/net/coderbot/iris/mixin/MixinMinecraft_PipelineManagement.java index ce0b66e717..f4584af6e2 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinMinecraft_PipelineManagement.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinMinecraft_PipelineManagement.java @@ -4,6 +4,8 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -11,6 +13,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(Minecraft.class) +@OnlyIn(Dist.CLIENT) public class MixinMinecraft_PipelineManagement { /** * Should run before the Minecraft.level field is updated after disconnecting from a server or leaving a singleplayer world diff --git a/src/main/java/net/coderbot/iris/mixin/MixinModelViewBobbing.java b/src/main/java/net/coderbot/iris/mixin/MixinModelViewBobbing.java index 936d75e815..d2c02058c9 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinModelViewBobbing.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinModelViewBobbing.java @@ -1,5 +1,10 @@ package net.coderbot.iris.mixin; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix3f; +import com.mojang.math.Matrix4f; +import net.irisshaders.iris.api.v0.IrisApi; +import net.minecraft.client.renderer.GameRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -9,11 +14,6 @@ import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Matrix4f; - -import net.minecraft.client.renderer.GameRenderer; - /** * This mixin makes the effects of view bobbing and nausea apply to the model view matrix, not the projection matrix. * @@ -27,10 +27,20 @@ public class MixinModelViewBobbing { @Unique private Matrix4f bobbingEffectsModel; + @Unique + private boolean areShadersOn; + + @Inject(method = "renderLevel", at = @At("HEAD")) + private void iris$saveShadersOn(float pGameRenderer0, long pLong1, PoseStack pPoseStack2, CallbackInfo ci) { + areShadersOn = IrisApi.getInstance().isShaderPackInUse(); + } + @ModifyArg(method = "renderLevel", index = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;bobHurt(Lcom/mojang/blaze3d/vertex/PoseStack;F)V")) private PoseStack iris$separateViewBobbing(PoseStack stack) { + if (!areShadersOn) return stack; + stack.pushPose(); stack.last().pose().setIdentity(); @@ -43,6 +53,8 @@ public class MixinModelViewBobbing { slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;bobHurt(Lcom/mojang/blaze3d/vertex/PoseStack;F)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;resetProjectionMatrix(Lcom/mojang/math/Matrix4f;)V"))) private PoseStack.Pose iris$saveBobbing(PoseStack stack) { + if (!areShadersOn) return stack.last(); + bobbingEffectsModel = stack.last().pose().copy(); stack.popPose(); @@ -54,6 +66,8 @@ public class MixinModelViewBobbing { at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;resetProjectionMatrix(Lcom/mojang/math/Matrix4f;)V")) private void iris$applyBobbingToModelView(float tickDelta, long limitTime, PoseStack matrix, CallbackInfo ci) { + if (!areShadersOn) return; + matrix.last().pose().multiply(bobbingEffectsModel); bobbingEffectsModel = null; diff --git a/src/main/java/net/coderbot/iris/mixin/MixinParticleEngine.java b/src/main/java/net/coderbot/iris/mixin/MixinParticleEngine.java index e8fc725133..d23f5d1afa 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinParticleEngine.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinParticleEngine.java @@ -8,7 +8,6 @@ import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.culling.Frustum; - import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -17,19 +16,19 @@ /** * Ensures that all particles are rendered with the textured_lit shader program. */ -@Mixin(value = ParticleEngine.class, remap = false) +@Mixin(ParticleEngine.class) public class MixinParticleEngine { private static final String RENDER = "Lnet/minecraft/client/particle/ParticleEngine;render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;)V"; - @Inject(method = RENDER, at = @At("HEAD")) + @Inject(method = RENDER, at = @At("HEAD"), remap = false) private void iris$beginDrawingParticles(PoseStack poseStack, MultiBufferSource.BufferSource bufferSource, LightTexture lightTexture, Camera camera, float f, Frustum frustum, CallbackInfo ci) { Iris.getPipelineManager().getPipeline().ifPresent(pipeline -> pipeline.setPhase(WorldRenderingPhase.PARTICLES)); } - @Inject(method = RENDER, at = @At("RETURN")) + @Inject(method = RENDER, at = @At("RETURN"), remap = false) private void iris$finishDrawingParticles(PoseStack poseStack, MultiBufferSource.BufferSource bufferSource, LightTexture lightTexture, Camera camera, float f, Frustum frustum, CallbackInfo ci) { diff --git a/src/main/java/net/coderbot/iris/mixin/MixinProgramManager.java b/src/main/java/net/coderbot/iris/mixin/MixinProgramManager.java index 6768728d96..a41ba8d0a9 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinProgramManager.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinProgramManager.java @@ -15,5 +15,11 @@ public class MixinProgramManager { if (shader instanceof ExtendedShader && ((ExtendedShader) shader).getGeometry() != null) { ((ExtendedShader) shader).getGeometry().close(); } + if (shader instanceof ExtendedShader && ((ExtendedShader) shader).getTessControl() != null) { + ((ExtendedShader) shader).getTessControl().close(); + } + if (shader instanceof ExtendedShader && ((ExtendedShader) shader).getTessEval() != null) { + ((ExtendedShader) shader).getTessEval().close(); + } } } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinProgramType.java b/src/main/java/net/coderbot/iris/mixin/MixinProgramType.java index 5046475cf1..44316a1ff2 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinProgramType.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinProgramType.java @@ -4,6 +4,7 @@ import net.coderbot.iris.pipeline.newshader.IrisProgramTypes; import org.apache.commons.lang3.ArrayUtils; import org.lwjgl.opengl.GL32C; +import org.lwjgl.opengl.GL42C; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; @@ -11,6 +12,7 @@ @Mixin(Program.Type.class) public class MixinProgramType { + @SuppressWarnings("target") @Shadow @Final @Mutable @@ -22,6 +24,12 @@ public class MixinProgramType { IrisProgramTypes.GEOMETRY = ProgramTypeAccessor.createProgramType("GEOMETRY", baseOrdinal, "geometry", ".gsh", GL32C.GL_GEOMETRY_SHADER); - $VALUES = ArrayUtils.addAll($VALUES, IrisProgramTypes.GEOMETRY); + IrisProgramTypes.TESS_CONTROL + = ProgramTypeAccessor.createProgramType("TESS_CONTROL", baseOrdinal + 1, "tess_control", ".tcs", GL42C.GL_TESS_CONTROL_SHADER); + + IrisProgramTypes.TESS_EVAL + = ProgramTypeAccessor.createProgramType("TESS_EVAL", baseOrdinal + 2, "tess_eval", ".tes", GL42C.GL_TESS_EVALUATION_SHADER); + + $VALUES = ArrayUtils.addAll($VALUES, IrisProgramTypes.GEOMETRY, IrisProgramTypes.TESS_CONTROL, IrisProgramTypes.TESS_EVAL); } } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinRenderSystem.java b/src/main/java/net/coderbot/iris/mixin/MixinRenderSystem.java index 84a3bdf1a3..a466d1c153 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinRenderSystem.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinRenderSystem.java @@ -3,23 +3,26 @@ import com.mojang.blaze3d.systems.RenderSystem; import net.coderbot.iris.Iris; import net.coderbot.iris.gl.GLDebug; +import net.coderbot.iris.gl.IrisRenderSystem; +import net.coderbot.iris.samplers.IrisSamplers; import net.coderbot.iris.texture.TextureTracker; import net.minecraft.client.renderer.texture.AbstractTexture; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.resources.ResourceLocation; -import net.coderbot.iris.gl.IrisRenderSystem; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -@Mixin(RenderSystem.class) +@Mixin(value = RenderSystem.class) public class MixinRenderSystem { @Inject(method = "initRenderer", at = @At("RETURN")) private static void iris$onRendererInit(int debugVerbosity, boolean alwaysFalse, CallbackInfo ci) { + Iris.duringRenderSystemInit(); GLDebug.initRenderer(); IrisRenderSystem.initRenderer(); + IrisSamplers.initRenderer(); Iris.onRenderSystemInit(); } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinShaderInstance.java b/src/main/java/net/coderbot/iris/mixin/MixinShaderInstance.java index 47747459e8..e2545016c5 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinShaderInstance.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinShaderInstance.java @@ -1,18 +1,8 @@ package net.coderbot.iris.mixin; -import org.slf4j.Logger; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - import com.google.common.collect.ImmutableSet; import com.mojang.blaze3d.shaders.Uniform; import com.mojang.blaze3d.vertex.VertexFormat; - import net.coderbot.iris.Iris; import net.coderbot.iris.gl.blending.DepthColorStorage; import net.coderbot.iris.pipeline.WorldRenderingPipeline; @@ -23,6 +13,14 @@ import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceProvider; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ShaderInstance.class) public abstract class MixinShaderInstance implements ShaderInstanceInterface { @@ -83,14 +81,14 @@ private static boolean shouldOverrideShaders() { public void iris$setupGeometryShader(ResourceProvider resourceProvider, String string, VertexFormat vertexFormat, CallbackInfo ci) { this.iris$createGeometryShader(resourceProvider, string); }*/ - + @Inject(method = "(Lnet/minecraft/server/packs/resources/ResourceProvider;Lnet/minecraft/resources/ResourceLocation;Lcom/mojang/blaze3d/vertex/VertexFormat;)V", at = @At(value = "RETURN")) public void oculus$setupGeometryShader(ResourceProvider resourceProvider, ResourceLocation location, VertexFormat vertexFormat, CallbackInfo ci) { - this.iris$createGeometryShader(resourceProvider, location); + this.iris$createExtraShaders(resourceProvider, location.getPath()); } @Override - public void iris$createGeometryShader(ResourceProvider provider, ResourceLocation name) { + public void iris$createExtraShaders(ResourceProvider provider, String name) { //no-op, used for ExtendedShader to call before the super constructor } } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinTitleScreen.java b/src/main/java/net/coderbot/iris/mixin/MixinTitleScreen.java index 2f9ab6fda6..0b98da271f 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinTitleScreen.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinTitleScreen.java @@ -1,24 +1,13 @@ package net.coderbot.iris.mixin; -import java.net.URI; -import java.net.URISyntaxException; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - import net.coderbot.iris.Iris; -import net.coderbot.iris.compat.sodium.SodiumVersionCheck; -import net.minecraft.ChatFormatting; -import net.minecraft.Util; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.ConfirmScreen; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.TitleScreen; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraftforge.fml.loading.FMLLoader; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(TitleScreen.class) public class MixinTitleScreen extends Screen { @@ -29,38 +18,12 @@ protected MixinTitleScreen(Component arg) { } @Inject(method = "init", at = @At("RETURN")) - public void iris$showSodiumIncompatScreen(CallbackInfo ci) { - if (iris$hasFirstInit) { - return; + public void iris$firstInit(CallbackInfo ci) { + if (!iris$hasFirstInit) { + Iris.onLoadingComplete(); } iris$hasFirstInit = true; - String reason; - - if (!Iris.isSodiumInstalled() && FMLLoader.isProduction()) { - reason = "iris.sodium.failure.reason.notFound"; - } else { - Iris.onLoadingComplete(); - - return; - } - - Minecraft.getInstance().setScreen(new ConfirmScreen( - (boolean accepted) -> { - if (accepted) { - try { - Util.getPlatform().openUri(new URI(SodiumVersionCheck.getDownloadLink())); - } catch (URISyntaxException e) { - throw new IllegalStateException(e); - } - } else { - Minecraft.getInstance().stop(); - } - }, - new TranslatableComponent("iris.sodium.failure.title").withStyle(ChatFormatting.RED), - new TranslatableComponent(reason), - new TranslatableComponent("iris.sodium.failure.download"), - new TranslatableComponent("menu.quit"))); } } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinTweakFarPlane.java b/src/main/java/net/coderbot/iris/mixin/MixinTweakFarPlane.java index e5ad02f97b..f67f9db3d2 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinTweakFarPlane.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinTweakFarPlane.java @@ -31,6 +31,10 @@ * * Fun. */ + +/** + * Due to shader devs moving forward with removing legacy code, I have decided to disable this Mixin. It will be stored here for reference. -IMS + */ @Mixin(GameRenderer.class) public class MixinTweakFarPlane { @Shadow diff --git a/src/main/java/net/coderbot/iris/mixin/MixinWindow.java b/src/main/java/net/coderbot/iris/mixin/MixinWindow.java new file mode 100644 index 0000000000..8787ea4757 --- /dev/null +++ b/src/main/java/net/coderbot/iris/mixin/MixinWindow.java @@ -0,0 +1,21 @@ +package net.coderbot.iris.mixin; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.blaze3d.platform.Window; +import net.coderbot.iris.Iris; +import org.lwjgl.glfw.GLFW; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(value = Window.class, remap = false) +public class MixinWindow { + @WrapOperation(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwDefaultWindowHints()V")) + private void iris$enableDebugContext(final Operation original) { + original.call(); + if (Iris.getIrisConfig().areDebugOptionsEnabled()) { + GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_DEBUG_CONTEXT, GLFW.GLFW_TRUE); + Iris.logger.info("OpenGL debug context activated."); + } + } +} diff --git a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinBlockEntityRenderDispatcher.java b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinBlockEntityRenderDispatcher.java index 165d319034..d0dcb19532 100644 --- a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinBlockEntityRenderDispatcher.java +++ b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinBlockEntityRenderDispatcher.java @@ -1,18 +1,23 @@ package net.coderbot.iris.mixin.entity_render_context; +import com.mojang.blaze3d.vertex.PoseStack; import it.unimi.dsi.fastutil.objects.Object2IntMap; import net.coderbot.batchedentityrendering.impl.Groupable; import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.coderbot.iris.fantastic.WrappingMultiBufferSource; import net.coderbot.iris.layer.BlockEntityRenderStateShard; import net.coderbot.iris.layer.OuterWrappedRenderType; +import net.coderbot.iris.uniforms.CapturedRenderingState; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.world.entity.Entity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; /** * Wraps block entity rendering functions in order to create additional render layers @@ -21,6 +26,8 @@ */ @Mixin(BlockEntityRenderDispatcher.class) public class MixinBlockEntityRenderDispatcher { + private static final String RUN_REPORTED = + "Lnet/minecraft/client/renderer/blockentity/BlockEntityRenderDispatcher;tryRender(Lnet/minecraft/world/level/block/entity/BlockEntity;Ljava/lang/Runnable;)V"; // I inject here in the method so that: // @@ -33,32 +40,32 @@ public class MixinBlockEntityRenderDispatcher { @ModifyVariable(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/BlockEntityType;isValid(Lnet/minecraft/world/level/block/state/BlockState;)Z"), allow = 1, require = 1) - private MultiBufferSource iris$wrapBufferSource(MultiBufferSource bufferSource, BlockEntity blockEntity) { + private MultiBufferSource iris$wrapBufferSource(MultiBufferSource bufferSource, BlockEntity blockEntity) { if (!(bufferSource instanceof Groupable)) { // Fully batched entity rendering is not being used, do not use this wrapper!!! return bufferSource; } + BlockState state = blockEntity.getBlockState(); + Object2IntMap blockStateIds = BlockRenderingSettings.INSTANCE.getBlockStateIds(); - if (blockStateIds == null ) { - return bufferSource; - } - - // At this point, based on where we are in BlockEntityRenderDispatcher: - // - The block entity is non-null - // - The block entity has a world - // - The block entity is not sure that it's supported by a valid block - - BlockState state = blockEntity.getBlockState(); - if (!blockEntity.getType().isValid(state)) { + if (blockStateIds == null) { return bufferSource; } int intId = blockStateIds.getOrDefault(state, -1); - RenderStateShard stateShard = BlockEntityRenderStateShard.forId(intId); + + CapturedRenderingState.INSTANCE.setCurrentBlockEntity(intId); return type -> - bufferSource.getBuffer(OuterWrappedRenderType.wrapExactlyOnce("iris:is_block_entity", type, stateShard)); + bufferSource.getBuffer(OuterWrappedRenderType.wrapExactlyOnce("iris:is_block_entity", type, BlockEntityRenderStateShard.INSTANCE)); + } + + + @Inject(method = "render", at = @At(value = "INVOKE", target = RUN_REPORTED, shift = At.Shift.AFTER)) + private void iris$afterRender(BlockEntity blockEntity, float tickDelta, PoseStack matrix, + MultiBufferSource bufferSource, CallbackInfo ci) { + CapturedRenderingState.INSTANCE.setCurrentBlockEntity(0); } } diff --git a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinCapeLayer.java b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinCapeLayer.java new file mode 100644 index 0000000000..0f69a4b5fb --- /dev/null +++ b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinCapeLayer.java @@ -0,0 +1,35 @@ +package net.coderbot.iris.mixin.entity_render_context; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.coderbot.iris.shaderpack.materialmap.NamespacedId; +import net.coderbot.iris.uniforms.CapturedRenderingState; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.layers.CapeLayer; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(CapeLayer.class) +public class MixinCapeLayer { + private static final NamespacedId CAPE_LOCATION = new NamespacedId("minecraft", "player_cape"); + + @Inject(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/client/player/AbstractClientPlayer;FFFFFF)V", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;pushPose()V"), locals = LocalCapture.CAPTURE_FAILHARD) + private void changeId(PoseStack pCapeLayer0, MultiBufferSource pMultiBufferSource1, int pInt2, AbstractClientPlayer pAbstractClientPlayer3, float pFloat4, float pFloat5, float pFloat6, float pFloat7, float pFloat8, float pFloat9, CallbackInfo ci, ItemStack lvItemStack11) { + if (BlockRenderingSettings.INSTANCE.getItemIds() == null) return; + + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(BlockRenderingSettings.INSTANCE.getItemIds().applyAsInt(CAPE_LOCATION)); + } + + @Inject(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/client/player/AbstractClientPlayer;FFFFFF)V", at = @At(value = "RETURN")) + private void changeId2(CallbackInfo ci) { + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(0); + } +} diff --git a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinElytraLayer.java b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinElytraLayer.java new file mode 100644 index 0000000000..79d6e22177 --- /dev/null +++ b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinElytraLayer.java @@ -0,0 +1,59 @@ +package net.coderbot.iris.mixin.entity_render_context; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.coderbot.iris.shaderpack.materialmap.NamespacedId; +import net.coderbot.iris.uniforms.CapturedRenderingState; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.layers.ElytraLayer; +import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer; +import net.minecraft.client.renderer.entity.layers.RenderLayer; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.PlayerModelPart; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(ElytraLayer.class) +public abstract class MixinElytraLayer> extends RenderLayer { + @Unique + private static final NamespacedId ELYTRA_CAPE_LOCATION = new NamespacedId("minecraft", "elytra_with_cape"); + + public MixinElytraLayer(RenderLayerParent pRenderLayer0) { + super(pRenderLayer0); + } + + @Inject(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;pushPose()V"), locals = LocalCapture.CAPTURE_FAILHARD) + private void changeId(PoseStack pElytraLayer0, MultiBufferSource pMultiBufferSource1, int pInt2, T pLivingEntity3, float pFloat4, float pFloat5, float pFloat6, float pFloat7, float pFloat8, float pFloat9, CallbackInfo ci, ItemStack lvItemStack11, ResourceLocation lvResourceLocation12) { + if (BlockRenderingSettings.INSTANCE.getItemIds() == null) return; + + if (pLivingEntity3 instanceof AbstractClientPlayer player && player.isCapeLoaded() + && player.getCloakTextureLocation() != null + && player.isModelPartShown(PlayerModelPart.CAPE)) { + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(BlockRenderingSettings.INSTANCE.getItemIds().applyAsInt(ELYTRA_CAPE_LOCATION)); + return; + } + + ResourceLocation location = Registry.ITEM.getKey(Items.ELYTRA); + + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(BlockRenderingSettings.INSTANCE.getItemIds().applyAsInt(new NamespacedId(location.getNamespace(), location.getPath()))); + } + + @Inject(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V", at = @At(value = "RETURN")) + private void changeId2(CallbackInfo ci) { + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(0); + } +} diff --git a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderDispatcher.java b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderDispatcher.java index 70ae3a1dde..feace0deef 100644 --- a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderDispatcher.java +++ b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderDispatcher.java @@ -1,20 +1,28 @@ package net.coderbot.iris.mixin.entity_render_context; +import com.mojang.blaze3d.vertex.PoseStack; import it.unimi.dsi.fastutil.objects.Object2IntFunction; +import it.unimi.dsi.fastutil.objects.Object2IntMap; import net.coderbot.batchedentityrendering.impl.Groupable; import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.coderbot.iris.fantastic.WrappingMultiBufferSource; +import net.coderbot.iris.layer.BlockEntityRenderStateShard; import net.coderbot.iris.layer.EntityRenderStateShard; import net.coderbot.iris.layer.OuterWrappedRenderType; import net.coderbot.iris.shaderpack.materialmap.NamespacedId; +import net.coderbot.iris.uniforms.CapturedRenderingState; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.monster.ZombieVillager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; /** * Wraps entity rendering functions in order to create additional render layers @@ -32,18 +40,34 @@ public class MixinEntityRenderDispatcher { return bufferSource; } - ResourceLocation entityId = Registry.ENTITY_TYPE.getKey(entity.getType()); - Object2IntFunction entityIds = BlockRenderingSettings.INSTANCE.getEntityIds(); if (entityIds == null) { return bufferSource; } - int intId = entityIds.applyAsInt(new NamespacedId(entityId.getNamespace(), entityId.getPath())); - RenderStateShard phase = EntityRenderStateShard.forId(intId); + int intId; + + if (entity instanceof ZombieVillager zombie && zombie.isConverting() && BlockRenderingSettings.INSTANCE.hasVillagerConversionId()) { + intId = entityIds.applyAsInt(new NamespacedId("minecraft", "zombie_villager_converting"));; + } else { + ResourceLocation entityId = Registry.ENTITY_TYPE.getKey(entity.getType()); + intId = entityIds.applyAsInt(new NamespacedId(entityId.getNamespace(), entityId.getPath())); + } + + CapturedRenderingState.INSTANCE.setCurrentEntity(intId); return type -> - bufferSource.getBuffer(OuterWrappedRenderType.wrapExactlyOnce("iris:is_entity", type, phase)); + bufferSource.getBuffer(OuterWrappedRenderType.wrapExactlyOnce("iris:is_entity", type, EntityRenderStateShard.INSTANCE)); + } + + // Inject before MatrixStack#pop so that our wrapper stack management operations naturally line up + // with vanilla's MatrixStack management functions. + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;popPose()V")) + private void iris$endEntityRender(Entity entity, double x, double y, double z, float yaw, float tickDelta, + PoseStack poseStack, MultiBufferSource bufferSource, int light, + CallbackInfo ci) { + CapturedRenderingState.INSTANCE.setCurrentEntity(0); + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(0); } } diff --git a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinHorseArmorLayer.java b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinHorseArmorLayer.java new file mode 100644 index 0000000000..08bdeb155b --- /dev/null +++ b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinHorseArmorLayer.java @@ -0,0 +1,37 @@ +package net.coderbot.iris.mixin.entity_render_context; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.coderbot.iris.shaderpack.materialmap.NamespacedId; +import net.coderbot.iris.uniforms.CapturedRenderingState; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.entity.layers.HorseArmorLayer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.animal.horse.Horse; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.HorseArmorItem; +import net.minecraft.world.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(HorseArmorLayer.class) +public class MixinHorseArmorLayer { + @Inject(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/animal/horse/Horse;FFFFFF)V", at = @At(value = "HEAD")) + private void changeId(PoseStack pHorseArmorLayer0, MultiBufferSource pMultiBufferSource1, int pInt2, Horse pHorse3, float pFloat4, float pFloat5, float pFloat6, float pFloat7, float pFloat8, float pFloat9, CallbackInfo ci) { + if (BlockRenderingSettings.INSTANCE.getItemIds() == null || !(pHorse3.getArmor().getItem() instanceof HorseArmorItem)) return; + + ResourceLocation location = Registry.ITEM.getKey((pHorse3.getArmor().getItem())); + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(BlockRenderingSettings.INSTANCE.getItemIds().applyAsInt(new NamespacedId(location.getNamespace(), location.getPath()))); + } + + @Inject(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/animal/horse/Horse;FFFFFF)V", at = @At(value = "TAIL")) + private void changeId2(CallbackInfo ci) { + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(0); + } +} diff --git a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinHumanoidArmorLayer.java b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinHumanoidArmorLayer.java new file mode 100644 index 0000000000..cae30351a0 --- /dev/null +++ b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinHumanoidArmorLayer.java @@ -0,0 +1,44 @@ +package net.coderbot.iris.mixin.entity_render_context; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.coderbot.iris.shaderpack.materialmap.NamespacedId; +import net.coderbot.iris.uniforms.CapturedRenderingState; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer; +import net.minecraft.client.renderer.entity.layers.RenderLayer; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(HumanoidArmorLayer.class) +public abstract class MixinHumanoidArmorLayer, A extends HumanoidModel> + extends RenderLayer { + public MixinHumanoidArmorLayer(RenderLayerParent pRenderLayer0) { + super(pRenderLayer0); + } + + @Inject(method = "renderArmorPiece", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/HumanoidModel;copyPropertiesTo(Lnet/minecraft/client/model/HumanoidModel;)V"), locals = LocalCapture.CAPTURE_FAILHARD) + private void changeId(PoseStack pHumanoidArmorLayer0, MultiBufferSource pMultiBufferSource1, T pLivingEntity2, EquipmentSlot pEquipmentSlot3, int pInt4, A pHumanoidModel5, CallbackInfo ci, ItemStack lvItemStack7, ArmorItem lvArmorItem8) { + if (BlockRenderingSettings.INSTANCE.getItemIds() == null) return; + + ResourceLocation location = Registry.ITEM.getKey(lvArmorItem8); + + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(BlockRenderingSettings.INSTANCE.getItemIds().applyAsInt(new NamespacedId(location.getNamespace(), location.getPath()))); + } + + @Inject(method = "renderArmorPiece", at = @At(value = "TAIL")) + private void changeId2(CallbackInfo ci) { + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(0); + } +} diff --git a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinItemRenderer.java b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinItemRenderer.java new file mode 100644 index 0000000000..f99ca959f8 --- /dev/null +++ b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinItemRenderer.java @@ -0,0 +1,56 @@ +package net.coderbot.iris.mixin.entity_render_context; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.coderbot.iris.shaderpack.materialmap.NamespacedId; +import net.coderbot.iris.uniforms.CapturedRenderingState; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.*; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(ItemRenderer.class) +public abstract class MixinItemRenderer { + @Unique + private int previousBeValue; + + @Inject(method = "render", at = @At(value = "HEAD")) + private void changeId(ItemStack pItemRenderer0, ItemTransforms.TransformType pItemTransforms$TransformType1, boolean pBoolean2, PoseStack pPoseStack3, MultiBufferSource pMultiBufferSource4, int pInt5, int pInt6, BakedModel pBakedModel7, CallbackInfo ci) { + iris$setupId(pItemRenderer0); + } + + @Unique + private void iris$setupId(ItemStack pItemRenderer0) { + if (BlockRenderingSettings.INSTANCE.getItemIds() == null) return; + + if (pItemRenderer0.getItem() instanceof BlockItem blockItem && !(pItemRenderer0.getItem() instanceof SolidBucketItem)) { + if (BlockRenderingSettings.INSTANCE.getBlockStateIds() == null) return; + + previousBeValue = CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity(); + CapturedRenderingState.INSTANCE.setCurrentBlockEntity(1); + + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(BlockRenderingSettings.INSTANCE.getBlockStateIds().getOrDefault(blockItem.getBlock().defaultBlockState(), 0)); + } else { + ResourceLocation location = Registry.ITEM.getKey(pItemRenderer0.getItem()); + + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(BlockRenderingSettings.INSTANCE.getItemIds().applyAsInt(new NamespacedId(location.getNamespace(), location.getPath()))); + } + } + + @Inject(method = "render", at = @At(value = "RETURN")) + private void changeId2(CallbackInfo ci) { + CapturedRenderingState.INSTANCE.setCurrentRenderedItem(0); + CapturedRenderingState.INSTANCE.setCurrentBlockEntity(previousBeValue); + previousBeValue = 0; + } +} diff --git a/src/main/java/net/coderbot/iris/mixin/fantastic/MixinLevelRenderer.java b/src/main/java/net/coderbot/iris/mixin/fantastic/MixinLevelRenderer.java index bae2268096..5aeac4df08 100644 --- a/src/main/java/net/coderbot/iris/mixin/fantastic/MixinLevelRenderer.java +++ b/src/main/java/net/coderbot/iris/mixin/fantastic/MixinLevelRenderer.java @@ -1,30 +1,24 @@ package net.coderbot.iris.mixin.fantastic; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix4f; - -import llamalad7.mixinextras.injector.WrapWithCondition; import net.coderbot.iris.Iris; import net.coderbot.iris.fantastic.ParticleRenderingPhase; import net.coderbot.iris.fantastic.PhasedParticleEngine; -import net.coderbot.iris.shaderpack.ParticleRenderingSettings; import net.coderbot.iris.pipeline.WorldRenderingPipeline; +import net.coderbot.iris.shaderpack.ParticleRenderingSettings; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.particle.ParticleEngine; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderBuffers; +import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.culling.Frustum; - import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; /** @@ -73,21 +67,35 @@ public class MixinLevelRenderer { minecraft.particleEngine.render(poseStack, bufferSource, lightTexture, camera, f, frustum); } }*/ - - @WrapWithCondition( - method = "renderLevel", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;)V") + + @WrapOperation( + method = "renderLevel", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lcom/mojang/blaze3d/vertex/PoseStack;" + + "Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;" + + "Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;" + + "FLnet/minecraft/client/renderer/culling/Frustum;)V" + ) ) - private boolean oculus$renderTranslucentAfterDeferred(ParticleEngine instance, PoseStack poseStack, MultiBufferSource.BufferSource bufferSource, LightTexture lightTexture, Camera camera, float f, Frustum frustum) { + private void oculus$renderTranslucentAfterDeferred( + final ParticleEngine instance, + final PoseStack poseStack, + final MultiBufferSource.BufferSource bufferSource, + final LightTexture lightTexture, + final Camera camera, + final float f, + final Frustum frustum, + final Operation original + ) { ParticleRenderingSettings settings = getRenderingSettings(); - + if (settings == ParticleRenderingSettings.AFTER) { - minecraft.particleEngine.render(poseStack, bufferSource, lightTexture, camera, f, frustum); + original.call(instance, poseStack, bufferSource, lightTexture, camera, f, frustum); } else if (settings == ParticleRenderingSettings.MIXED) { - ((PhasedParticleEngine) minecraft.particleEngine).setParticleRenderingPhase(ParticleRenderingPhase.TRANSLUCENT); - minecraft.particleEngine.render(poseStack, bufferSource, lightTexture, camera, f, frustum); + ((PhasedParticleEngine) instance).setParticleRenderingPhase(ParticleRenderingPhase.TRANSLUCENT); + original.call(instance, poseStack, bufferSource, lightTexture, camera, f, frustum); } - return true; } private ParticleRenderingSettings getRenderingSettings() { diff --git a/src/main/java/net/coderbot/iris/mixin/fantastic/MixinParticleEngine.java b/src/main/java/net/coderbot/iris/mixin/fantastic/MixinParticleEngine.java index 40004f79ed..c3c9ff09a5 100644 --- a/src/main/java/net/coderbot/iris/mixin/fantastic/MixinParticleEngine.java +++ b/src/main/java/net/coderbot/iris/mixin/fantastic/MixinParticleEngine.java @@ -1,95 +1,96 @@ package net.coderbot.iris.mixin.fantastic; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Queue; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - import com.google.common.collect.ImmutableList; - +import com.google.common.collect.Maps; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import net.coderbot.iris.fantastic.ParticleRenderingPhase; import net.coderbot.iris.fantastic.PhasedParticleEngine; import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.ParticleEngine; import net.minecraft.client.particle.ParticleRenderType; +import net.minecraftforge.client.ForgeHooksClient; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.List; +import java.util.Map; +import java.util.Queue; /** * Extends the ParticleEngine class to allow multiple phases of particle rendering. - * + *

* This is used to enable the rendering of known-opaque particles much earlier than other particles, most notably before * translucent content. Normally, particles behind translucent blocks are not visible on Fancy graphics, and a user must * enable the much more intensive Fabulous graphics option. This is not ideal because Fabulous graphics is fundamentally * incompatible with most shader packs. - * + *

* So what causes this? Essentially, on Fancy graphics, all particles are rendered after translucent terrain. Aside from * causing problems with particles being invisible, this also causes particles to write to the translucent depth buffer, * even when they are not translucent. This notably causes problems with particles on Sildur's Enhanced Default when * underwater. - * + *

* So, what these mixins do is try to render known-opaque particles right before entities are rendered and right after * opaque terrain has been rendered. This seems to be an acceptable injection point, and has worked in my testing. It * fixes issues with particles when underwater, fixes a vanilla bug, and doesn't have any significant performance hit. * A win-win! - * + *

* Unfortunately, there are limitations. Some particles rendering in texture sheets where translucency is supported. So, * even if an individual particle from that sheet is not translucent, it will still be treated as translucent, and thus * will not be affected by this patch. Without making more invasive and sweeping changes, there isn't a great way to get * around this. - * + *

* As the saying goes, "Work smarter, not harder." */ @Mixin(ParticleEngine.class) public class MixinParticleEngine implements PhasedParticleEngine { - @Unique - private ParticleRenderingPhase phase = ParticleRenderingPhase.EVERYTHING; - - @Shadow - @Final - private static List RENDER_ORDER; - - @Shadow - @Final - private Map> particles; + @Unique + private ParticleRenderingPhase phase = ParticleRenderingPhase.EVERYTHING; - private static final List OPAQUE_PARTICLE_RENDER_TYPES; + @Shadow + @Final + private static List RENDER_ORDER; - static { - OPAQUE_PARTICLE_RENDER_TYPES = ImmutableList.of( - ParticleRenderType.PARTICLE_SHEET_OPAQUE, - ParticleRenderType.PARTICLE_SHEET_LIT, - ParticleRenderType.CUSTOM, - ParticleRenderType.NO_RENDER - ); - } + private static final List OPAQUE_PARTICLE_RENDER_TYPES; - @Redirect(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;)V", at = @At(value = "FIELD", target = "Lnet/minecraft/client/particle/ParticleEngine;particles:Ljava/util/Map;")) - private Map> iris$selectParticlesToRender(ParticleEngine instance) { - Map> toRender = new HashMap<>(particles); - if (phase == ParticleRenderingPhase.TRANSLUCENT) { - // Remove all known opaque particle texture sheets. - for(ParticleRenderType type : OPAQUE_PARTICLE_RENDER_TYPES) - toRender.remove(type); + static { + OPAQUE_PARTICLE_RENDER_TYPES = ImmutableList.of( + ParticleRenderType.PARTICLE_SHEET_OPAQUE, + ParticleRenderType.PARTICLE_SHEET_LIT, + ParticleRenderType.CUSTOM, + ParticleRenderType.NO_RENDER + ); + } - return toRender; - } else if (phase == ParticleRenderingPhase.OPAQUE) { - // Render only opaque particle sheets - toRender.remove(ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT); - return toRender; - } else { - // Don't override particle rendering - return toRender; - } - } + @ModifyExpressionValue( + method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;" + + "Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;" + + "Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;" + + "FLnet/minecraft/client/renderer/culling/Frustum;)V", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/client/particle/ParticleEngine;particles:Ljava/util/Map;" + ) + ) + private Map> iris$selectParticlesToRender( + Map> particles + ) { + Map> toRender = + Maps.newTreeMap(ForgeHooksClient.makeParticleRenderTypeComparator(RENDER_ORDER)); + for (Map.Entry> type : particles.entrySet()) { + if (phase == ParticleRenderingPhase.OPAQUE && + type.getKey() == ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT) continue; + if (phase == ParticleRenderingPhase.TRANSLUCENT && OPAQUE_PARTICLE_RENDER_TYPES.contains(type.getKey())) + continue; + toRender.put(type.getKey(), type.getValue()); + } + return toRender; + } - @Override - public void setParticleRenderingPhase(ParticleRenderingPhase phase) { - this.phase = phase; - } -} \ No newline at end of file + @Override + public void setParticleRenderingPhase(ParticleRenderingPhase phase) { + this.phase = phase; + } +} diff --git a/src/main/java/net/coderbot/iris/mixin/gui/MixinGui.java b/src/main/java/net/coderbot/iris/mixin/gui/MixinGui.java index 98bc987633..ee3068156b 100644 --- a/src/main/java/net/coderbot/iris/mixin/gui/MixinGui.java +++ b/src/main/java/net/coderbot/iris/mixin/gui/MixinGui.java @@ -35,33 +35,6 @@ public class MixinGui { } } - // TODO: Move this to a more appropriate mixin - @Inject(method = "render", at = @At("RETURN")) - public void iris$displayBigSodiumWarning(PoseStack poseStack, float tickDelta, CallbackInfo ci) { - if (Iris.isSodiumInstalled() - || Minecraft.getInstance().options.renderDebug - || !Iris.getCurrentPack().isPresent()) { - return; - } - - Font font = Minecraft.getInstance().font; - - List warningLines = new ArrayList<>(); - warningLines.add("[" + Iris.MODNAME + "] Sodium isn't installed; you will have poor performance."); - warningLines.add("[" + Iris.MODNAME + "] Install Sodium if you want to run benchmarks or get higher FPS!"); - - for (int i = 0; i < warningLines.size(); ++i) { - String string = warningLines.get(i); - - final int lineHeight = 9; - final int lineWidth = font.width(string); - final int y = 2 + lineHeight * i; - - GuiComponent.fill(poseStack, 1, y - 1, 2 + lineWidth + 1, y + lineHeight - 1, 0x9050504E); - font.draw(poseStack, string, 2.0F, y, 0xFFFF55); - } - } - @Inject(method = "renderVignette", at = @At("HEAD"), cancellable = true) private void iris$disableVignetteRendering(Entity entity, CallbackInfo ci) { WorldRenderingPipeline pipeline = Iris.getPipelineManager().getPipelineNullable(); diff --git a/src/main/java/net/coderbot/iris/mixin/statelisteners/BooleanStateAccessor.java b/src/main/java/net/coderbot/iris/mixin/statelisteners/BooleanStateAccessor.java index 8490c1741b..6a13c0640c 100644 --- a/src/main/java/net/coderbot/iris/mixin/statelisteners/BooleanStateAccessor.java +++ b/src/main/java/net/coderbot/iris/mixin/statelisteners/BooleanStateAccessor.java @@ -1,9 +1,10 @@ package net.coderbot.iris.mixin.statelisteners; +import com.mojang.blaze3d.platform.GlStateManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(targets = "com/mojang/blaze3d/platform/GlStateManager$BooleanState") +@Mixin(GlStateManager.BooleanState.class) public interface BooleanStateAccessor { @Accessor("enabled") boolean isEnabled(); diff --git a/src/main/java/net/coderbot/iris/mixin/texture/MixinGlStateManager.java b/src/main/java/net/coderbot/iris/mixin/texture/MixinGlStateManager.java index ebd8730396..1980a38ad5 100644 --- a/src/main/java/net/coderbot/iris/mixin/texture/MixinGlStateManager.java +++ b/src/main/java/net/coderbot/iris/mixin/texture/MixinGlStateManager.java @@ -8,7 +8,6 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; diff --git a/src/main/java/net/coderbot/iris/mixin/texture/MixinTextureManager.java b/src/main/java/net/coderbot/iris/mixin/texture/MixinTextureManager.java index 0d69356940..fd378efccc 100644 --- a/src/main/java/net/coderbot/iris/mixin/texture/MixinTextureManager.java +++ b/src/main/java/net/coderbot/iris/mixin/texture/MixinTextureManager.java @@ -13,7 +13,7 @@ @Mixin(TextureManager.class) public class MixinTextureManager { - @Inject(method = "m_118482_", at = @At("TAIL"), remap = false) + @Inject(method = {"m_118482_", "method_18167"}, at = @At("TAIL"), remap = false) private void iris$onTailReloadLambda(ResourceManager resourceManager, Executor applyExecutor, Void void1, CallbackInfo ci) { TextureFormatLoader.reload(resourceManager); PBRTextureManager.INSTANCE.clear(); diff --git a/src/main/java/net/coderbot/iris/mixin/vertices/MixinBufferBuilder.java b/src/main/java/net/coderbot/iris/mixin/vertices/MixinBufferBuilder.java index 0a14ec8aed..c0e83bd18a 100644 --- a/src/main/java/net/coderbot/iris/mixin/vertices/MixinBufferBuilder.java +++ b/src/main/java/net/coderbot/iris/mixin/vertices/MixinBufferBuilder.java @@ -3,10 +3,15 @@ import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferVertexConsumer; import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.DefaultedVertexConsumer; +import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormatElement; import net.coderbot.iris.block_rendering.BlockRenderingSettings; import net.coderbot.iris.vendored.joml.Vector3f; +import net.coderbot.iris.vertices.NormI8; +import org.jetbrains.annotations.NotNull; +import net.coderbot.iris.uniforms.CapturedRenderingState; import net.coderbot.iris.vertices.BlockSensitiveBufferBuilder; import net.coderbot.iris.vertices.BufferBuilderPolygonView; import net.coderbot.iris.vertices.ExtendedDataHelper; @@ -20,6 +25,7 @@ import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.nio.ByteBuffer; @@ -28,7 +34,7 @@ * Dynamically and transparently extends the vanilla vertex formats with additional data */ @Mixin(BufferBuilder.class) -public abstract class MixinBufferBuilder implements BufferVertexConsumer, BlockSensitiveBufferBuilder, ExtendingBufferBuilder { +public abstract class MixinBufferBuilder extends DefaultedVertexConsumer implements BufferVertexConsumer, BlockSensitiveBufferBuilder, ExtendingBufferBuilder { @Unique private boolean extending; @@ -48,7 +54,7 @@ public abstract class MixinBufferBuilder implements BufferVertexConsumer, BlockS private final Vector3f normal = new Vector3f(); @Unique - private boolean injectNormal; + private boolean injectNormalAndUV1; @Unique private short currentBlock; @@ -92,6 +98,12 @@ public abstract class MixinBufferBuilder implements BufferVertexConsumer, BlockS @Shadow public abstract void putShort(int i, short s); + @Shadow + protected abstract void switchFormat(VertexFormat arg); + + @Shadow + public abstract void nextElement(); + @Override public void iris$beginWithoutExtending(VertexFormat.Mode drawMode, VertexFormat vertexFormat) { iris$shouldNotExtend = true; @@ -107,27 +119,51 @@ public abstract class MixinBufferBuilder implements BufferVertexConsumer, BlockS vertexCount = 0; if (extending) { - injectNormal = format == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP; + injectNormalAndUV1 = format == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP; } } @Inject(method = "begin", at = @At("RETURN")) private void iris$afterBegin(VertexFormat.Mode drawMode, VertexFormat format, CallbackInfo ci) { if (extending) { - if (format == DefaultVertexFormat.NEW_ENTITY) { - this.format = IrisVertexFormats.ENTITY; - this.iris$isTerrain = false; - } else { - this.format = IrisVertexFormats.TERRAIN; + if (format == DefaultVertexFormat.BLOCK) { + this.switchFormat(IrisVertexFormats.TERRAIN); this.iris$isTerrain = true; + } else { + this.switchFormat(IrisVertexFormats.ENTITY); + this.iris$isTerrain = false; } this.currentElement = this.format.getElements().get(0); } } + @Override + public @NotNull VertexConsumer uv2(int pBufferVertexConsumer0, int pInt1) { + if (injectNormalAndUV1 && currentElement == DefaultVertexFormat.ELEMENT_UV1) { + this.putShort(0, (short) 0); + this.putShort(2, (short) 10); + this.nextElement(); + } + return BufferVertexConsumer.super.uv2(pBufferVertexConsumer0, pInt1); + } + + @ModifyArg(method = "begin", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/BufferBuilder;switchFormat(Lcom/mojang/blaze3d/vertex/VertexFormat;)V")) + private VertexFormat iris$afterBeginSwitchFormat(VertexFormat arg) { + if (extending) { + if (format == DefaultVertexFormat.NEW_ENTITY) { + return IrisVertexFormats.ENTITY; + } else { + return IrisVertexFormats.TERRAIN; + } + } + return arg; + } + + @Inject(method = "discard()V", at = @At("HEAD")) private void iris$onDiscard(CallbackInfo ci) { extending = false; + injectNormalAndUV1 = false; vertexCount = 0; } @@ -147,7 +183,7 @@ public abstract class MixinBufferBuilder implements BufferVertexConsumer, BlockS return; } - if (injectNormal && currentElement == DefaultVertexFormat.ELEMENT_NORMAL) { + if (injectNormalAndUV1 && currentElement == DefaultVertexFormat.ELEMENT_NORMAL) { this.putInt(0, 0); this.nextElement(); } @@ -156,8 +192,15 @@ public abstract class MixinBufferBuilder implements BufferVertexConsumer, BlockS // ENTITY_ELEMENT this.putShort(0, currentBlock); this.putShort(2, currentRenderType); - this.nextElement(); + } else { + // ENTITY_ELEMENT + this.putShort(0, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedEntity()); + this.putShort(2, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity()); + this.putShort(4, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedItem()); } + + this.nextElement(); + // MID_TEXTURE_ELEMENT this.putFloat(0, 0); this.putFloat(4, 0); @@ -201,15 +244,6 @@ private void fillExtendedData(int vertexAmount) { midU /= vertexAmount; midV /= vertexAmount; - if (vertexAmount == 3) { - NormalHelper.computeFaceNormalTri(normal, polygon); - } else { - NormalHelper.computeFaceNormal(normal, polygon); - } - int packedNormal = NormalHelper.packNormal(normal, 0.0f); - - int tangent = NormalHelper.computeTangent(normal.x, normal.y, normal.z, polygon); - int midUOffset; int midVOffset; int normalOffset; @@ -220,17 +254,35 @@ private void fillExtendedData(int vertexAmount) { normalOffset = 24; tangentOffset = 8; } else { - midUOffset = 12; - midVOffset = 8; - normalOffset = 16; - tangentOffset = 4; + midUOffset = 14; + midVOffset = 10; + normalOffset = 24; + tangentOffset = 6; } - for (int vertex = 0; vertex < vertexAmount; vertex++) { - buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU); - buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV); - buffer.putInt(nextElementByte - normalOffset - stride * vertex, packedNormal); - buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent); + if (vertexAmount == 3) { + // NormalHelper.computeFaceNormalTri(normal, polygon); // Removed to enable smooth shaded triangles. Mods rendering triangles with bad normals need to recalculate their normals manually or otherwise shading might be inconsistent. + + for (int vertex = 0; vertex < vertexAmount; vertex++) { + int packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex); // retrieve per-vertex normal + + int tangent = NormalHelper.computeTangentSmooth(NormI8.unpackX(packedNormal), NormI8.unpackY(packedNormal), NormI8.unpackZ(packedNormal), polygon); + + buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU); + buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV); + buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent); + } + } else { + NormalHelper.computeFaceNormal(normal, polygon); + int packedNormal = NormI8.pack(normal.x, normal.y, normal.z, 0.0f); + int tangent = NormalHelper.computeTangent(normal.x, normal.y, normal.z, polygon); + + for (int vertex = 0; vertex < vertexAmount; vertex++) { + buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU); + buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV); + buffer.putInt(nextElementByte - normalOffset - stride * vertex, packedNormal); + buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent); + } } } diff --git a/src/main/java/net/coderbot/iris/mixin/vertices/MixinVertexFormat.java b/src/main/java/net/coderbot/iris/mixin/vertices/MixinVertexFormat.java index cfe614144d..5bff29cff9 100644 --- a/src/main/java/net/coderbot/iris/mixin/vertices/MixinVertexFormat.java +++ b/src/main/java/net/coderbot/iris/mixin/vertices/MixinVertexFormat.java @@ -18,11 +18,11 @@ public class MixinVertexFormat { @Inject(method = "setupBufferState", at = @At("HEAD"), cancellable = true) private void iris$onSetupBufferState(CallbackInfo ci) { if (BlockRenderingSettings.INSTANCE.shouldUseExtendedVertexFormat() && ImmediateState.renderWithExtendedVertexFormat) { - if ((Object) this == DefaultVertexFormat.BLOCK || (Object) this == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP) { + if ((Object) this == DefaultVertexFormat.BLOCK) { IrisVertexFormats.TERRAIN.setupBufferState(); ci.cancel(); - } else if ((Object) this == DefaultVertexFormat.NEW_ENTITY) { + } else if ((Object) this == DefaultVertexFormat.NEW_ENTITY || (Object) this == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP) { IrisVertexFormats.ENTITY.setupBufferState(); ci.cancel(); @@ -33,11 +33,11 @@ public class MixinVertexFormat { @Inject(method = "clearBufferState", at = @At("HEAD"), cancellable = true) private void iris$onClearBufferState(CallbackInfo ci) { if (BlockRenderingSettings.INSTANCE.shouldUseExtendedVertexFormat() && ImmediateState.renderWithExtendedVertexFormat) { - if ((Object) this == DefaultVertexFormat.BLOCK || (Object) this == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP) { + if ((Object) this == DefaultVertexFormat.BLOCK) { IrisVertexFormats.TERRAIN.clearBufferState(); ci.cancel(); - } else if ((Object) this == DefaultVertexFormat.NEW_ENTITY) { + } else if ((Object) this == DefaultVertexFormat.NEW_ENTITY || (Object) this == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP) { IrisVertexFormats.ENTITY.clearBufferState(); ci.cancel(); diff --git a/src/main/java/net/coderbot/iris/mixin/vertices/MixinVertexFormatElement.java b/src/main/java/net/coderbot/iris/mixin/vertices/MixinVertexFormatElement.java index 427c80b45b..677667d1ef 100644 --- a/src/main/java/net/coderbot/iris/mixin/vertices/MixinVertexFormatElement.java +++ b/src/main/java/net/coderbot/iris/mixin/vertices/MixinVertexFormatElement.java @@ -13,7 +13,7 @@ public class MixinVertexFormatElement { @Inject(method = "supportsUsage", at = @At("HEAD"), cancellable = true) private void iris$fixGenericAttributes(int index, VertexFormatElement.Usage type, CallbackInfoReturnable cir) { - if (type == VertexFormatElement.Usage.GENERIC) { + if (type == VertexFormatElement.Usage.GENERIC || type == VertexFormatElement.Usage.PADDING) { cir.setReturnValue(true); } } diff --git a/src/main/java/net/coderbot/iris/mixin/vertices/block_rendering/MixinBufferBuilder_SeparateAo.java b/src/main/java/net/coderbot/iris/mixin/vertices/block_rendering/MixinBufferBuilder_SeparateAo.java index be6d73dd49..e8ced92f40 100644 --- a/src/main/java/net/coderbot/iris/mixin/vertices/block_rendering/MixinBufferBuilder_SeparateAo.java +++ b/src/main/java/net/coderbot/iris/mixin/vertices/block_rendering/MixinBufferBuilder_SeparateAo.java @@ -7,6 +7,8 @@ import net.minecraft.client.renderer.block.model.BakedQuad; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; import java.util.Arrays; @@ -21,12 +23,10 @@ * field to store the directional shading / ambient occlusion coefficient for each vertex. This mixin implements that * behavior, though conditionally controlled by the current shader pack of course. */ -@Mixin(BufferBuilder.class) +@Mixin(value = BufferBuilder.class, priority = 999) public abstract class MixinBufferBuilder_SeparateAo extends DefaultedVertexConsumer { - @Unique private float[] brightnesses; - @Unique private int brightnessIndex; @Override @@ -43,9 +43,8 @@ public void putBulkData(PoseStack.Pose matrixEntry, BakedQuad quad, float[] brig super.putBulkData(matrixEntry, quad, brightnesses, red, green, blue, lights, overlay, useQuadColorData); } - @Override - public void vertex(float x, float y, float z, float red, float green, float blue, float alpha, float u, float v, - int overlay, int light, float normalX, float normalY, float normalZ) { + @ModifyVariable(method = "vertex", at = @At("HEAD"), index = 7, argsOnly = true) + public float vertex(float alpha) { if (brightnesses != null && BlockRenderingSettings.INSTANCE.shouldUseSeparateAo()) { if (brightnessIndex < brightnesses.length) { alpha = brightnesses[brightnessIndex++]; @@ -54,6 +53,6 @@ public void vertex(float x, float y, float z, float red, float green, float blue } } - super.vertex(x, y, z, red, green, blue, alpha, u, v, overlay, light, normalX, normalY, normalZ); + return alpha; } } diff --git a/src/main/java/net/coderbot/iris/pipeline/ClearPassCreator.java b/src/main/java/net/coderbot/iris/pipeline/ClearPassCreator.java index 78cef8c68a..c0f649745f 100644 --- a/src/main/java/net/coderbot/iris/pipeline/ClearPassCreator.java +++ b/src/main/java/net/coderbot/iris/pipeline/ClearPassCreator.java @@ -45,6 +45,7 @@ public static ImmutableList createClearPasses(RenderTargets renderTar } RenderTarget target = renderTargets.get(buffer); + if (target == null) return; Vector4f clearColor = settings.getClearColor().orElse(defaultClearColor); clearByColor.computeIfAbsent(new Vector2i(target.getWidth(), target.getHeight()), size -> new HashMap<>()).computeIfAbsent(new ClearPassInformation(clearColor, target.getWidth(), target.getHeight()), color -> new IntArrayList()).add(buffer); } @@ -82,18 +83,24 @@ public static ImmutableList createClearPasses(RenderTargets renderTar public static ImmutableList createShadowClearPasses(ShadowRenderTargets renderTargets, boolean fullClear, PackShadowDirectives renderTargetDirectives) { + if (renderTargets == null) { + return ImmutableList.of(); + } + final int maxDrawBuffers = GlStateManager._getInteger(GL21C.GL_MAX_DRAW_BUFFERS); // Sort buffers by their clear color so we can group up glClear calls. Map clearByColor = new HashMap<>(); - for (int i = 0; i < renderTargetDirectives.getColorSamplingSettings().size(); i++) { - // unboxed - PackShadowDirectives.SamplingSettings settings = renderTargetDirectives.getColorSamplingSettings().get(i); + for (int i = 0; i < renderTargets.getRenderTargetCount(); i++) { + if (renderTargets.get(i) != null) { + // unboxed + PackShadowDirectives.SamplingSettings settings = renderTargetDirectives.getColorSamplingSettings().get(i); - if (fullClear || settings.getClear()) { - Vector4f clearColor = settings.getClearColor(); - clearByColor.computeIfAbsent(clearColor, color -> new IntArrayList()).add(i); + if (fullClear || settings.getClear()) { + Vector4f clearColor = settings.getClearColor(); + clearByColor.computeIfAbsent(clearColor, color -> new IntArrayList()).add(i); + } } } diff --git a/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java b/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java index 19f35da46b..5f2f60cdce 100644 --- a/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java +++ b/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java @@ -11,30 +11,26 @@ import net.coderbot.iris.Iris; import net.coderbot.iris.block_rendering.BlockMaterialMapping; import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.coderbot.iris.compat.dh.DHCompat; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gbuffer_overrides.matching.InputAvailability; import net.coderbot.iris.gbuffer_overrides.matching.ProgramTable; import net.coderbot.iris.gbuffer_overrides.matching.RenderCondition; import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition; import net.coderbot.iris.gbuffer_overrides.state.RenderTargetStateListener; -import net.coderbot.iris.gl.blending.AlphaTest; -import net.coderbot.iris.gl.blending.AlphaTestOverride; -import net.coderbot.iris.gl.blending.AlphaTestStorage; -import net.coderbot.iris.gl.blending.BlendModeOverride; -import net.coderbot.iris.gl.blending.BufferBlendOverride; +import net.coderbot.iris.gl.IrisRenderSystem; +import net.coderbot.iris.gl.blending.*; +import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; import net.coderbot.iris.gl.framebuffer.GlFramebuffer; -import net.coderbot.iris.gl.program.ComputeProgram; -import net.coderbot.iris.gl.program.Program; -import net.coderbot.iris.gl.program.ProgramBuilder; -import net.coderbot.iris.gl.program.ProgramImages; -import net.coderbot.iris.gl.program.ProgramSamplers; +import net.coderbot.iris.gl.program.*; +import net.coderbot.iris.gl.texture.DepthBufferFormat; import net.coderbot.iris.gl.texture.TextureType; import net.coderbot.iris.helpers.Tri; -import net.coderbot.iris.pipeline.newshader.FogMode; -import net.coderbot.iris.pipeline.transform.PatchShaderType; -import net.coderbot.iris.gl.texture.DepthBufferFormat; import net.coderbot.iris.layer.GbufferPrograms; import net.coderbot.iris.mixin.GlStateManagerAccessor; import net.coderbot.iris.mixin.LevelRendererAccessor; +import net.coderbot.iris.pipeline.newshader.FogMode; +import net.coderbot.iris.pipeline.transform.PatchShaderType; import net.coderbot.iris.pipeline.transform.TransformPatcher; import net.coderbot.iris.postprocess.BufferFlipper; import net.coderbot.iris.postprocess.CenterDepthSampler; @@ -45,17 +41,7 @@ import net.coderbot.iris.rendertarget.RenderTargets; import net.coderbot.iris.samplers.IrisImages; import net.coderbot.iris.samplers.IrisSamplers; -import net.coderbot.iris.shaderpack.ComputeSource; -import net.coderbot.iris.shaderpack.CloudSetting; -import net.coderbot.iris.shaderpack.IdMap; -import net.coderbot.iris.shaderpack.OptionalBoolean; -import net.coderbot.iris.shaderpack.PackDirectives; -import net.coderbot.iris.shaderpack.PackShadowDirectives; -import net.coderbot.iris.shaderpack.ParticleRenderingSettings; -import net.coderbot.iris.shaderpack.ProgramDirectives; -import net.coderbot.iris.shaderpack.ProgramFallbackResolver; -import net.coderbot.iris.shaderpack.ProgramSet; -import net.coderbot.iris.shaderpack.ProgramSource; +import net.coderbot.iris.shaderpack.*; import net.coderbot.iris.shaderpack.loading.ProgramId; import net.coderbot.iris.shaderpack.texture.TextureStage; import net.coderbot.iris.shadows.ShadowCompositeRenderer; @@ -67,9 +53,9 @@ import net.coderbot.iris.texture.pbr.PBRTextureManager; import net.coderbot.iris.texture.pbr.PBRType; import net.coderbot.iris.uniforms.CapturedRenderingState; -import net.coderbot.iris.uniforms.custom.CustomUniforms; import net.coderbot.iris.uniforms.CommonUniforms; import net.coderbot.iris.uniforms.FrameUpdateNotifier; +import net.coderbot.iris.uniforms.custom.CustomUniforms; import net.coderbot.iris.vendored.joml.Vector3d; import net.coderbot.iris.vendored.joml.Vector4f; import net.minecraft.client.Camera; @@ -77,25 +63,14 @@ import net.minecraft.client.renderer.DimensionSpecialEffects; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.texture.AbstractTexture; +import net.minecraft.network.chat.TranslatableComponent; import org.jetbrains.annotations.Nullable; -import org.lwjgl.opengl.GL15C; -import org.lwjgl.opengl.GL20C; -import org.lwjgl.opengl.GL21C; -import org.lwjgl.opengl.GL30C; +import org.lwjgl.opengl.*; +import java.util.*; import java.util.function.IntFunction; import java.util.function.Supplier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.OptionalInt; -import java.util.Set; - /** * Encapsulates the compiled shader program objects for the currently loaded shaderpack. */ @@ -159,6 +134,8 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R private boolean isRenderingShadow = false; private InputAvailability inputs = new InputAvailability(false, false, false); private SpecialCondition special = null; + private ShaderStorageBufferHolder shaderStorageBufferHolder; + private boolean showSSBOError = false; private boolean shouldBindPBR; private int currentNormalTexture; @@ -195,6 +172,24 @@ public DeferredWorldRenderingPipeline(ProgramSet programs) { } }); + if (!programs.getPackDirectives().getBufferObjects().isEmpty()) { + if (IrisRenderSystem.supportsSSBO()) { + //this.shaderStorageBufferHolder = new ShaderStorageBufferHolder(programs.getPackDirectives().getBufferObjects()); + + this.shaderStorageBufferHolder.setupBuffers(); + } else { + Iris.logger.fatal("Shader storage buffers/immutable buffer storage is not supported on this graphics card, however the shaderpack requested them? Let's hope it's not a problem."); + showSSBOError = true; + for (int i = 0; i < 16; i++) { + IrisRenderSystem.bindBufferBase(GL43C.GL_SHADER_STORAGE_BUFFER, i, i); + } + } + } else { + for (int i = 0; i < 16; i++) { + IrisRenderSystem.bindBufferBase(GL43C.GL_SHADER_STORAGE_BUFFER, i, i); + } + } + RenderTarget mainTarget = Minecraft.getInstance().getMainRenderTarget(); int depthTextureId = mainTarget.getDepthTextureId(); @@ -254,36 +249,36 @@ public DeferredWorldRenderingPipeline(ProgramSet programs) { this.shadowTargetsSupplier = () -> { if (shadowRenderTargets == null) { - this.shadowRenderTargets = new ShadowRenderTargets(shadowMapResolution, shadowDirectives); + this.shadowRenderTargets = new ShadowRenderTargets(this, shadowMapResolution, shadowDirectives); } return shadowRenderTargets; }; - PatchedShaderPrinter.resetPrintState(); + ShaderPrinter.resetPrintState(); - this.prepareRenderer = new CompositeRenderer(this, programs.getPackDirectives(), programs.getPrepare(), programs.getPrepareCompute(), renderTargets, + this.prepareRenderer = new CompositeRenderer(this, programs.getPackDirectives(), programs.getPrepare(), programs.getPrepareCompute(), renderTargets, null, customTextureManager.getNoiseTexture(), updateNotifier, centerDepthSampler, flipper, shadowTargetsSupplier, TextureStage.PREPARE, customTextureManager.getCustomTextureIdMap(TextureStage.PREPARE), - customTextureManager.getIrisCustomTextures(), programs.getPackDirectives().getExplicitFlips("prepare_pre"), customUniforms); + customTextureManager.getIrisCustomTextures(), null, programs.getPackDirectives().getExplicitFlips("prepare_pre"), customUniforms); flippedAfterPrepare = flipper.snapshot(); - this.deferredRenderer = new CompositeRenderer(this, programs.getPackDirectives(), programs.getDeferred(), programs.getDeferredCompute(), renderTargets, + this.deferredRenderer = new CompositeRenderer(this, programs.getPackDirectives(), programs.getDeferred(), programs.getDeferredCompute(), renderTargets, null, customTextureManager.getNoiseTexture(), updateNotifier, centerDepthSampler, flipper, shadowTargetsSupplier, - TextureStage.DEFERRED, customTextureManager.getCustomTextureIdMap(TextureStage.DEFERRED), customTextureManager.getIrisCustomTextures(), + TextureStage.DEFERRED, customTextureManager.getCustomTextureIdMap(TextureStage.DEFERRED), customTextureManager.getIrisCustomTextures(), null, programs.getPackDirectives().getExplicitFlips("deferred_pre"), customUniforms); flippedAfterTranslucent = flipper.snapshot(); - this.compositeRenderer = new CompositeRenderer(this, programs.getPackDirectives(), programs.getComposite(), programs.getCompositeCompute(), renderTargets, + this.compositeRenderer = new CompositeRenderer(this, programs.getPackDirectives(), programs.getComposite(), programs.getCompositeCompute(), renderTargets, null, customTextureManager.getNoiseTexture(), updateNotifier, centerDepthSampler, flipper, shadowTargetsSupplier, TextureStage.COMPOSITE_AND_FINAL, customTextureManager.getCustomTextureIdMap(TextureStage.COMPOSITE_AND_FINAL), - customTextureManager.getIrisCustomTextures(), programs.getPackDirectives().getExplicitFlips("composite_pre"), customUniforms); - this.finalPassRenderer = new FinalPassRenderer(this, programs, renderTargets, customTextureManager.getNoiseTexture(), updateNotifier, flipper.snapshot(), + customTextureManager.getIrisCustomTextures(), null, programs.getPackDirectives().getExplicitFlips("composite_pre"), customUniforms); + this.finalPassRenderer = new FinalPassRenderer(this, programs, renderTargets, customTextureManager.getNoiseTexture(), null, updateNotifier, flipper.snapshot(), centerDepthSampler, shadowTargetsSupplier, - customTextureManager.getCustomTextureIdMap(TextureStage.COMPOSITE_AND_FINAL), customTextureManager.getIrisCustomTextures(), - this.compositeRenderer.getFlippedAtLeastOnceFinal(), customUniforms); + customTextureManager.getCustomTextureIdMap(TextureStage.COMPOSITE_AND_FINAL), customTextureManager.getIrisCustomTextures(), null, + this.compositeRenderer.getFlippedAtLeastOnceFinal(), customUniforms); // [(textured=false,lightmap=false), (textured=true,lightmap=false), (textured=true,lightmap=true)] ProgramId[] ids = new ProgramId[] { @@ -366,7 +361,7 @@ public DeferredWorldRenderingPipeline(ProgramSet programs) { }); if (shadowRenderTargets == null && shadowDirectives.isShadowEnabled() == OptionalBoolean.TRUE) { - shadowRenderTargets = new ShadowRenderTargets(shadowMapResolution, shadowDirectives); + shadowRenderTargets = new ShadowRenderTargets(this, shadowMapResolution, shadowDirectives); } if (shadowRenderTargets != null) { @@ -376,10 +371,10 @@ public DeferredWorldRenderingPipeline(ProgramSet programs) { if (programs.getPackDirectives().getShadowDirectives().isShadowEnabled().orElse(true)) { Program shadowProgram = table.match(RenderCondition.SHADOW, new InputAvailability(true, true, true)).getProgram(); - this.shadowCompositeRenderer = new ShadowCompositeRenderer(this, programs.getPackDirectives(), programs.getShadowComposite(), programs.getShadowCompCompute(), this.shadowRenderTargets, customTextureManager.getNoiseTexture(), updateNotifier, - customTextureManager.getCustomTextureIdMap(TextureStage.SHADOWCOMP), programs.getPackDirectives().getExplicitFlips("shadowcomp_pre"), customTextureManager.getIrisCustomTextures(), customUniforms); + this.shadowCompositeRenderer = new ShadowCompositeRenderer(this, programs.getPackDirectives(), programs.getShadowComposite(), programs.getShadowCompCompute(), this.shadowRenderTargets, null, customTextureManager.getNoiseTexture(), updateNotifier, + customTextureManager.getCustomTextureIdMap(TextureStage.SHADOWCOMP), null, programs.getPackDirectives().getExplicitFlips("shadowcomp_pre"), customTextureManager.getIrisCustomTextures(), customUniforms); this.shadowRenderer = new ShadowRenderer(programs.getShadow().orElse(null), - programs.getPackDirectives(), shadowRenderTargets, shadowCompositeRenderer, customUniforms); + programs.getPackDirectives(), shadowRenderTargets, shadowCompositeRenderer, customUniforms, false); } else { shadowCompositeRenderer = null; shadowRenderer = null; @@ -412,7 +407,7 @@ public DeferredWorldRenderingPipeline(ProgramSet programs) { IrisSamplers.addNoiseSampler(customTextureSamplerInterceptor, customTextureManager.getNoiseTexture()); if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, Objects.requireNonNull(shadowRenderTargets), null); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, Objects.requireNonNull(shadowRenderTargets), null, false); } return builder.build(); @@ -442,7 +437,7 @@ public DeferredWorldRenderingPipeline(ProgramSet programs) { // Only initialize these samplers if the shadow map renderer exists. // Otherwise, this program shouldn't be used at all? if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, Objects.requireNonNull(shadowRenderTargets), null); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, Objects.requireNonNull(shadowRenderTargets), null, false); } return builder.build(); @@ -491,6 +486,11 @@ public boolean shouldDisableDirectionalShading() { return !oldLighting; } + @Override + public boolean shouldDisableFrustumCulling() { + return false; + } + @Override public CloudSetting getCloudSetting() { return cloudSetting; @@ -531,11 +531,21 @@ public boolean allowConcurrentCompute() { return allowConcurrentCompute; } + @Override + public boolean hasFeature(FeatureFlags flags) { + return false; + } + @Override public float getSunPathRotation() { return sunPathRotation; } + @Override + public DHCompat getDHCompat() { + return null; + } + private RenderCondition getCondition(WorldRenderingPhase phase) { if (isRenderingShadow) { return RenderCondition.SHADOW; @@ -643,21 +653,9 @@ private Pass createDefaultPass() { private Pass createPass(ProgramSource source, InputAvailability availability, boolean shadow, ProgramId id) { // TODO: Properly handle empty shaders? - Map transformed = TransformPatcher.patchAttributes( - source.getVertexSource().orElseThrow(NullPointerException::new), - source.getGeometrySource().orElse(null), - source.getFragmentSource().orElseThrow(NullPointerException::new), - availability, customTextureMap); - String vertex = transformed.get(PatchShaderType.VERTEX); - String geometry = transformed.get(PatchShaderType.GEOMETRY); - String fragment = transformed.get(PatchShaderType.FRAGMENT); - - PatchedShaderPrinter.debugPatchedShaders(source.getName(), vertex, geometry, fragment); - ProgramBuilder builder = ProgramBuilder.begin(source.getName(), vertex, geometry, fragment, - IrisSamplers.WORLD_RESERVED_TEXTURE_UNITS); - return createPassInner(builder, source.getParent().getPack().getIdMap(), source.getDirectives(), source.getParent().getPackDirectives(), availability, shadow, id); + return createPassInner(null, source.getParent().getPack().getIdMap(), source.getDirectives(), source.getParent().getPackDirectives(), availability, shadow, id); } private Pass createPassInner(ProgramBuilder builder, IdMap map, ProgramDirectives programDirectives, @@ -702,7 +700,7 @@ private Pass createPassInner(ProgramBuilder builder, IdMap map, ProgramDirective } if (shadowRenderTargets != null) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowRenderTargets, null); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowRenderTargets, null, false); IrisImages.addShadowColorImages(builder, shadowRenderTargets, null); } } @@ -905,6 +903,11 @@ public void destroy() { // Destroy custom textures and the static samplers (normals, specular, and noise) customTextureManager.destroy(); whitePixel.releaseId(); + + if (shaderStorageBufferHolder != null) { + // Destroy shader storage buffer objects + shaderStorageBufferHolder.destroyBuffers(); + } } private static void destroyPasses(ProgramTable table) { @@ -1052,7 +1055,7 @@ private ComputeProgram[] createShadowComputes(ComputeSource[] compute, ProgramSe if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { if (shadowRenderTargets != null) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowRenderTargets, null); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowRenderTargets, null, false); IrisImages.addShadowColorImages(builder, shadowRenderTargets, null); } } @@ -1062,7 +1065,7 @@ private ComputeProgram[] createShadowComputes(ComputeSource[] compute, ProgramSe // tell the customUniforms that those locations belong to this pass this.customUniforms.mapholderToPass(builder, programs[i]); - programs[i].setWorkGroupInfo(source.getWorkGroupRelative(), source.getWorkGroups()); + programs[i].setWorkGroupInfo(source.getWorkGroupRelative(), source.getWorkGroups(), null); } } @@ -1156,6 +1159,11 @@ public OptionalInt getForcedShadowRenderDistanceChunksForDisplay() { private boolean isRenderingWorld = false; private boolean isRenderingFullScreenPass = false; + @Override + public void onShadowBufferChange() { + + } + @Override public void beginLevelRendering() { isRenderingFullScreenPass = false; @@ -1178,6 +1186,13 @@ public void beginLevelRendering() { throw new IllegalStateException("Called beginLevelRendering but level rendering appears to still be in progress?"); } + if (showSSBOError) { + showSSBOError = false; + if (Minecraft.getInstance().player != null) { + Minecraft.getInstance().player.displayClientMessage(new TranslatableComponent("iris.shaders.ssbofailure"), false); + } + } + updateNotifier.onNewFrame(); // Get ready for world rendering prepareRenderTargets(); @@ -1232,6 +1247,11 @@ public void finalizeLevelRendering() { isRenderingFullScreenPass = false; } + @Override + public void finalizeGameRendering() { + + } + @Override public SodiumTerrainPipeline getSodiumTerrainPipeline() { return sodiumTerrainPipeline; diff --git a/src/main/java/net/coderbot/iris/pipeline/FixedFunctionWorldRenderingPipeline.java b/src/main/java/net/coderbot/iris/pipeline/FixedFunctionWorldRenderingPipeline.java index 6220c44146..e4346a5ce4 100644 --- a/src/main/java/net/coderbot/iris/pipeline/FixedFunctionWorldRenderingPipeline.java +++ b/src/main/java/net/coderbot/iris/pipeline/FixedFunctionWorldRenderingPipeline.java @@ -4,6 +4,8 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.coderbot.iris.compat.dh.DHCompat; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gbuffer_overrides.matching.InputAvailability; import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition; import net.coderbot.iris.gbuffer_overrides.state.RenderTargetStateListener; @@ -24,11 +26,18 @@ public class FixedFunctionWorldRenderingPipeline implements WorldRenderingPipeli public FixedFunctionWorldRenderingPipeline() { BlockRenderingSettings.INSTANCE.setDisableDirectionalShading(shouldDisableDirectionalShading()); BlockRenderingSettings.INSTANCE.setUseSeparateAo(false); + BlockRenderingSettings.INSTANCE.setSeparateEntityDraws(false); BlockRenderingSettings.INSTANCE.setAmbientOcclusionLevel(1.0f); BlockRenderingSettings.INSTANCE.setUseExtendedVertexFormat(false); + BlockRenderingSettings.INSTANCE.setVoxelizeLightBlocks(false); BlockRenderingSettings.INSTANCE.setBlockTypeIds(null); } + @Override + public void onShadowBufferChange() { + + } + @Override public void beginLevelRendering() { // Use the default Minecraft framebuffer and ensure that no programs are in use @@ -131,6 +140,11 @@ public void finalizeLevelRendering() { // stub: nothing to do here } + @Override + public void finalizeGameRendering() { + // stub: nothing to do here + } + @Override public void destroy() { // stub: nothing to do here @@ -158,6 +172,11 @@ public boolean shouldDisableDirectionalShading() { return false; } + @Override + public boolean shouldDisableFrustumCulling() { + return false; + } + @Override public CloudSetting getCloudSetting() { return CloudSetting.DEFAULT; @@ -198,9 +217,19 @@ public boolean allowConcurrentCompute() { return false; } + @Override + public boolean hasFeature(FeatureFlags flags) { + return false; + } + @Override public float getSunPathRotation() { // No sun tilt return 0; } + + @Override + public DHCompat getDHCompat() { + return null; + } } diff --git a/src/main/java/net/coderbot/iris/pipeline/HandRenderer.java b/src/main/java/net/coderbot/iris/pipeline/HandRenderer.java index 1e21ea73c8..2ed5620be4 100644 --- a/src/main/java/net/coderbot/iris/pipeline/HandRenderer.java +++ b/src/main/java/net/coderbot/iris/pipeline/HandRenderer.java @@ -87,16 +87,17 @@ public void renderSolid(PoseStack poseStack, float tickDelta, Camera camera, Gam renderingSolid = true; - Minecraft.getInstance().getItemInHandRenderer().renderHandsWithItems(tickDelta, poseStack, bufferSource, Minecraft.getInstance().player, Minecraft.getInstance().getEntityRenderDispatcher().getPackedLightCoords(camera.getEntity(), tickDelta)); + gameRenderer.itemInHandRenderer.renderHandsWithItems(tickDelta, poseStack, bufferSource.getUnflushableWrapper(), Minecraft.getInstance().player, Minecraft.getInstance().getEntityRenderDispatcher().getPackedLightCoords(camera.getEntity(), tickDelta)); Minecraft.getInstance().getProfiler().pop(); + bufferSource.readyUp(); + bufferSource.endBatch(); + gameRenderer.resetProjectionMatrix(CapturedRenderingState.INSTANCE.getGbufferProjection()); poseStack.popPose(); - bufferSource.endBatch(); - renderingSolid = false; pipeline.setPhase(WorldRenderingPhase.NONE); diff --git a/src/main/java/net/coderbot/iris/pipeline/LightningHandler.java b/src/main/java/net/coderbot/iris/pipeline/LightningHandler.java new file mode 100644 index 0000000000..82945958b9 --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/LightningHandler.java @@ -0,0 +1,29 @@ +package net.coderbot.iris.pipeline; + +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.coderbot.iris.layer.InnerWrappedRenderType; +import net.coderbot.iris.layer.LightningRenderStateShard; +import net.coderbot.iris.layer.OuterWrappedRenderType; +import net.minecraft.client.renderer.RenderType; + +public class LightningHandler extends RenderType { + public static final RenderType IRIS_LIGHTNING = new InnerWrappedRenderType("iris_lightning2", RenderType.create( + "iris_lightning", + DefaultVertexFormat.POSITION_COLOR, + VertexFormat.Mode.QUADS, + 256, + false, + true, + RenderType.CompositeState.builder() + .setShaderState(RENDERTYPE_LIGHTNING_SHADER) + .setWriteMaskState(COLOR_DEPTH_WRITE) + .setTransparencyState(LIGHTNING_TRANSPARENCY) + .setOutputState(WEATHER_TARGET) + .createCompositeState(false) + ), new LightningRenderStateShard()); + + public LightningHandler(String pRenderType0, VertexFormat pVertexFormat1, VertexFormat.Mode pVertexFormat$Mode2, int pInt3, boolean pBoolean4, boolean pBoolean5, Runnable pRunnable6, Runnable pRunnable7) { + super(pRenderType0, pVertexFormat1, pVertexFormat$Mode2, pInt3, pBoolean4, pBoolean5, pRunnable6, pRunnable7); + } +} diff --git a/src/main/java/net/coderbot/iris/pipeline/PatchedShaderPrinter.java b/src/main/java/net/coderbot/iris/pipeline/PatchedShaderPrinter.java deleted file mode 100644 index fff50b766d..0000000000 --- a/src/main/java/net/coderbot/iris/pipeline/PatchedShaderPrinter.java +++ /dev/null @@ -1,75 +0,0 @@ -package net.coderbot.iris.pipeline; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.stream.Stream; - -import net.coderbot.iris.Iris; -import net.minecraftforge.fml.loading.FMLLoader; -import net.minecraftforge.fml.loading.FMLPaths; - -/** - * Static class that deals with printing the patched_shader folder. - */ -public class PatchedShaderPrinter { - private static boolean outputLocationCleared = false; - private static int programCounter = 0; - public static final boolean prettyPrintShaders = !FMLLoader.isProduction() - || System.getProperty("iris.prettyPrintShaders", "false").equals("true"); - - public static void resetPrintState() { - outputLocationCleared = false; - programCounter = 0; - } - - public static void debugPatchedShaders(String name, String vertex, String geometry, String fragment, String json) { - if (prettyPrintShaders) { - final Path debugOutDir = FMLPaths.GAMEDIR.get().resolve("patched_shaders"); - if (!outputLocationCleared) { - try { - if (Files.exists(debugOutDir)) { - try (Stream stream = Files.list(debugOutDir)) { - stream.forEach(path -> { - try { - Files.delete(path); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } - } - - Files.createDirectories(debugOutDir); - } catch (IOException e) { - Iris.logger.warn("Failed to initialize debug patched shader source location", e); - } - outputLocationCleared = true; - } - - try { - programCounter++; - String prefix = String.format("%03d_", programCounter); - if (vertex != null) { - Files.write(debugOutDir.resolve(prefix + name + ".vsh"), vertex.getBytes(StandardCharsets.UTF_8)); - } - if (geometry != null) { - Files.write(debugOutDir.resolve(prefix + name + ".gsh"), geometry.getBytes(StandardCharsets.UTF_8)); - } - if (fragment != null) { - Files.write(debugOutDir.resolve(prefix + name + ".fsh"), fragment.getBytes(StandardCharsets.UTF_8)); - } - if (json != null) { - Files.write(debugOutDir.resolve(prefix + name + ".json"), json.getBytes(StandardCharsets.UTF_8)); - } - } catch (IOException e) { - Iris.logger.warn("Failed to write debug patched shader source", e); - } - } - } - - public static void debugPatchedShaders(String name, String vertex, String geometry, String fragment) { - debugPatchedShaders(name, vertex, geometry, fragment, null); - } -} diff --git a/src/main/java/net/coderbot/iris/pipeline/PipelineManager.java b/src/main/java/net/coderbot/iris/pipeline/PipelineManager.java index 91e4efa74a..5deec8b654 100644 --- a/src/main/java/net/coderbot/iris/pipeline/PipelineManager.java +++ b/src/main/java/net/coderbot/iris/pipeline/PipelineManager.java @@ -4,6 +4,7 @@ import net.coderbot.iris.Iris; import net.coderbot.iris.block_rendering.BlockRenderingSettings; import net.coderbot.iris.shaderpack.DimensionId; +import net.coderbot.iris.shaderpack.materialmap.NamespacedId; import net.coderbot.iris.uniforms.SystemTimeUniforms; import net.minecraft.client.Minecraft; import org.jetbrains.annotations.Nullable; @@ -16,16 +17,16 @@ public class PipelineManager { private static PipelineManager instance; - private final Function pipelineFactory; - private final Map pipelinesPerDimension = new HashMap<>(); + private final Function pipelineFactory; + private final Map pipelinesPerDimension = new HashMap<>(); private WorldRenderingPipeline pipeline = new FixedFunctionWorldRenderingPipeline(); private int versionCounterForSodiumShaderReload = 0; - public PipelineManager(Function pipelineFactory) { + public PipelineManager(Function pipelineFactory) { this.pipelineFactory = pipelineFactory; } - public WorldRenderingPipeline preparePipeline(DimensionId currentDimension) { + public WorldRenderingPipeline preparePipeline(NamespacedId currentDimension) { if (!pipelinesPerDimension.containsKey(currentDimension)) { SystemTimeUniforms.COUNTER.reset(); SystemTimeUniforms.TIMER.reset(); diff --git a/src/main/java/net/coderbot/iris/pipeline/ShaderAccess.java b/src/main/java/net/coderbot/iris/pipeline/ShaderAccess.java new file mode 100644 index 0000000000..eb9993ebe0 --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/ShaderAccess.java @@ -0,0 +1,23 @@ +package net.coderbot.iris.pipeline; + +import net.coderbot.iris.Iris; +import net.coderbot.iris.pipeline.newshader.CoreWorldRenderingPipeline; +import net.coderbot.iris.pipeline.newshader.ShaderKey; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.ShaderInstance; + +public class ShaderAccess { + public static ShaderInstance getParticleTranslucentShader() { + WorldRenderingPipeline pipeline = Iris.getPipelineManager().getPipelineNullable(); + + if (pipeline instanceof CoreWorldRenderingPipeline) { + ShaderInstance override = ((CoreWorldRenderingPipeline) pipeline).getShaderMap().getShader(ShaderKey.PARTICLES_TRANS); + + if (override != null) { + return override; + } + } + + return GameRenderer.getParticleShader(); + } +} diff --git a/src/main/java/net/coderbot/iris/pipeline/ShaderPrinter.java b/src/main/java/net/coderbot/iris/pipeline/ShaderPrinter.java new file mode 100644 index 0000000000..da426bdb90 --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/ShaderPrinter.java @@ -0,0 +1,127 @@ +package net.coderbot.iris.pipeline; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import net.coderbot.iris.Iris; +import net.coderbot.iris.pipeline.transform.PatchShaderType; +import net.minecraftforge.fml.loading.FMLPaths; + +/** + * Static class that deals with printing the patched_shader folder. + */ +public class ShaderPrinter { + private static boolean outputLocationCleared = false; + private static int programCounter = 0; + private static final Path debugOutDir = FMLPaths.GAMEDIR.get().resolve("patched_shaders"); + + public static void resetPrintState() { + outputLocationCleared = false; + programCounter = 0; + } + + public static ProgramPrintBuilder printProgram(String name) { + return new ProgramPrintBuilder(name); + } + + public static class ProgramPrintBuilder { + // copy the debug flag if for some reason the debug flag changes during the + // lifetime of this builder object + private final boolean isActive = Iris.getIrisConfig().areDebugOptionsEnabled(); + + // the prefix is created at instantiation time so that all sources attached to + // this builder use the same counter prefix + private final String prefix = isActive ? String.format("%03d_", ++programCounter) : null; + + // the prefix and the sources list aren't created if debug is disabled + private final List sources = isActive ? new ArrayList<>(PatchShaderType.values().length * 2) : null; + + private String name; + private boolean done = false; // makes the print function idempotent + + public ProgramPrintBuilder(String name) { + setName(name); + } + + public ProgramPrintBuilder setName(String name) { + this.name = name; + return this; + } + + private void addItem(String extension, String content) { + if (content != null && sources != null) { + sources.add(prefix + name + extension); + sources.add(content); + } + } + + public ProgramPrintBuilder addSource(PatchShaderType type, String source) { + if (sources == null) { + return this; + } + addItem(type.extension, source); + return this; + } + + public ProgramPrintBuilder addSources(Map sources) { + if (sources == null) { + return this; + } + for (Map.Entry entry : sources.entrySet()) { + addSource(entry.getKey(), entry.getValue()); + } + return this; + } + + public ProgramPrintBuilder addJson(String json) { + if (sources == null) { + return this; + } + addItem(".json", json); + return this; + } + + public void print() { + if (done) { + return; + } + done = true; + if (isActive) { + if (!outputLocationCleared) { + try { + if (Files.exists(debugOutDir)) { + try (Stream stream = Files.list(debugOutDir)) { + stream.forEach(path -> { + try { + Files.delete(path); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } + } + + Files.createDirectories(debugOutDir); + } catch (IOException e) { + Iris.logger.warn("Failed to initialize debug patched shader source location", e); + } + outputLocationCleared = true; + } + + try { + for (int i = 0; i < sources.size(); i += 2) { + Files.write(debugOutDir.resolve(sources.get(i)), sources.get(i + 1).getBytes(StandardCharsets.UTF_8)); + } + } catch (IOException e) { + Iris.logger.warn("Failed to write debug patched shader source", e); + } + } + } + } +} diff --git a/src/main/java/net/coderbot/iris/pipeline/ShadowRenderer.java b/src/main/java/net/coderbot/iris/pipeline/ShadowRenderer.java index e01901a3fc..a5bdb49e19 100644 --- a/src/main/java/net/coderbot/iris/pipeline/ShadowRenderer.java +++ b/src/main/java/net/coderbot/iris/pipeline/ShadowRenderer.java @@ -4,8 +4,10 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix4f; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import net.coderbot.batchedentityrendering.impl.BatchingDebugMessageHelper; import net.coderbot.batchedentityrendering.impl.DrawCallTrackingRenderBuffers; +import net.coderbot.batchedentityrendering.impl.FullyBufferedMultiBufferSource; import net.coderbot.batchedentityrendering.impl.MemoryTrackingRenderBuffers; import net.coderbot.batchedentityrendering.impl.RenderBuffersExt; import net.coderbot.iris.Iris; @@ -19,6 +21,7 @@ import net.coderbot.iris.shaderpack.PackDirectives; import net.coderbot.iris.shaderpack.PackShadowDirectives; import net.coderbot.iris.shaderpack.ProgramSource; +import net.coderbot.iris.shaderpack.ShadowCullState; import net.coderbot.iris.shadows.ShadowMatrices; import net.coderbot.iris.shadows.CullingDataCache; import net.coderbot.iris.shadows.Matrix4fAccess; @@ -28,6 +31,7 @@ import net.coderbot.iris.shadows.frustum.CullEverythingFrustum; import net.coderbot.iris.shadows.frustum.FrustumHolder; import net.coderbot.iris.shadows.frustum.advanced.AdvancedShadowCullingFrustum; +import net.coderbot.iris.shadows.frustum.advanced.ReversedAdvancedShadowCullingFrustum; import net.coderbot.iris.shadows.frustum.fallback.BoxCullingFrustum; import net.coderbot.iris.shadows.frustum.fallback.NonCullingFrustum; import net.coderbot.iris.uniforms.custom.CustomUniforms; @@ -64,6 +68,7 @@ public class ShadowRenderer { public static List visibleBlockEntities; private final float halfPlaneLength; + private final float voxelDistance; private final float renderDistanceMultiplier; private final float entityShadowDistanceMultiplier; private final int resolution; @@ -72,7 +77,7 @@ public class ShadowRenderer { public static Matrix4f MODELVIEW; private final ShadowRenderTargets targets; - private final OptionalBoolean packCullingState; + private final ShadowCullState packCullingState; private final ShadowCompositeRenderer compositeRenderer; private boolean packHasVoxelization; private final boolean shouldRenderTerrain; @@ -92,15 +97,19 @@ public class ShadowRenderer { private int renderedShadowBlockEntities = 0; private final CustomUniforms customUniforms; + private final boolean separateHardwareSamplers; public ShadowRenderer(ProgramSource shadow, PackDirectives directives, - ShadowRenderTargets shadowRenderTargets, ShadowCompositeRenderer compositeRenderer, CustomUniforms customUniforms) { + ShadowRenderTargets shadowRenderTargets, ShadowCompositeRenderer compositeRenderer, CustomUniforms customUniforms, boolean separateHardwareSamplers) { this.customUniforms = customUniforms; + this.separateHardwareSamplers = separateHardwareSamplers; + final PackShadowDirectives shadowDirectives = directives.getShadowDirectives(); this.halfPlaneLength = shadowDirectives.getDistance(); + this.voxelDistance = shadowDirectives.getVoxelDistance(); this.renderDistanceMultiplier = shadowDirectives.getDistanceRenderMul(); this.entityShadowDistanceMultiplier = shadowDirectives.getEntityShadowDistanceMul(); this.resolution = shadowDirectives.getResolution(); @@ -128,7 +137,7 @@ public ShadowRenderer(ProgramSource shadow, PackDirectives directives, this.packCullingState = shadowDirectives.getCullingState(); } else { this.packHasVoxelization = false; - this.packCullingState = OptionalBoolean.DEFAULT; + this.packCullingState = ShadowCullState.DEFAULT; } this.sunPathRotation = directives.getSunPathRotation(); @@ -195,7 +204,7 @@ private void configureSamplingSettings(PackShadowDirectives shadowDirectives) { final ImmutableList depthSamplingSettings = shadowDirectives.getDepthSamplingSettings(); - final ImmutableList colorSamplingSettings = + final Int2ObjectMap colorSamplingSettings = shadowDirectives.getColorSamplingSettings(); RenderSystem.activeTexture(GL20C.GL_TEXTURE4); @@ -204,17 +213,19 @@ private void configureSamplingSettings(PackShadowDirectives shadowDirectives) { configureDepthSampler(targets.getDepthTextureNoTranslucents().getTextureId(), depthSamplingSettings.get(1)); - for (int i = 0; i < colorSamplingSettings.size(); i++) { - int glTextureId = targets.get(i).getMainTexture(); + for (int i = 0; i < targets.getNumColorTextures(); i++) { + if (targets.get(i) != null) { + int glTextureId = targets.get(i).getMainTexture(); - configureSampler(glTextureId, colorSamplingSettings.get(i)); + configureSampler(glTextureId, colorSamplingSettings.computeIfAbsent(i, a -> new PackShadowDirectives.SamplingSettings())); + } } RenderSystem.activeTexture(GL20C.GL_TEXTURE0); } private void configureDepthSampler(int glTextureId, PackShadowDirectives.DepthSamplingSettings settings) { - if (settings.getHardwareFiltering()) { + if (settings.getHardwareFiltering() && !separateHardwareSamplers) { // We have to do this or else shadow hardware filtering breaks entirely! IrisRenderSystem.texParameteri(glTextureId, GL20C.GL_TEXTURE_2D, GL20C.GL_TEXTURE_COMPARE_MODE, GL30C.GL_COMPARE_REF_TO_TEXTURE); } @@ -263,12 +274,12 @@ private FrustumHolder createShadowFrustum(float renderMultiplier, FrustumHolder // TODO: Cull entities / block entities with Advanced Frustum Culling even if voxelization is detected. String distanceInfo; String cullingInfo; - if ((packCullingState == OptionalBoolean.FALSE || packHasVoxelization) && packCullingState != OptionalBoolean.TRUE) { + if ((packCullingState == ShadowCullState.DEFAULT && packHasVoxelization) || packCullingState == ShadowCullState.DISTANCE) { double distance = halfPlaneLength * renderMultiplier; String reason; - if (packCullingState == OptionalBoolean.FALSE) { + if (packCullingState == ShadowCullState.DISTANCE) { reason = "(set by shader pack)"; } else /*if (packHasVoxelization)*/ { reason = "(voxelization detected)"; @@ -276,7 +287,7 @@ private FrustumHolder createShadowFrustum(float renderMultiplier, FrustumHolder if (distance <= 0 || distance > Minecraft.getInstance().options.getEffectiveRenderDistance() * 16) { distanceInfo = "render distance = " + Minecraft.getInstance().options.getEffectiveRenderDistance() * 16 - + " blocks "; + + " blocks "; distanceInfo += Minecraft.getInstance().isLocalServer() ? "(capped by normal render distance)" : "(capped by normal/server render distance)"; cullingInfo = "disabled " + reason; return holder.setInfo(new NonCullingFrustum(), distanceInfo, cullingInfo); @@ -289,7 +300,12 @@ private FrustumHolder createShadowFrustum(float renderMultiplier, FrustumHolder } else { BoxCuller boxCuller; - double distance = halfPlaneLength * renderMultiplier; + boolean isReversed = packCullingState == ShadowCullState.REVERSED; + + // Assume render multiplier is meant to be 1 if reversed culling is on + if (isReversed && renderMultiplier < 0) renderMultiplier = 1.0f; + + double distance = (isReversed ? voxelDistance : halfPlaneLength) * renderMultiplier; String setter = "(set by shader pack)"; if (renderMultiplier < 0) { @@ -297,15 +313,15 @@ private FrustumHolder createShadowFrustum(float renderMultiplier, FrustumHolder setter = "(set by user)"; } - if (distance >= Minecraft.getInstance().options.renderDistance * 16) { + if (distance >= Minecraft.getInstance().options.renderDistance * 16 && !isReversed) { distanceInfo = "render distance = " + Minecraft.getInstance().options.getEffectiveRenderDistance() * 16 - + " blocks "; + + " blocks "; distanceInfo += Minecraft.getInstance().isLocalServer() ? "(capped by normal render distance)" : "(capped by normal/server render distance)"; boxCuller = null; } else { distanceInfo = distance + " blocks " + setter; - if (distance == 0.0) { + if (distance == 0.0 && !isReversed) { cullingInfo = "no shadows rendered"; holder.setInfo(new CullEverythingFrustum(), distanceInfo, cullingInfo); } @@ -313,7 +329,7 @@ private FrustumHolder createShadowFrustum(float renderMultiplier, FrustumHolder boxCuller = new BoxCuller(distance); } - cullingInfo = "Advanced Frustum Culling enabled"; + cullingInfo = (isReversed ? "Reversed" : "Advanced") + " Frustum Culling enabled"; Vector4f shadowLightPosition = new CelestialUniforms(sunPathRotation).getShadowLightPositionInWorldSpace(); @@ -322,9 +338,13 @@ private FrustumHolder createShadowFrustum(float renderMultiplier, FrustumHolder shadowLightVectorFromOrigin.normalize(); - return holder.setInfo(new AdvancedShadowCullingFrustum(((Matrix4fAccess) (Object) CapturedRenderingState.INSTANCE.getGbufferModelView()).convertToJOML(), - ((Matrix4fAccess) (Object) CapturedRenderingState.INSTANCE.getGbufferProjection()).convertToJOML(), shadowLightVectorFromOrigin, boxCuller), distanceInfo, cullingInfo); - + if (isReversed) { + return holder.setInfo(new ReversedAdvancedShadowCullingFrustum(((Matrix4fAccess) (Object) CapturedRenderingState.INSTANCE.getGbufferModelView()).convertToJOML(), + ((Matrix4fAccess) (Object) CapturedRenderingState.INSTANCE.getGbufferProjection()).convertToJOML(), shadowLightVectorFromOrigin, boxCuller, new BoxCuller(halfPlaneLength * renderMultiplier)), distanceInfo, cullingInfo); + } else { + return holder.setInfo(new AdvancedShadowCullingFrustum(((Matrix4fAccess) (Object) CapturedRenderingState.INSTANCE.getGbufferModelView()).convertToJOML(), + ((Matrix4fAccess) (Object) CapturedRenderingState.INSTANCE.getGbufferProjection()).convertToJOML(), shadowLightVectorFromOrigin, boxCuller), distanceInfo, cullingInfo); + } } return holder; @@ -336,6 +356,10 @@ public void setupShadowViewport() { } public void renderShadows(LevelRendererAccessor levelRenderer, Camera playerCamera) { + if (IrisVideoSettings.getOverriddenShadowDistance(IrisVideoSettings.shadowDistance) == 0) { + return; + } + Minecraft client = Minecraft.getInstance(); levelRenderer.getLevel().getProfiler().popPush("shadows"); @@ -485,9 +509,11 @@ public void renderShadows(LevelRendererAccessor levelRenderer, Camera playerCame levelRenderer.getLevel().getProfiler().popPush("draw entities"); - // NB: Don't try to draw the translucent parts of entities afterwards. It'll cause problems since some + // NB: Don't try to draw the translucent parts of entities afterwards in the shadow pass. It'll cause problems since some // shader packs assume that everything drawn afterwards is actually translucent and should cast a colored // shadow... + if (bufferSource instanceof FullyBufferedMultiBufferSource fullyBufferedMultiBufferSource) fullyBufferedMultiBufferSource.readyUp(); + bufferSource.endBatch(); copyPreTranslucentDepth(levelRenderer); @@ -609,6 +635,7 @@ private int renderPlayerEntity(LevelRendererAccessor levelRenderer, EntityRender int shadowEntities = 0; if (!dispatcher.shouldRender(player, frustum, cameraX, cameraY, cameraZ) || player.isSpectator()) { + levelRenderer.getLevel().getProfiler().pop(); return 0; } @@ -641,18 +668,29 @@ private void copyPreTranslucentDepth(LevelRendererAccessor levelRenderer) { targets.copyPreTranslucentDepth(); } - public void addDebugText(List messages) { - messages.add("[" + Iris.MODNAME + "] Shadow Maps: " + debugStringOverall); - messages.add("[" + Iris.MODNAME + "] Shadow Distance Terrain: " + terrainFrustumHolder.getDistanceInfo() + " Entity: " + entityFrustumHolder.getDistanceInfo()); - messages.add("[" + Iris.MODNAME + "] Shadow Culling Terrain: " + terrainFrustumHolder.getCullingInfo() + " Entity: " + entityFrustumHolder.getCullingInfo()); - messages.add("[" + Iris.MODNAME + "] Shadow Terrain: " + debugStringTerrain - + (shouldRenderTerrain ? "" : " (no terrain) ") + (shouldRenderTranslucent ? "" : "(no translucent)")); - messages.add("[" + Iris.MODNAME + "] Shadow Entities: " + getEntitiesDebugString()); - messages.add("[" + Iris.MODNAME + "] Shadow Block Entities: " + getBlockEntitiesDebugString()); - - if (buffers instanceof DrawCallTrackingRenderBuffers && (shouldRenderEntities || shouldRenderPlayer)) { - DrawCallTrackingRenderBuffers drawCallTracker = (DrawCallTrackingRenderBuffers) buffers; - messages.add("[" + Iris.MODNAME + "] Shadow Entity Batching: " + BatchingDebugMessageHelper.getDebugMessage(drawCallTracker)); + public void addDebugText(List messages) { + if (IrisVideoSettings.getOverriddenShadowDistance(IrisVideoSettings.shadowDistance) == 0) { + messages.add("[" + Iris.MODNAME + "] Shadow Maps: off, shadow distance 0"); + return; + } + + if (Iris.getIrisConfig().areDebugOptionsEnabled()) { + messages.add("[" + Iris.MODNAME + "] Shadow Maps: " + debugStringOverall); + messages.add("[" + Iris.MODNAME + "] Shadow Distance Terrain: " + terrainFrustumHolder.getDistanceInfo() + " Entity: " + entityFrustumHolder.getDistanceInfo()); + messages.add("[" + Iris.MODNAME + "] Shadow Culling Terrain: " + terrainFrustumHolder.getCullingInfo() + " Entity: " + entityFrustumHolder.getCullingInfo()); + messages.add("[" + Iris.MODNAME + "] Shadow Terrain: " + debugStringTerrain + + (shouldRenderTerrain ? "" : " (no terrain) ") + (shouldRenderTranslucent ? "" : "(no translucent)")); + messages.add("[" + Iris.MODNAME + "] Shadow Entities: " + getEntitiesDebugString()); + messages.add("[" + Iris.MODNAME + "] Shadow Block Entities: " + getBlockEntitiesDebugString()); + + if (buffers instanceof DrawCallTrackingRenderBuffers && (shouldRenderEntities || shouldRenderPlayer)) { + DrawCallTrackingRenderBuffers drawCallTracker = (DrawCallTrackingRenderBuffers) buffers; + messages.add("[" + Iris.MODNAME + "] Shadow Entity Batching: " + BatchingDebugMessageHelper.getDebugMessage(drawCallTracker)); + } + } else { + messages.add("[" + Iris.MODNAME + "] Shadow info: " + debugStringTerrain); + messages.add("[" + Iris.MODNAME + "] E: " + renderedShadowEntities); + messages.add("[" + Iris.MODNAME + "] BE: " + renderedShadowBlockEntities); } } diff --git a/src/main/java/net/coderbot/iris/pipeline/SodiumTerrainPipeline.java b/src/main/java/net/coderbot/iris/pipeline/SodiumTerrainPipeline.java index 213ad2d796..1b014fc10e 100644 --- a/src/main/java/net/coderbot/iris/pipeline/SodiumTerrainPipeline.java +++ b/src/main/java/net/coderbot/iris/pipeline/SodiumTerrainPipeline.java @@ -37,17 +37,29 @@ import net.coderbot.iris.uniforms.custom.CustomUniforms; public class SodiumTerrainPipeline { - Optional terrainVertex; - Optional terrainGeometry; - Optional terrainFragment; + Optional terrainSolidVertex; + Optional terrainSolidGeometry; + Optional terrainSolidTessControl; + Optional terrainSolidTessEval; + Optional terrainSolidFragment; + GlFramebuffer terrainSolidFramebuffer; + BlendModeOverride terrainSolidBlendOverride; + List terrainSolidBufferOverrides; + + Optional terrainCutoutVertex; + Optional terrainCutoutGeometry; + Optional terrainCutoutTessControl; + Optional terrainCutoutTessEval; Optional terrainCutoutFragment; - GlFramebuffer terrainFramebuffer; - BlendModeOverride terrainBlendOverride; - List terrainBufferOverrides; + GlFramebuffer terrainCutoutFramebuffer; + BlendModeOverride terrainCutoutBlendOverride; + List terrainCutoutBufferOverrides; Optional terrainCutoutAlpha; Optional translucentVertex; Optional translucentGeometry; + Optional translucentTessControl; + Optional translucentTessEval; Optional translucentFragment; GlFramebuffer translucentFramebuffer; BlendModeOverride translucentBlendOverride; @@ -56,6 +68,8 @@ public class SodiumTerrainPipeline { Optional shadowVertex; Optional shadowGeometry; + Optional shadowTessControl; + Optional shadowTessEval; Optional shadowFragment; Optional shadowCutoutFragment; GlFramebuffer shadowFramebuffer; @@ -82,20 +96,28 @@ public SodiumTerrainPipeline(WorldRenderingPipeline parent, ProgramSet programSe this.parent = Objects.requireNonNull(parent); this.customUniforms = customUniforms; - Optional terrainSource = first(programSet.getGbuffersTerrain(), programSet.getGbuffersTexturedLit(), programSet.getGbuffersTextured(), programSet.getGbuffersBasic()); - Optional translucentSource = first(programSet.getGbuffersWater(), terrainSource); + Optional terrainSolidSource = first(programSet.getGbuffersTerrainSolid(), programSet.getGbuffersTerrain(), programSet.getGbuffersTexturedLit(), programSet.getGbuffersTextured(), programSet.getGbuffersBasic()); + Optional terrainCutoutSource = first(programSet.getGbuffersTerrainCutout(), programSet.getGbuffersTerrain(), programSet.getGbuffersTexturedLit(), programSet.getGbuffersTextured(), programSet.getGbuffersBasic()); + Optional translucentSource = first(programSet.getGbuffersWater(), terrainCutoutSource); this.programSet = programSet; this.shadowFramebuffer = shadowFramebuffer; - terrainSource.ifPresent(sources -> terrainFramebuffer = targets.createGbufferFramebuffer(flippedAfterPrepare, + terrainSolidSource.ifPresent(sources -> terrainSolidFramebuffer = targets.createGbufferFramebuffer(flippedAfterPrepare, + sources.getDirectives().getDrawBuffers())); + + terrainCutoutSource.ifPresent(sources -> terrainCutoutFramebuffer = targets.createGbufferFramebuffer(flippedAfterPrepare, sources.getDirectives().getDrawBuffers())); translucentSource.ifPresent(sources -> translucentFramebuffer = targets.createGbufferFramebuffer(flippedAfterTranslucent, sources.getDirectives().getDrawBuffers())); - if (terrainFramebuffer == null) { - terrainFramebuffer = targets.createGbufferFramebuffer(flippedAfterPrepare, new int[] {0}); + if (terrainSolidFramebuffer == null) { + terrainSolidFramebuffer = targets.createGbufferFramebuffer(flippedAfterPrepare, new int[] {0}); + } + + if (terrainCutoutFramebuffer == null) { + terrainCutoutFramebuffer = targets.createGbufferFramebuffer(flippedAfterPrepare, new int[] {0}); } if (translucentFramebuffer == null) { @@ -110,22 +132,58 @@ public SodiumTerrainPipeline(WorldRenderingPipeline parent, ProgramSet programSe private static final Supplier> terrainCutoutDefault = () -> Optional.of(AlphaTests.ONE_TENTH_ALPHA); private static final Supplier> translucentDefault = () -> Optional.of(AlphaTest.ALWAYS); - private static final Supplier> shadowDefault = () -> Optional.of(AlphaTests.NON_ZERO_ALPHA); + private static final Supplier> shadowDefault = () -> Optional.of(AlphaTests.ONE_TENTH_ALPHA); public void patchShaders(ChunkVertexType vertexType) { ShaderAttributeInputs inputs = new ShaderAttributeInputs(true, true, false, true, true); - Optional terrainSource = first(programSet.getGbuffersTerrain(), programSet.getGbuffersTexturedLit(), programSet.getGbuffersTextured(), programSet.getGbuffersBasic()); - Optional translucentSource = first(programSet.getGbuffersWater(), terrainSource); + Optional terrainSolidSource = first(programSet.getGbuffersTerrainSolid(), programSet.getGbuffersTerrain(), programSet.getGbuffersTexturedLit(), programSet.getGbuffersTextured(), programSet.getGbuffersBasic()); + Optional terrainCutoutSource = first(programSet.getGbuffersTerrainCutout(), programSet.getGbuffersTerrain(), programSet.getGbuffersTexturedLit(), programSet.getGbuffersTextured(), programSet.getGbuffersBasic()); + Optional translucentSource = first(programSet.getGbuffersWater(), terrainCutoutSource); + + + terrainSolidSource.ifPresentOrElse(sources -> { + terrainSolidBlendOverride = sources.getDirectives().getBlendModeOverride().orElse(ProgramId.Terrain.getBlendModeOverride()); + terrainSolidBufferOverrides = new ArrayList<>(); + sources.getDirectives().getBufferBlendOverrides().forEach(information -> { + int index = Ints.indexOf(sources.getDirectives().getDrawBuffers(), information.getIndex()); + if (index > -1) { + terrainSolidBufferOverrides.add(new BufferBlendOverride(index, information.getBlendMode())); + } + }); + + Map transformed = TransformPatcher.patchSodium( + sources.getVertexSource().orElse(null), + sources.getGeometrySource().orElse(null), + sources.getTessControlSource().orElse(null), + sources.getTessEvalSource().orElse(null), + sources.getFragmentSource().orElse(null), + AlphaTest.ALWAYS, inputs, + vertexType.getPositionScale(), vertexType.getPositionOffset(), vertexType.getTextureScale(), parent.getTextureMap()); + terrainSolidVertex = Optional.ofNullable(transformed.get(PatchShaderType.VERTEX)); + terrainSolidGeometry = Optional.ofNullable(transformed.get(PatchShaderType.GEOMETRY)); + terrainSolidTessControl = Optional.ofNullable(transformed.get(PatchShaderType.TESS_CONTROL)); + terrainSolidTessEval = Optional.ofNullable(transformed.get(PatchShaderType.TESS_EVAL)); + terrainSolidFragment = Optional.ofNullable(transformed.get(PatchShaderType.FRAGMENT)); + ShaderPrinter.printProgram(sources.getName() + "_sodium_solid").addSources(transformed).print(); + }, () -> { + terrainSolidBlendOverride = null; + terrainSolidBufferOverrides = Collections.emptyList(); + terrainSolidVertex = Optional.empty(); + terrainSolidGeometry = Optional.empty(); + terrainSolidTessControl = Optional.empty(); + terrainSolidTessEval = Optional.empty(); + terrainSolidFragment = Optional.empty(); + }); - terrainSource.ifPresentOrElse(sources -> { - terrainBlendOverride = sources.getDirectives().getBlendModeOverride().orElse(ProgramId.Terrain.getBlendModeOverride()); - terrainBufferOverrides = new ArrayList<>(); + terrainCutoutSource.ifPresentOrElse(sources -> { + terrainCutoutBlendOverride = sources.getDirectives().getBlendModeOverride().orElse(ProgramId.Terrain.getBlendModeOverride()); + terrainCutoutBufferOverrides = new ArrayList<>(); sources.getDirectives().getBufferBlendOverrides().forEach(information -> { int index = Ints.indexOf(sources.getDirectives().getDrawBuffers(), information.getIndex()); if (index > -1) { - terrainBufferOverrides.add(new BufferBlendOverride(index, information.getBlendMode())); + terrainCutoutBufferOverrides.add(new BufferBlendOverride(index, information.getBlendMode())); } }); terrainCutoutAlpha = sources.getDirectives().getAlphaTestOverride().or(terrainCutoutDefault); @@ -133,24 +191,27 @@ public void patchShaders(ChunkVertexType vertexType) { Map transformed = TransformPatcher.patchSodium( sources.getVertexSource().orElse(null), sources.getGeometrySource().orElse(null), + sources.getTessControlSource().orElse(null), + sources.getTessEvalSource().orElse(null), sources.getFragmentSource().orElse(null), - terrainCutoutAlpha.get(), AlphaTest.ALWAYS, inputs, + terrainCutoutAlpha.orElse(AlphaTests.ONE_TENTH_ALPHA), inputs, vertexType.getPositionScale(), vertexType.getPositionOffset(), vertexType.getTextureScale(), parent.getTextureMap()); - terrainVertex = Optional.ofNullable(transformed.get(PatchShaderType.VERTEX)); - terrainGeometry = Optional.ofNullable(transformed.get(PatchShaderType.GEOMETRY)); - terrainCutoutFragment = Optional.ofNullable(transformed.get(PatchShaderType.FRAGMENT_CUTOUT)); - terrainFragment = Optional.ofNullable(transformed.get(PatchShaderType.FRAGMENT)); + terrainCutoutVertex = Optional.ofNullable(transformed.get(PatchShaderType.VERTEX)); + terrainCutoutGeometry = Optional.ofNullable(transformed.get(PatchShaderType.GEOMETRY)); + terrainCutoutTessControl = Optional.ofNullable(transformed.get(PatchShaderType.TESS_CONTROL)); + terrainCutoutTessEval = Optional.ofNullable(transformed.get(PatchShaderType.TESS_EVAL)); + terrainCutoutFragment = Optional.ofNullable(transformed.get(PatchShaderType.FRAGMENT)); - PatchedShaderPrinter.debugPatchedShaders(sources.getName() + "_sodium", terrainVertex.orElse(null), terrainGeometry.orElse(null), terrainFragment.orElse(null)); - PatchedShaderPrinter.debugPatchedShaders(sources.getName() + "_sodium_cutout", null, null, terrainCutoutFragment.orElse(null)); + ShaderPrinter.printProgram(sources.getName() + "_sodium_cutout").addSources(transformed).print(); }, () -> { - terrainBlendOverride = null; - terrainBufferOverrides = Collections.emptyList(); + terrainCutoutBlendOverride = null; + terrainCutoutBufferOverrides = Collections.emptyList(); terrainCutoutAlpha = terrainCutoutDefault.get(); - terrainVertex = Optional.empty(); - terrainGeometry = Optional.empty(); + terrainCutoutVertex = Optional.empty(); + terrainCutoutGeometry = Optional.empty(); + terrainCutoutTessControl = Optional.empty(); + terrainCutoutTessEval = Optional.empty(); terrainCutoutFragment = Optional.empty(); - terrainFragment = Optional.empty(); }); @@ -168,20 +229,26 @@ public void patchShaders(ChunkVertexType vertexType) { Map transformed = TransformPatcher.patchSodium( sources.getVertexSource().orElse(null), sources.getGeometrySource().orElse(null), + sources.getTessControlSource().orElse(null), + sources.getTessEvalSource().orElse(null), sources.getFragmentSource().orElse(null), - null, translucentAlpha.get(), inputs, + translucentAlpha.orElse(AlphaTest.ALWAYS), inputs, vertexType.getPositionScale(), vertexType.getPositionOffset(), vertexType.getTextureScale(), parent.getTextureMap()); translucentVertex = Optional.ofNullable(transformed.get(PatchShaderType.VERTEX)); translucentGeometry = Optional.ofNullable(transformed.get(PatchShaderType.GEOMETRY)); + translucentTessControl = Optional.ofNullable(transformed.get(PatchShaderType.TESS_CONTROL)); + translucentTessEval = Optional.ofNullable(transformed.get(PatchShaderType.TESS_EVAL)); translucentFragment = Optional.ofNullable(transformed.get(PatchShaderType.FRAGMENT)); - PatchedShaderPrinter.debugPatchedShaders(sources.getName() + "_sodium", translucentVertex.orElse(null), translucentGeometry.orElse(null), translucentFragment.orElse(null)); + ShaderPrinter.printProgram(sources.getName() + "_sodium").addSources(transformed).print(); }, () -> { translucentBlendOverride = null; translucentBufferOverrides = Collections.emptyList(); translucentAlpha = translucentDefault.get(); translucentVertex = Optional.empty(); translucentGeometry = Optional.empty(); + translucentTessControl = Optional.empty(); + translucentTessEval = Optional.empty(); translucentFragment = Optional.empty(); }); @@ -199,53 +266,105 @@ public void patchShaders(ChunkVertexType vertexType) { Map transformed = TransformPatcher.patchSodium( sources.getVertexSource().orElse(null), sources.getGeometrySource().orElse(null), + sources.getTessControlSource().orElse(null), + sources.getTessEvalSource().orElse(null), + sources.getFragmentSource().orElse(null), + AlphaTest.ALWAYS, inputs, + vertexType.getPositionScale(), vertexType.getPositionOffset(), vertexType.getTextureScale(), parent.getTextureMap()); + Map transformedCutout = TransformPatcher.patchSodium( + sources.getVertexSource().orElse(null), + sources.getGeometrySource().orElse(null), + sources.getTessControlSource().orElse(null), + sources.getTessEvalSource().orElse(null), sources.getFragmentSource().orElse(null), - shadowAlpha.get(), AlphaTest.ALWAYS, inputs, + shadowAlpha.get(), inputs, vertexType.getPositionScale(), vertexType.getPositionOffset(), vertexType.getTextureScale(), parent.getTextureMap()); shadowVertex = Optional.ofNullable(transformed.get(PatchShaderType.VERTEX)); shadowGeometry = Optional.ofNullable(transformed.get(PatchShaderType.GEOMETRY)); - shadowCutoutFragment = Optional.ofNullable(transformed.get(PatchShaderType.FRAGMENT_CUTOUT)); + shadowTessControl = Optional.ofNullable(transformed.get(PatchShaderType.TESS_CONTROL)); + shadowTessEval = Optional.ofNullable(transformed.get(PatchShaderType.TESS_EVAL)); + shadowCutoutFragment = Optional.ofNullable(transformedCutout.get(PatchShaderType.FRAGMENT)); shadowFragment = Optional.ofNullable(transformed.get(PatchShaderType.FRAGMENT)); - PatchedShaderPrinter.debugPatchedShaders(sources.getName() + "_sodium", shadowVertex.orElse(null), shadowGeometry.orElse(null), shadowFragment.orElse(null)); - PatchedShaderPrinter.debugPatchedShaders(sources.getName() + "_sodium_cutout", null, null, shadowCutoutFragment.orElse(null)); + ShaderPrinter.printProgram(sources.getName() + "_sodium") + .addSources(transformed) + .setName(sources.getName() + "_sodium_cutout") + .addSource(PatchShaderType.FRAGMENT, shadowCutoutFragment.orElse(null)) + .print(); }, () -> { shadowBlendOverride = null; shadowBufferOverrides = Collections.emptyList(); shadowAlpha = shadowDefault.get(); shadowVertex = Optional.empty(); shadowGeometry = Optional.empty(); + shadowTessControl = Optional.empty(); + shadowTessEval = Optional.empty(); shadowCutoutFragment = Optional.empty(); shadowFragment = Optional.empty(); }); } - public Optional getTerrainVertexShaderSource() { - return terrainVertex; + public Optional getTerrainSolidVertexShaderSource() { + return terrainSolidVertex; + } + + public Optional getTerrainSolidGeometryShaderSource() { + return terrainSolidGeometry; + } + + public Optional getTerrainSolidTessControlShaderSource() { + return terrainSolidTessControl; + } + + public Optional getTerrainSolidTessEvalShaderSource() { + return terrainSolidTessEval; + } + + public Optional getTerrainSolidFragmentShaderSource() { + return terrainSolidFragment; + } + + public Optional getTerrainCutoutVertexShaderSource() { + return terrainCutoutVertex; } - public Optional getTerrainGeometryShaderSource() { - return terrainGeometry; + public Optional getTerrainCutoutGeometryShaderSource() { + return terrainCutoutGeometry; } - public Optional getTerrainFragmentShaderSource() { - return terrainFragment; + public Optional getTerrainCutoutTessControlShaderSource() { + return terrainCutoutTessControl; + } + + public Optional getTerrainCutoutTessEvalShaderSource() { + return terrainCutoutTessEval; } public Optional getTerrainCutoutFragmentShaderSource() { return terrainCutoutFragment; } - public GlFramebuffer getTerrainFramebuffer() { - return terrainFramebuffer; + public GlFramebuffer getTerrainSolidFramebuffer() { + return terrainSolidFramebuffer; + } + public GlFramebuffer getTerrainCutoutFramebuffer() { + return terrainCutoutFramebuffer; + } + + public BlendModeOverride getTerrainSolidBlendOverride() { + return terrainSolidBlendOverride; + } + + public List getTerrainSolidBufferOverrides() { + return terrainSolidBufferOverrides; } - public BlendModeOverride getTerrainBlendOverride() { - return terrainBlendOverride; + public BlendModeOverride getTerrainCutoutBlendOverride() { + return terrainCutoutBlendOverride; } - public List getTerrainBufferOverrides() { - return terrainBufferOverrides; + public List getTerrainCutoutBufferOverrides() { + return terrainCutoutBufferOverrides; } public Optional getTerrainCutoutAlpha() { @@ -260,6 +379,14 @@ public Optional getTranslucentGeometryShaderSource() { return translucentGeometry; } + public Optional getTranslucentTessControlShaderSource() { + return translucentTessControl; + } + + public Optional getTranslucentTessEvalShaderSource() { + return translucentTessEval; + } + public Optional getTranslucentFragmentShaderSource() { return translucentFragment; } @@ -288,6 +415,14 @@ public Optional getShadowGeometryShaderSource() { return shadowGeometry; } + public Optional getShadowTessControlShaderSource() { + return shadowTessControl; + } + + public Optional getShadowTessEvalShaderSource() { + return shadowTessEval; + } + public Optional getShadowFragmentShaderSource() { return shadowFragment; } diff --git a/src/main/java/net/coderbot/iris/pipeline/WorldRenderingPipeline.java b/src/main/java/net/coderbot/iris/pipeline/WorldRenderingPipeline.java index ed8300e06f..3bec5584b0 100644 --- a/src/main/java/net/coderbot/iris/pipeline/WorldRenderingPipeline.java +++ b/src/main/java/net/coderbot/iris/pipeline/WorldRenderingPipeline.java @@ -1,6 +1,8 @@ package net.coderbot.iris.pipeline; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.compat.dh.DHCompat; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition; import net.coderbot.iris.gbuffer_overrides.state.RenderTargetStateListener; import net.coderbot.iris.gl.texture.TextureType; @@ -16,7 +18,9 @@ import java.util.OptionalInt; public interface WorldRenderingPipeline { - void beginLevelRendering(); + void onShadowBufferChange(); + + void beginLevelRendering(); void renderShadows(LevelRendererAccessor worldRenderer, Camera camera); void addDebugText(List messages); OptionalInt getForcedShadowRenderDistanceChunksForDisplay(); @@ -41,6 +45,7 @@ public interface WorldRenderingPipeline { void beginTranslucents(); void finalizeLevelRendering(); + void finalizeGameRendering(); void destroy(); SodiumTerrainPipeline getSodiumTerrainPipeline(); @@ -48,6 +53,7 @@ public interface WorldRenderingPipeline { boolean shouldDisableVanillaEntityShadows(); boolean shouldDisableDirectionalShading(); + boolean shouldDisableFrustumCulling(); CloudSetting getCloudSetting(); boolean shouldRenderUnderwaterOverlay(); boolean shouldRenderVignette(); @@ -56,6 +62,9 @@ public interface WorldRenderingPipeline { boolean shouldWriteRainAndSnowToDepthBuffer(); ParticleRenderingSettings getParticleRenderingSettings(); boolean allowConcurrentCompute(); + boolean hasFeature(FeatureFlags flags); float getSunPathRotation(); + + DHCompat getDHCompat(); } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/ExtendedShader.java b/src/main/java/net/coderbot/iris/pipeline/newshader/ExtendedShader.java index dc19bcba70..b89e8d8822 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/ExtendedShader.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/ExtendedShader.java @@ -1,21 +1,11 @@ package net.coderbot.iris.pipeline.newshader; -import java.io.IOException; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import org.jetbrains.annotations.Nullable; -import org.lwjgl.opengl.ARBTextureSwizzle; -import org.lwjgl.opengl.GL30C; - import com.mojang.blaze3d.preprocessor.GlslPreprocessor; import com.mojang.blaze3d.shaders.Program; import com.mojang.blaze3d.shaders.ProgramManager; import com.mojang.blaze3d.shaders.Uniform; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.VertexFormat; - import net.coderbot.iris.gl.IrisRenderSystem; import net.coderbot.iris.gl.blending.AlphaTest; import net.coderbot.iris.gl.blending.BlendModeOverride; @@ -32,14 +22,23 @@ import net.coderbot.iris.uniforms.CapturedRenderingState; import net.coderbot.iris.uniforms.custom.CustomUniforms; import net.coderbot.iris.vendored.joml.Vector3f; +import net.coderbot.iris.vertices.ImmediateState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.Resource; import net.minecraft.server.packs.resources.ResourceProvider; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.opengl.ARBTextureSwizzle; +import org.lwjgl.opengl.GL30C; import repack.joml.Matrix3f; import repack.joml.Matrix4f; +import java.io.IOException; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + public class ExtendedShader extends ShaderInstance implements ShaderInstanceInterface { private final boolean intensitySwizzle; private final List bufferBlendOverrides; @@ -57,13 +56,14 @@ public class ExtendedShader extends ShaderInstance implements ShaderInstanceInte GlFramebuffer baseline; BlendModeOverride blendModeOverride; float alphaTest; - private Program geometry; + boolean usesTessellation; + private Program geometry, tessControl, tessEval; private final ShaderAttributeInputs inputs; private static ExtendedShader lastApplied; private final Vector3f chunkOffset = new Vector3f(); - public ExtendedShader(ResourceProvider resourceFactory, String string, VertexFormat vertexFormat, + public ExtendedShader(ResourceProvider resourceFactory, String string, VertexFormat vertexFormat, boolean usesTessellation, GlFramebuffer writingToBeforeTranslucent, GlFramebuffer writingToAfterTranslucent, GlFramebuffer baseline, BlendModeOverride blendModeOverride, AlphaTest alphaTest, Consumer uniformCreator, BiConsumer samplerCreator, boolean isIntensity, @@ -78,6 +78,7 @@ public ExtendedShader(ResourceProvider resourceFactory, String string, VertexFor ProgramImages.Builder builder = ProgramImages.builder(programId); samplerCreator.accept(samplerBuilder, builder); customUniforms.mapholderToPass(uniformBuilder, this); + this.usesTessellation = usesTessellation; uniforms = uniformBuilder.buildUniforms(); this.customUniforms = customUniforms; @@ -147,6 +148,8 @@ public void apply() { IrisRenderSystem.bindTextureToUnit(TextureType.TEXTURE_2D.getGlType(), IrisSamplers.OVERLAY_TEXTURE_UNIT, RenderSystem.getShaderTexture(1)); IrisRenderSystem.bindTextureToUnit(TextureType.TEXTURE_2D.getGlType(), IrisSamplers.LIGHTMAP_TEXTURE_UNIT, RenderSystem.getShaderTexture(2)); + ImmediateState.usingTessellation = usesTessellation; + if (PROJECTION_MATRIX != null) { if (projectionInverse != null) { projectionInverse.set(tempMatrix4f.set(PROJECTION_MATRIX.getFloatBuffer()).invert().get(tempFloats)); @@ -231,13 +234,41 @@ public void attachToProgram() { if (this.geometry != null) { this.geometry.attachToShader(this); } + if (this.tessControl != null) { + this.tessControl.attachToShader(this); + } + if (this.tessEval != null) { + this.tessEval.attachToShader(this); + } } @Override - public void iris$createGeometryShader(ResourceProvider factory, ResourceLocation name) throws IOException { - Resource geometry = factory.getResource(new ResourceLocation(name.getNamespace(), name.getPath() + "_geometry.gsh")); + public void iris$createExtraShaders(ResourceProvider factory, String name) throws IOException { + Resource geometry = factory.getResource(new ResourceLocation("minecraft", name + "_geometry.gsh")); if (geometry != null) { - this.geometry = Program.compileShader(IrisProgramTypes.GEOMETRY, name.getPath(), geometry.getInputStream(), geometry.getSourceName(), new GlslPreprocessor() { + this.geometry = Program.compileShader(IrisProgramTypes.GEOMETRY, name, geometry.getInputStream(), geometry.getSourceName(), new GlslPreprocessor() { + @Nullable + @Override + public String applyImport(boolean bl, String string) { + return null; + } + }); + } + + Resource tessControl = factory.getResource(new ResourceLocation("minecraft", name + "_tessControl.tcs")); + if (tessControl != null) { + this.tessControl = Program.compileShader(IrisProgramTypes.TESS_CONTROL, name, tessControl.getInputStream(), tessControl.getSourceName(), new GlslPreprocessor() { + @Nullable + @Override + public String applyImport(boolean bl, String string) { + return null; + } + }); + } + + Resource tessEval = factory.getResource(new ResourceLocation("minecraft", name + "_tessEval.tes")); + if (tessEval != null) { + this.tessEval = Program.compileShader(IrisProgramTypes.TESS_EVAL, name, tessEval.getInputStream(), tessEval.getSourceName(), new GlslPreprocessor() { @Nullable @Override public String applyImport(boolean bl, String string) { @@ -251,6 +282,14 @@ public Program getGeometry() { return this.geometry; } + public Program getTessControl() { + return this.tessControl; + } + + public Program getTessEval() { + return this.tessEval; + } + public boolean hasActiveImages() { return images.getActiveImages() > 0; } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/IrisProgramTypes.java b/src/main/java/net/coderbot/iris/pipeline/newshader/IrisProgramTypes.java index 43ddb734dd..2ab068c930 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/IrisProgramTypes.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/IrisProgramTypes.java @@ -4,4 +4,6 @@ public class IrisProgramTypes { public static Program.Type GEOMETRY; + public static Program.Type TESS_CONTROL; + public static Program.Type TESS_EVAL; } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/NewShaderTests.java b/src/main/java/net/coderbot/iris/pipeline/newshader/NewShaderTests.java index 5160d148f3..30251f8b8d 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/NewShaderTests.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/NewShaderTests.java @@ -8,7 +8,7 @@ import net.coderbot.iris.gl.blending.BlendModeOverride; import net.coderbot.iris.gl.blending.BufferBlendOverride; import net.coderbot.iris.gl.framebuffer.GlFramebuffer; -import net.coderbot.iris.pipeline.PatchedShaderPrinter; +import net.coderbot.iris.pipeline.ShaderPrinter; import net.coderbot.iris.pipeline.WorldRenderingPipeline; import net.coderbot.iris.pipeline.newshader.fallback.FallbackShader; import net.coderbot.iris.pipeline.newshader.fallback.ShaderSynthesizer; @@ -42,17 +42,21 @@ public static ExtendedShader create(WorldRenderingPipeline pipeline, String name GlFramebuffer writingToAfterTranslucent, GlFramebuffer baseline, AlphaTest fallbackAlpha, VertexFormat vertexFormat, ShaderAttributeInputs inputs, FrameUpdateNotifier updateNotifier, NewWorldRenderingPipeline parent, Supplier> flipped, FogMode fogMode, boolean isIntensity, - boolean isFullbright, boolean isShadowPass, CustomUniforms customUniforms) throws IOException { + boolean isFullbright, boolean isShadowPass, boolean isLines, CustomUniforms customUniforms) throws IOException { AlphaTest alpha = source.getDirectives().getAlphaTestOverride().orElse(fallbackAlpha); BlendModeOverride blendModeOverride = source.getDirectives().getBlendModeOverride().orElse(programId.getBlendModeOverride()); Map transformed = TransformPatcher.patchVanilla( source.getVertexSource().orElseThrow(RuntimeException::new), source.getGeometrySource().orElse(null), + source.getTessControlSource().orElse(null), + source.getTessEvalSource().orElse(null), source.getFragmentSource().orElseThrow(RuntimeException::new), - alpha, true, inputs, pipeline.getTextureMap()); + alpha, isLines, true, inputs, pipeline.getTextureMap()); String vertex = transformed.get(PatchShaderType.VERTEX); String geometry = transformed.get(PatchShaderType.GEOMETRY); + String tessControl = transformed.get(PatchShaderType.TESS_CONTROL); + String tessEval = transformed.get(PatchShaderType.TESS_EVAL); String fragment = transformed.get(PatchShaderType.FRAGMENT); StringBuilder shaderJson = new StringBuilder("{\n" + @@ -88,9 +92,9 @@ public static ExtendedShader create(WorldRenderingPipeline pipeline, String name String shaderJsonString = shaderJson.toString(); - PatchedShaderPrinter.debugPatchedShaders(source.getName(), vertex, geometry, fragment, shaderJsonString); + ShaderPrinter.printProgram(name).addSources(transformed).addJson(shaderJsonString).print(); - ResourceProvider shaderResourceFactory = new IrisProgramResourceFactory(shaderJsonString, vertex, geometry, fragment); + ResourceProvider shaderResourceFactory = new IrisProgramResourceFactory(shaderJsonString, vertex, geometry, tessControl, tessEval, fragment); List overrides = new ArrayList<>(); source.getDirectives().getBufferBlendOverrides().forEach(information -> { @@ -100,7 +104,7 @@ public static ExtendedShader create(WorldRenderingPipeline pipeline, String name } }); - return new ExtendedShader(shaderResourceFactory, name, vertexFormat, writingToBeforeTranslucent, writingToAfterTranslucent, baseline, blendModeOverride, alpha, uniforms -> { + return new ExtendedShader(shaderResourceFactory, name, vertexFormat, tessControl != null || tessEval != null, writingToBeforeTranslucent, writingToAfterTranslucent, baseline, blendModeOverride, alpha, uniforms -> { CommonUniforms.addDynamicUniforms(uniforms, FogMode.PER_VERTEX); customUniforms.assignTo(uniforms); //SamplerUniforms.addWorldSamplerUniforms(uniforms); @@ -116,8 +120,8 @@ public static FallbackShader createFallback(String name, GlFramebuffer writingTo GlFramebuffer writingToAfterTranslucent, AlphaTest alpha, VertexFormat vertexFormat, BlendModeOverride blendModeOverride, NewWorldRenderingPipeline parent, FogMode fogMode, boolean entityLighting, - boolean intensityTex, boolean isFullbright) throws IOException { - ShaderAttributeInputs inputs = new ShaderAttributeInputs(vertexFormat, isFullbright); + boolean isGlint, boolean isText, boolean intensityTex, boolean isFullbright) throws IOException { + ShaderAttributeInputs inputs = new ShaderAttributeInputs(vertexFormat, isFullbright, false, isGlint, isText); // TODO: Is this check sound in newer versions? boolean isLeash = vertexFormat == DefaultVertexFormat.POSITION_COLOR_LIGHTMAP; @@ -160,9 +164,13 @@ public static FallbackShader createFallback(String name, GlFramebuffer writingTo " ]\n" + "}"; - PatchedShaderPrinter.debugPatchedShaders(name, vertex, null, fragment, shaderJsonString); + ShaderPrinter.printProgram(name) + .addSource(PatchShaderType.VERTEX, vertex) + .addSource(PatchShaderType.FRAGMENT, fragment) + .addJson(shaderJsonString) + .print(); - ResourceProvider shaderResourceFactory = new IrisProgramResourceFactory(shaderJsonString, vertex, null, fragment); + ResourceProvider shaderResourceFactory = new IrisProgramResourceFactory(shaderJsonString, vertex, null, null, null, fragment); return new FallbackShader(shaderResourceFactory, name, vertexFormat, writingToBeforeTranslucent, writingToAfterTranslucent, blendModeOverride, alpha.getReference(), parent); @@ -172,12 +180,16 @@ private static class IrisProgramResourceFactory implements ResourceProvider { private final String json; private final String vertex; private final String geometry; + private final String tessControl; + private final String tessEval; private final String fragment; - public IrisProgramResourceFactory(String json, String vertex, String geometry, String fragment) { + public IrisProgramResourceFactory(String json, String vertex, String geometry, String tessControl, String tessEval, String fragment) { this.json = json; this.vertex = vertex; this.geometry = geometry; + this.tessControl = tessControl; + this.tessEval = tessEval; this.fragment = fragment; } @@ -194,6 +206,16 @@ public Resource getResource(ResourceLocation id) throws IOException { return null; } return new StringResource(id, geometry); + } else if (path.endsWith("tcs")) { + if (tessControl == null) { + return null; + } + return new StringResource(id, tessControl); + } else if (path.endsWith("tes")) { + if (tessEval == null) { + return null; + } + return new StringResource(id, tessEval); } else if (path.endsWith("fsh")) { return new StringResource(id, fragment); } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/NewWorldRenderingPipeline.java b/src/main/java/net/coderbot/iris/pipeline/newshader/NewWorldRenderingPipeline.java index d7c63c1058..641f7fcab2 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/NewWorldRenderingPipeline.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/NewWorldRenderingPipeline.java @@ -10,20 +10,30 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; import net.coderbot.iris.block_rendering.BlockMaterialMapping; import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.coderbot.iris.colorspace.ColorSpace; +import net.coderbot.iris.colorspace.ColorSpaceConverter; +import net.coderbot.iris.colorspace.ColorSpaceFragmentConverter; +import net.coderbot.iris.compat.dh.DHCompat; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gbuffer_overrides.matching.InputAvailability; import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition; import net.coderbot.iris.gbuffer_overrides.state.RenderTargetStateListener; +import net.coderbot.iris.gl.IrisRenderSystem; import net.coderbot.iris.gl.blending.AlphaTest; import net.coderbot.iris.gl.blending.BlendModeOverride; +import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; import net.coderbot.iris.gl.framebuffer.GlFramebuffer; +import net.coderbot.iris.gl.image.GlImage; import net.coderbot.iris.gl.image.ImageHolder; import net.coderbot.iris.gl.program.ComputeProgram; import net.coderbot.iris.gl.program.ProgramBuilder; import net.coderbot.iris.gl.program.ProgramImages; import net.coderbot.iris.gl.program.ProgramSamplers; import net.coderbot.iris.gl.sampler.SamplerHolder; +import net.coderbot.iris.gl.sampler.SamplerLimits; import net.coderbot.iris.gl.texture.DepthBufferFormat; import net.coderbot.iris.gl.texture.TextureType; +import net.coderbot.iris.gui.option.IrisVideoSettings; import net.coderbot.iris.helpers.Tri; import net.coderbot.iris.mixin.GlStateManagerAccessor; import net.coderbot.iris.mixin.LevelRendererAccessor; @@ -31,12 +41,13 @@ import net.coderbot.iris.pipeline.ClearPassCreator; import net.coderbot.iris.pipeline.CustomTextureManager; import net.coderbot.iris.pipeline.HorizonRenderer; -import net.coderbot.iris.pipeline.PatchedShaderPrinter; +import net.coderbot.iris.pipeline.ShaderPrinter; import net.coderbot.iris.pipeline.ShadowRenderer; import net.coderbot.iris.pipeline.SodiumTerrainPipeline; import net.coderbot.iris.pipeline.WorldRenderingPhase; import net.coderbot.iris.pipeline.WorldRenderingPipeline; import net.coderbot.iris.pipeline.newshader.fallback.FallbackShader; +import net.coderbot.iris.pipeline.transform.PatchShaderType; import net.coderbot.iris.pipeline.transform.TransformPatcher; import net.coderbot.iris.postprocess.BufferFlipper; import net.coderbot.iris.postprocess.CenterDepthSampler; @@ -49,6 +60,8 @@ import net.coderbot.iris.samplers.IrisSamplers; import net.coderbot.iris.shaderpack.CloudSetting; import net.coderbot.iris.shaderpack.ComputeSource; +import net.coderbot.iris.shaderpack.FilledIndirectPointer; +import net.coderbot.iris.shaderpack.ImageInformation; import net.coderbot.iris.shaderpack.OptionalBoolean; import net.coderbot.iris.shaderpack.PackDirectives; import net.coderbot.iris.shaderpack.PackShadowDirectives; @@ -56,6 +69,7 @@ import net.coderbot.iris.shaderpack.ProgramFallbackResolver; import net.coderbot.iris.shaderpack.ProgramSet; import net.coderbot.iris.shaderpack.ProgramSource; +import net.coderbot.iris.shaderpack.ShaderPack; import net.coderbot.iris.shaderpack.loading.ProgramId; import net.coderbot.iris.shaderpack.texture.TextureStage; import net.coderbot.iris.shadows.ShadowCompositeRenderer; @@ -80,13 +94,14 @@ import net.minecraft.client.renderer.texture.AbstractTexture; import net.minecraft.client.renderer.texture.DynamicTexture; import org.jetbrains.annotations.Nullable; +import org.lwjgl.opengl.ARBClearTexture; import org.lwjgl.opengl.GL15C; import org.lwjgl.opengl.GL20C; import org.lwjgl.opengl.GL21C; import org.lwjgl.opengl.GL30C; +import org.lwjgl.opengl.GL43C; import java.io.IOException; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -102,6 +117,10 @@ public class NewWorldRenderingPipeline implements WorldRenderingPipeline, CoreWo private final CustomUniforms customUniforms; private final ShadowCompositeRenderer shadowCompositeRenderer; private final Object2ObjectMap, String> customTextureMap; + private final ComputeProgram[] setup; + private final boolean separateHardwareSamplers; + private ShaderStorageBufferHolder shaderStorageBufferHolder; + private final ProgramFallbackResolver resolver; private ShadowRenderTargets shadowRenderTargets; private final Supplier shadowTargetsSupplier; @@ -116,6 +135,7 @@ public class NewWorldRenderingPipeline implements WorldRenderingPipeline, CoreWo private ImmutableList shadowClearPassesFull; private final GlFramebuffer baseline; + private final CompositeRenderer beginRenderer; private final CompositeRenderer prepareRenderer; private final CompositeRenderer deferredRenderer; private final CompositeRenderer compositeRenderer; @@ -126,6 +146,7 @@ public class NewWorldRenderingPipeline implements WorldRenderingPipeline, CoreWo private final FrameUpdateNotifier updateNotifier; private final CenterDepthSampler centerDepthSampler; private final SodiumTerrainPipeline sodiumTerrainPipeline; + private final ColorSpaceConverter colorSpaceConverter; private final ImmutableSet flippedBeforeShadow; private final ImmutableSet flippedAfterPrepare; @@ -146,10 +167,10 @@ public class NewWorldRenderingPipeline implements WorldRenderingPipeline, CoreWo private boolean destroyed = false; private boolean isRenderingWorld; private boolean isMainBound; + private boolean frustumCulling; private final CloudSetting cloudSetting; private final boolean shouldRenderSun; private final boolean shouldRenderMoon; - private final boolean prepareBeforeShadow; private final boolean allowConcurrentCompute; @Nullable @@ -160,9 +181,15 @@ public class NewWorldRenderingPipeline implements WorldRenderingPipeline, CoreWo private int currentSpecularTexture; private ParticleRenderingSettings particleRenderingSettings; private PackDirectives packDirectives; + private Set customImages; + private GlImage[] clearImages; + private final ShaderPack pack; + private PackShadowDirectives shadowDirectives; + private ColorSpace currentColorSpace; + private DHCompat dhCompat; public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { - PatchedShaderPrinter.resetPrintState(); + ShaderPrinter.resetPrintState(); this.shouldRenderUnderwaterOverlay = programSet.getPackDirectives().underwaterOverlay(); this.shouldRenderVignette = programSet.getPackDirectives().vignette(); @@ -171,30 +198,56 @@ public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { this.updateNotifier = new FrameUpdateNotifier(); this.packDirectives = programSet.getPackDirectives(); this.customTextureMap = programSet.getPackDirectives().getTextureMap(); - + this.separateHardwareSamplers = programSet.getPack().hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS); + this.shadowDirectives = packDirectives.getShadowDirectives(); this.cloudSetting = programSet.getPackDirectives().getCloudSetting(); this.shouldRenderSun = programSet.getPackDirectives().shouldRenderSun(); this.shouldRenderMoon = programSet.getPackDirectives().shouldRenderMoon(); - this.prepareBeforeShadow = programSet.getPackDirectives().isPrepareBeforeShadow(); this.allowConcurrentCompute = programSet.getPackDirectives().getConcurrentCompute(); + this.frustumCulling = programSet.getPackDirectives().shouldUseFrustumCulling(); + this.dhCompat = new DHCompat(); + + this.resolver = new ProgramFallbackResolver(programSet); + this.pack = programSet.getPack(); + + RenderTarget main = Minecraft.getInstance().getMainRenderTarget(); + int depthTextureId = main.getDepthTextureId(); + int internalFormat = TextureInfoCache.INSTANCE.getInfo(depthTextureId).getInternalFormat(); + DepthBufferFormat depthBufferFormat = DepthBufferFormat.fromGlEnumOrDefault(internalFormat); - ProgramFallbackResolver resolver = new ProgramFallbackResolver(programSet); + if (!programSet.getPackDirectives().getBufferObjects().isEmpty()) { + if (IrisRenderSystem.supportsSSBO()) { + this.shaderStorageBufferHolder = new ShaderStorageBufferHolder(programSet.getPackDirectives().getBufferObjects(), main.width, main.height); + + this.shaderStorageBufferHolder.setupBuffers(); + } else { + throw new IllegalStateException("Shader storage buffers/immutable buffer storage is not supported on this graphics card, however the shaderpack requested them? This shouldn't be possible."); + } + } else { + for (int i = 0; i < Math.min(16, SamplerLimits.get().getMaxShaderStorageUnits()); i++) { + IrisRenderSystem.bindBufferBase(GL43C.GL_SHADER_STORAGE_BUFFER, i, 0); + } + } + + this.customImages = new HashSet<>(); + for (ImageInformation information : programSet.getPack().getIrisCustomImages()) { + if (information.isRelative()) { + customImages.add(new GlImage.Relative(information.name(), information.samplerName(), information.format(), information.internalTextureFormat(), information.type(), information.clear(), information.relativeWidth(), information.relativeHeight(), main.width, main.height)); + } else { + customImages.add(new GlImage(information.name(), information.samplerName(), information.target(), information.format(), information.internalTextureFormat(), information.type(), information.clear(), information.width(), information.height(), information.depth())); + } + } + + this.clearImages = customImages.stream().filter(GlImage::shouldClear).toArray(GlImage[]::new); this.particleRenderingSettings = programSet.getPackDirectives().getParticleRenderingSettings().orElseGet(() -> { - if (programSet.getDeferred().length > 0) { + if (programSet.getDeferred().length > 0 && !programSet.getPackDirectives().shouldUseSeparateEntityDraws()) { return ParticleRenderingSettings.AFTER; } else { return ParticleRenderingSettings.MIXED; } }); - this.shadowComputes = createShadowComputes(programSet.getShadowCompute(), programSet); - - RenderTarget main = Minecraft.getInstance().getMainRenderTarget(); - int depthTextureId = main.getDepthTextureId(); - int internalFormat = TextureInfoCache.INSTANCE.getInfo(depthTextureId).getInternalFormat(); - DepthBufferFormat depthBufferFormat = DepthBufferFormat.fromGlEnumOrDefault(internalFormat); - this.renderTargets = new RenderTargets(main.width, main.height, depthTextureId, ((Blaze3dRenderTargetExt) main).iris$getDepthBufferVersion(), depthBufferFormat, programSet.getPackDirectives().getRenderTargetDirectives().getRenderTargetSettings(), programSet.getPackDirectives()); this.sunPathRotation = programSet.getPackDirectives().getSunPathRotation(); @@ -224,10 +277,9 @@ public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { GlStateManager._activeTexture(GL20C.GL_TEXTURE0); - this.flippedBeforeShadow = ImmutableSet.of(); - BufferFlipper flipper = new BufferFlipper(); + this.centerDepthSampler = new CenterDepthSampler(() -> renderTargets.getDepthTexture(), programSet.getPackDirectives().getCenterDepthHalfLife()); this.shadowMapResolution = programSet.getPackDirectives().getShadowDirectives().getResolution(); @@ -235,33 +287,42 @@ public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { this.shadowTargetsSupplier = () -> { if (shadowRenderTargets == null) { // TODO: Support more than two shadowcolor render targets - this.shadowRenderTargets = new ShadowRenderTargets(shadowMapResolution, shadowDirectives); + this.shadowRenderTargets = new ShadowRenderTargets(this, shadowMapResolution, shadowDirectives); } return shadowRenderTargets; }; - this.prepareRenderer = new CompositeRenderer(this, programSet.getPackDirectives(), programSet.getPrepare(), programSet.getPrepareCompute(), renderTargets, + this.shadowComputes = createShadowComputes(programSet.getShadowCompute(), programSet); + + this.beginRenderer = new CompositeRenderer(this, programSet.getPackDirectives(), programSet.getBegin(), programSet.getBeginCompute(), renderTargets, shaderStorageBufferHolder, + customTextureManager.getNoiseTexture(), updateNotifier, centerDepthSampler, flipper, shadowTargetsSupplier, TextureStage.BEGIN, + customTextureManager.getCustomTextureIdMap().getOrDefault(TextureStage.BEGIN, Object2ObjectMaps.emptyMap()), customTextureManager.getIrisCustomTextures(), customImages, + programSet.getPackDirectives().getExplicitFlips("begin_pre"), customUniforms); + + flippedBeforeShadow = flipper.snapshot(); + + this.prepareRenderer = new CompositeRenderer(this, programSet.getPackDirectives(), programSet.getPrepare(), programSet.getPrepareCompute(), renderTargets, shaderStorageBufferHolder, customTextureManager.getNoiseTexture(), updateNotifier, centerDepthSampler, flipper, shadowTargetsSupplier, TextureStage.PREPARE, - customTextureManager.getCustomTextureIdMap().getOrDefault(TextureStage.PREPARE, Object2ObjectMaps.emptyMap()), customTextureManager.getIrisCustomTextures(), + customTextureManager.getCustomTextureIdMap().getOrDefault(TextureStage.PREPARE, Object2ObjectMaps.emptyMap()), customTextureManager.getIrisCustomTextures(), customImages, programSet.getPackDirectives().getExplicitFlips("prepare_pre"), customUniforms); flippedAfterPrepare = flipper.snapshot(); - this.deferredRenderer = new CompositeRenderer(this, programSet.getPackDirectives(), programSet.getDeferred(), programSet.getDeferredCompute(), renderTargets, + this.deferredRenderer = new CompositeRenderer(this, programSet.getPackDirectives(), programSet.getDeferred(), programSet.getDeferredCompute(), renderTargets, shaderStorageBufferHolder, customTextureManager.getNoiseTexture(), updateNotifier, centerDepthSampler, flipper, shadowTargetsSupplier, TextureStage.DEFERRED, - customTextureManager.getCustomTextureIdMap().getOrDefault(TextureStage.DEFERRED, Object2ObjectMaps.emptyMap()), customTextureManager.getIrisCustomTextures(), + customTextureManager.getCustomTextureIdMap().getOrDefault(TextureStage.DEFERRED, Object2ObjectMaps.emptyMap()), customTextureManager.getIrisCustomTextures(), customImages, programSet.getPackDirectives().getExplicitFlips("deferred_pre"), customUniforms); flippedAfterTranslucent = flipper.snapshot(); - this.compositeRenderer = new CompositeRenderer(this, programSet.getPackDirectives(), programSet.getComposite(), programSet.getCompositeCompute(), renderTargets, + this.compositeRenderer = new CompositeRenderer(this, programSet.getPackDirectives(), programSet.getComposite(), programSet.getCompositeCompute(), renderTargets, shaderStorageBufferHolder, customTextureManager.getNoiseTexture(), updateNotifier, centerDepthSampler, flipper, shadowTargetsSupplier, TextureStage.COMPOSITE_AND_FINAL, - customTextureManager.getCustomTextureIdMap().getOrDefault(TextureStage.COMPOSITE_AND_FINAL, Object2ObjectMaps.emptyMap()), customTextureManager.getIrisCustomTextures(), + customTextureManager.getCustomTextureIdMap().getOrDefault(TextureStage.COMPOSITE_AND_FINAL, Object2ObjectMaps.emptyMap()), customTextureManager.getIrisCustomTextures(), customImages, programSet.getPackDirectives().getExplicitFlips("composite_pre"), customUniforms); - this.finalPassRenderer = new FinalPassRenderer(this, programSet, renderTargets, customTextureManager.getNoiseTexture(), updateNotifier, flipper.snapshot(), + this.finalPassRenderer = new FinalPassRenderer(this, programSet, renderTargets, customTextureManager.getNoiseTexture(), shaderStorageBufferHolder, updateNotifier, flipper.snapshot(), centerDepthSampler, shadowTargetsSupplier, - customTextureManager.getCustomTextureIdMap().getOrDefault(TextureStage.COMPOSITE_AND_FINAL, Object2ObjectMaps.emptyMap()), customTextureManager.getIrisCustomTextures(), + customTextureManager.getCustomTextureIdMap().getOrDefault(TextureStage.COMPOSITE_AND_FINAL, Object2ObjectMaps.emptyMap()), customTextureManager.getIrisCustomTextures(), customImages, this.compositeRenderer.getFlippedAtLeastOnceFinal(), customUniforms); Supplier> flipped = @@ -282,11 +343,12 @@ public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { IrisSamplers.addLevelSamplers(customTextureSamplerInterceptor, this, whitePixel, new InputAvailability(true, true, false)); IrisSamplers.addWorldDepthSamplers(customTextureSamplerInterceptor, renderTargets); IrisSamplers.addNoiseSampler(customTextureSamplerInterceptor, customTextureManager.getNoiseTexture()); + IrisSamplers.addCustomImages(customTextureSamplerInterceptor, customImages); if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { // we compiled the non-Sodium version of this program first... so if this is somehow null, something // very odd is going on. - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, Objects.requireNonNull(shadowRenderTargets), null); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, Objects.requireNonNull(shadowRenderTargets), null, separateHardwareSamplers); } return builder.build(); @@ -296,6 +358,7 @@ public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { ProgramImages.Builder builder = ProgramImages.builder(programId); IrisImages.addRenderTargetImages(builder, flipped, renderTargets); + IrisImages.addCustomImages(builder, customImages); if (IrisImages.hasShadowImages(builder)) { // we compiled the non-Sodium version of this program first... so if this is somehow null, something @@ -311,7 +374,7 @@ public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { ProgramSamplers.CustomTextureSamplerInterceptor customTextureSamplerInterceptor = ProgramSamplers.customTextureSamplerInterceptor(builder, customTextureManager.getCustomTextureIdMap().getOrDefault(TextureStage.GBUFFERS_AND_SHADOW, Object2ObjectMaps.emptyMap())); - IrisSamplers.addRenderTargetSamplers(customTextureSamplerInterceptor, () -> prepareBeforeShadow ? flippedAfterPrepare : flippedBeforeShadow, renderTargets, false); + IrisSamplers.addRenderTargetSamplers(customTextureSamplerInterceptor, () -> flippedBeforeShadow, renderTargets, false); IrisSamplers.addCustomTextures(builder, customTextureManager.getIrisCustomTextures()); if (!shouldBindPBR) { @@ -320,6 +383,7 @@ public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { IrisSamplers.addLevelSamplers(customTextureSamplerInterceptor, this, whitePixel, new InputAvailability(true, true, false)); IrisSamplers.addNoiseSampler(customTextureSamplerInterceptor, customTextureManager.getNoiseTexture()); + IrisSamplers.addCustomImages(customTextureSamplerInterceptor, customImages); // Only initialize these samplers if the shadow map renderer exists. // Otherwise, this program shouldn't be used at all? @@ -327,7 +391,7 @@ public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { // We don't compile Sodium shadow programs unless there's a shadow pass... And a shadow pass // can only exist if the shadow render targets have been created by detecting their // usage in a different program. So this null-check makes sense here. - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, Objects.requireNonNull(shadowRenderTargets), null); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, Objects.requireNonNull(shadowRenderTargets), null, separateHardwareSamplers); } return builder.build(); @@ -336,7 +400,8 @@ public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { IntFunction createShadowTerrainImages = (programId) -> { ProgramImages.Builder builder = ProgramImages.builder(programId); - IrisImages.addRenderTargetImages(builder, () -> prepareBeforeShadow ? flippedAfterPrepare : flippedBeforeShadow, renderTargets); + IrisImages.addRenderTargetImages(builder, () -> flippedBeforeShadow, renderTargets); + IrisImages.addCustomImages(builder, customImages); if (IrisImages.hasShadowImages(builder)) { // We don't compile Sodium shadow programs unless there's a shadow pass... And a shadow pass @@ -377,18 +442,16 @@ public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { BlockRenderingSettings.INSTANCE.setBlockTypeIds(BlockMaterialMapping.createBlockTypeMap(programSet.getPack().getIdMap().getBlockRenderTypeMap())); BlockRenderingSettings.INSTANCE.setEntityIds(programSet.getPack().getIdMap().getEntityIdMap()); + BlockRenderingSettings.INSTANCE.setItemIds(programSet.getPack().getIdMap().getItemIdMap()); BlockRenderingSettings.INSTANCE.setAmbientOcclusionLevel(programSet.getPackDirectives().getAmbientOcclusionLevel()); BlockRenderingSettings.INSTANCE.setDisableDirectionalShading(shouldDisableDirectionalShading()); BlockRenderingSettings.INSTANCE.setUseSeparateAo(programSet.getPackDirectives().shouldUseSeparateAo()); + BlockRenderingSettings.INSTANCE.setVoxelizeLightBlocks(programSet.getPackDirectives().shouldVoxelizeLightBlocks()); + BlockRenderingSettings.INSTANCE.setSeparateEntityDraws(programSet.getPackDirectives().shouldUseSeparateEntityDraws()); BlockRenderingSettings.INSTANCE.setUseExtendedVertexFormat(true); - this.clearPassesFull = ClearPassCreator.createClearPasses(renderTargets, true, - programSet.getPackDirectives().getRenderTargetDirectives()); - this.clearPasses = ClearPassCreator.createClearPasses(renderTargets, false, - programSet.getPackDirectives().getRenderTargetDirectives()); - if (shadowRenderTargets == null && shadowDirectives.isShadowEnabled() == OptionalBoolean.TRUE) { - shadowRenderTargets = new ShadowRenderTargets(shadowMapResolution, shadowDirectives); + shadowRenderTargets = new ShadowRenderTargets(this, shadowMapResolution, shadowDirectives); } if (shadowRenderTargets != null) { @@ -402,12 +465,12 @@ public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { this.shadowClearPasses = ClearPassCreator.createShadowClearPasses(shadowRenderTargets, false, shadowDirectives); this.shadowClearPassesFull = ClearPassCreator.createShadowClearPasses(shadowRenderTargets, true, shadowDirectives); - this.shadowCompositeRenderer = new ShadowCompositeRenderer(this, programSet.getPackDirectives(), programSet.getShadowComposite(), programSet.getShadowCompCompute(), this.shadowRenderTargets, customTextureManager.getNoiseTexture(), updateNotifier, - customTextureManager.getCustomTextureIdMap(TextureStage.SHADOWCOMP), programSet.getPackDirectives().getExplicitFlips("shadowcomp_pre"), customTextureManager.getIrisCustomTextures(), customUniforms); + this.shadowCompositeRenderer = new ShadowCompositeRenderer(this, programSet.getPackDirectives(), programSet.getShadowComposite(), programSet.getShadowCompCompute(), this.shadowRenderTargets, this.shaderStorageBufferHolder, customTextureManager.getNoiseTexture(), updateNotifier, + customTextureManager.getCustomTextureIdMap(TextureStage.SHADOWCOMP), customImages, programSet.getPackDirectives().getExplicitFlips("shadowcomp_pre"), customTextureManager.getIrisCustomTextures(), customUniforms); if (programSet.getPackDirectives().getShadowDirectives().isShadowEnabled().orElse(true)) { this.shadowRenderer = new ShadowRenderer(programSet.getShadow().orElse(null), - programSet.getPackDirectives(), shadowRenderTargets, shadowCompositeRenderer, customUniforms); + programSet.getPackDirectives(), shadowRenderTargets, shadowCompositeRenderer, customUniforms, programSet.getPack().hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS)); } else { shadowRenderer = null; } @@ -419,15 +482,69 @@ public NewWorldRenderingPipeline(ProgramSet programSet) throws IOException { this.shadowRenderer = null; } + dhCompat.setFramebuffer(renderTargets.createGbufferFramebuffer(ImmutableSet.of(), new int[] { 0 })); // TODO: Create fallback Sodium shaders if the pack doesn't provide terrain shaders // Currently we use Sodium's shaders but they don't support EXP2 fog underwater. this.sodiumTerrainPipeline = new SodiumTerrainPipeline(this, programSet, createTerrainSamplers, shadowRenderTargets == null ? null : createShadowTerrainSamplers, createTerrainImages, createShadowTerrainImages, renderTargets, flippedAfterPrepare, flippedAfterTranslucent, - shadowRenderTargets != null ? shadowRenderTargets.getMainRenderBuffer() : null, customUniforms); + shadowRenderTargets != null ? shadowRenderTargets.createShadowFramebuffer(ImmutableSet.of(), programSet.getShadow().filter(source -> !source.getDirectives().hasUnknownDrawBuffers()).map(source -> source.getDirectives().getDrawBuffers()).orElse(new int[]{0, 1})) : null, customUniforms); + + this.setup = createSetupComputes(programSet.getSetup(), programSet, TextureStage.SETUP); // first optimization pass this.customUniforms.optimise(); + boolean hasRun = false; + + this.clearPassesFull = ClearPassCreator.createClearPasses(renderTargets, true, + programSet.getPackDirectives().getRenderTargetDirectives()); + this.clearPasses = ClearPassCreator.createClearPasses(renderTargets, false, + programSet.getPackDirectives().getRenderTargetDirectives()); + + for (ComputeProgram program : setup) { + if (program != null) { + if (!hasRun) { + hasRun = true; + renderTargets.onFullClear(); + Vector3d fogColor3 = CapturedRenderingState.INSTANCE.getFogColor(); + + // NB: The alpha value must be 1.0 here, or else you will get a bunch of bugs. Sildur's Vibrant Shaders + // will give you pink reflections and other weirdness if this is zero. + Vector4f fogColor = new Vector4f((float) fogColor3.x, (float) fogColor3.y, (float) fogColor3.z, 1.0F); + + clearPassesFull.forEach(clearPass -> clearPass.execute(fogColor)); + } + program.use(); + program.dispatch(1, 1); + } + } + + if (hasRun) { + ComputeProgram.unbind(); + } + + if (programSet.getPackDirectives().supportsColorCorrection()) { + colorSpaceConverter = new ColorSpaceConverter() { + @Override + public void rebuildProgram(int width, int height, ColorSpace colorSpace) { + + } + + @Override + public void process(int target) { + + } + }; + } else { + // TODO: Fix grid appearing on some devices with compute converter + //if (IrisRenderSystem.supportsCompute()) { + // colorSpaceConverter = new ColorSpaceComputeConverter(main.width, main.height, IrisVideoSettings.colorSpace); + //} else { + colorSpaceConverter = new ColorSpaceFragmentConverter(main.width, main.height, IrisVideoSettings.colorSpace); + //} + } + + currentColorSpace = IrisVideoSettings.colorSpace; } private ComputeProgram[] createShadowComputes(ComputeSource[] compute, ProgramSet programSet) { @@ -440,13 +557,18 @@ private ComputeProgram[] createShadowComputes(ComputeSource[] compute, ProgramSe ProgramBuilder builder; try { - builder = ProgramBuilder.beginCompute(source.getName(), TransformPatcher.patchCompute(source.getSource().orElse(null), TextureStage.GBUFFERS_AND_SHADOW, customTextureMap), IrisSamplers.WORLD_RESERVED_TEXTURE_UNITS); + String transformed = TransformPatcher.patchCompute(source.getSource().orElse(null), TextureStage.GBUFFERS_AND_SHADOW, customTextureMap); + + ShaderPrinter.printProgram(source.getName()).addSource(PatchShaderType.COMPUTE, transformed).print(); + + builder = ProgramBuilder.beginCompute(source.getName(), transformed, IrisSamplers.WORLD_RESERVED_TEXTURE_UNITS); } catch (RuntimeException e) { // TODO: Better error handling - throw new RuntimeException("Shader compilation failed!", e); + throw new RuntimeException("Shader compilation failed for compute " + source.getName() + "!", e); } - CommonUniforms.addCommonUniforms(builder, programSet.getPack().getIdMap(), programSet.getPackDirectives(), updateNotifier, FogMode.OFF); + CommonUniforms.addDynamicUniforms(builder, FogMode.OFF); + customUniforms.assignTo(builder); Supplier> flipped; @@ -460,7 +582,9 @@ private ComputeProgram[] createShadowComputes(ComputeSource[] compute, ProgramSe IrisSamplers.addRenderTargetSamplers(customTextureSamplerInterceptor, flipped, renderTargets, false); IrisSamplers.addCustomTextures(builder, customTextureManager.getIrisCustomTextures()); + IrisSamplers.addCustomImages(customTextureSamplerInterceptor, customImages); IrisImages.addRenderTargetImages(builder, flipped, renderTargets); + IrisImages.addCustomImages(builder, customImages); IrisSamplers.addLevelSamplers(customTextureSamplerInterceptor, this, whitePixel, new InputAvailability(true, true, false)); @@ -468,14 +592,79 @@ private ComputeProgram[] createShadowComputes(ComputeSource[] compute, ProgramSe if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { if (shadowRenderTargets != null) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowRenderTargets, null); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowRenderTargets, null, separateHardwareSamplers); IrisImages.addShadowColorImages(builder, shadowRenderTargets, null); } } programs[i] = builder.buildCompute(); - programs[i].setWorkGroupInfo(source.getWorkGroupRelative(), source.getWorkGroups()); + this.customUniforms.mapholderToPass(builder, programs[i]); + + programs[i].setWorkGroupInfo(source.getWorkGroupRelative(), source.getWorkGroups(), FilledIndirectPointer.basedOff(shaderStorageBufferHolder, source.getIndirectPointer())); + } + } + + + return programs; + } + + private ComputeProgram[] createSetupComputes(ComputeSource[] compute, ProgramSet programSet, TextureStage stage) { + ComputeProgram[] programs = new ComputeProgram[compute.length]; + for (int i = 0; i < programs.length; i++) { + ComputeSource source = compute[i]; + if (source == null || !source.getSource().isPresent()) { + continue; + } else { + ProgramBuilder builder; + + try { + String transformed = TransformPatcher.patchCompute(source.getSource().orElse(null), stage, customTextureMap); + + ShaderPrinter.printProgram(source.getName()).addSource(PatchShaderType.COMPUTE, transformed).print(); + + builder = ProgramBuilder.beginCompute(source.getName(), transformed, IrisSamplers.COMPOSITE_RESERVED_TEXTURE_UNITS); + } catch (RuntimeException e) { + // TODO: Better error handling + throw new RuntimeException("Shader compilation failed for setup compute " + source.getName() + "!", e); + } + + CommonUniforms.addDynamicUniforms(builder, FogMode.OFF); + customUniforms.assignTo(builder); + + ImmutableSet empty = ImmutableSet.of(); + Supplier> flipped; + + flipped = () -> empty; + + TextureStage textureStage = TextureStage.SETUP; + + ProgramSamplers.CustomTextureSamplerInterceptor customTextureSamplerInterceptor = + ProgramSamplers.customTextureSamplerInterceptor(builder, + customTextureManager.getCustomTextureIdMap(textureStage)); + + IrisSamplers.addRenderTargetSamplers(customTextureSamplerInterceptor, flipped, renderTargets, true); + IrisSamplers.addCustomTextures(builder, customTextureManager.getIrisCustomTextures()); + IrisSamplers.addCompositeSamplers(builder, renderTargets); + IrisSamplers.addCustomImages(customTextureSamplerInterceptor, customImages); + IrisImages.addRenderTargetImages(builder, flipped, renderTargets); + IrisImages.addCustomImages(builder, customImages); + + IrisSamplers.addNoiseSampler(customTextureSamplerInterceptor, customTextureManager.getNoiseTexture()); + + if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { + if (shadowRenderTargets != null) { + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowRenderTargets, null, separateHardwareSamplers); + IrisImages.addShadowColorImages(builder, shadowRenderTargets, null); + } + } + + + programs[i] = builder.buildCompute(); + + this.customUniforms.mapholderToPass(builder, programs[i]); + + programs[i].setWorkGroupInfo(source.getWorkGroupRelative(), source.getWorkGroups(), FilledIndirectPointer.basedOff(shaderStorageBufferHolder, source.getIndirectPointer())); } } @@ -489,7 +678,7 @@ private ShaderInstance createShader(String name, Optional source, } return createShader(name, source.get(), key.getProgram(), key.getAlphaTest(), key.getVertexFormat(), key.getFogMode(), - key.isIntensity(), key.shouldIgnoreLightmap()); + key.isIntensity(), key.shouldIgnoreLightmap(), key.isGlint(), key.isText()); } @Override @@ -499,16 +688,20 @@ public Object2ObjectMap, String> getTextu private ShaderInstance createShader(String name, ProgramSource source, ProgramId programId, AlphaTest fallbackAlpha, VertexFormat vertexFormat, FogMode fogMode, - boolean isIntensity, boolean isFullbright) throws IOException { + boolean isIntensity, boolean isFullbright, boolean isGlint, boolean isText) throws IOException { GlFramebuffer beforeTranslucent = renderTargets.createGbufferFramebuffer(flippedAfterPrepare, source.getDirectives().getDrawBuffers()); GlFramebuffer afterTranslucent = renderTargets.createGbufferFramebuffer(flippedAfterTranslucent, source.getDirectives().getDrawBuffers()); - ShaderAttributeInputs inputs = new ShaderAttributeInputs(vertexFormat, isFullbright); + boolean isLines = programId == ProgramId.Line && resolver.has(ProgramId.Line); + + + ShaderAttributeInputs inputs = new ShaderAttributeInputs(vertexFormat, isFullbright, isLines, isGlint, isText); Supplier> flipped = () -> isBeforeTranslucent ? flippedAfterPrepare : flippedAfterTranslucent; + ExtendedShader extendedShader = NewShaderTests.create(this, name, source, programId, beforeTranslucent, afterTranslucent, - baseline, fallbackAlpha, vertexFormat, inputs, updateNotifier, this, flipped, fogMode, isIntensity, isFullbright, false, customUniforms); + baseline, fallbackAlpha, vertexFormat, inputs, updateNotifier, this, flipped, fogMode, isIntensity, isFullbright, false, isLines, customUniforms); loadedShaders.add(extendedShader); @@ -521,7 +714,7 @@ private ShaderInstance createFallbackShader(String name, ShaderKey key) throws I FallbackShader shader = NewShaderTests.createFallback(name, beforeTranslucent, afterTranslucent, key.getAlphaTest(), key.getVertexFormat(), null, this, key.getFogMode(), - key.hasDiffuseLighting(), key.isIntensity(), key.shouldIgnoreLightmap()); + key == ShaderKey.GLINT, key.isText(), key.hasDiffuseLighting(), key.isIntensity(), key.shouldIgnoreLightmap()); loadedShaders.add(shader); @@ -534,15 +727,15 @@ private ShaderInstance createShadowShader(String name, Optional s } return createShadowShader(name, source.get(), key.getProgram(), key.getAlphaTest(), key.getVertexFormat(), - key.isIntensity(), key.shouldIgnoreLightmap()); + key.isIntensity(), key.shouldIgnoreLightmap(), key.isText()); } private ShaderInstance createFallbackShadowShader(String name, ShaderKey key) throws IOException { - GlFramebuffer framebuffer = this.shadowRenderTargets.getMainRenderBuffer(); + GlFramebuffer framebuffer = shadowRenderTargets.createShadowFramebuffer(ImmutableSet.of(), new int[] { 0 }); FallbackShader shader = NewShaderTests.createFallback(name, framebuffer, framebuffer, key.getAlphaTest(), key.getVertexFormat(), BlendModeOverride.OFF, this, key.getFogMode(), - key.hasDiffuseLighting(), key.isIntensity(), key.shouldIgnoreLightmap()); + key == ShaderKey.GLINT, key.isText(), key.hasDiffuseLighting(), key.isIntensity(), key.shouldIgnoreLightmap()); loadedShaders.add(shader); @@ -550,14 +743,16 @@ private ShaderInstance createFallbackShadowShader(String name, ShaderKey key) th } private ShaderInstance createShadowShader(String name, ProgramSource source, ProgramId programId, AlphaTest fallbackAlpha, - VertexFormat vertexFormat, boolean isIntensity, boolean isFullbright) throws IOException { - GlFramebuffer framebuffer = this.shadowRenderTargets.getMainRenderBuffer(); - ShaderAttributeInputs inputs = new ShaderAttributeInputs(vertexFormat, isFullbright); + VertexFormat vertexFormat, boolean isIntensity, boolean isFullbright, boolean isText) throws IOException { + GlFramebuffer framebuffer = shadowRenderTargets.createShadowFramebuffer(ImmutableSet.of(), source.getDirectives().hasUnknownDrawBuffers() ? new int[]{0, 1} : source.getDirectives().getDrawBuffers()); + boolean isLines = programId == ProgramId.Line && resolver.has(ProgramId.Line); - Supplier> flipped = () -> (prepareBeforeShadow ? flippedAfterPrepare : flippedBeforeShadow); + ShaderAttributeInputs inputs = new ShaderAttributeInputs(vertexFormat, isFullbright, isLines, false, isText); + + Supplier> flipped = () -> flippedBeforeShadow; ExtendedShader extendedShader = NewShaderTests.create(this, name, source, programId, framebuffer, framebuffer, baseline, - fallbackAlpha, vertexFormat, inputs, updateNotifier, this, flipped, FogMode.PER_VERTEX, isIntensity, isFullbright, true, customUniforms); + fallbackAlpha, vertexFormat, inputs, updateNotifier, this, flipped, FogMode.PER_VERTEX, isIntensity, isFullbright, true, isLines, customUniforms); loadedShaders.add(extendedShader); @@ -575,6 +770,7 @@ public void addGbufferOrShadowSamplers(SamplerHolder samplers, ImageHolder image IrisSamplers.addRenderTargetSamplers(samplerHolder, flipped, renderTargets, false); IrisSamplers.addCustomTextures(samplerHolder, customTextureManager.getIrisCustomTextures()); IrisImages.addRenderTargetImages(images, flipped, renderTargets); + IrisImages.addCustomImages(images, customImages); if (!shouldBindPBR) { shouldBindPBR = IrisSamplers.hasPBRSamplers(samplerHolder); @@ -583,13 +779,14 @@ public void addGbufferOrShadowSamplers(SamplerHolder samplers, ImageHolder image IrisSamplers.addLevelSamplers(samplers, this, whitePixel, availability); IrisSamplers.addWorldDepthSamplers(samplerHolder, this.renderTargets); IrisSamplers.addNoiseSampler(samplerHolder, this.customTextureManager.getNoiseTexture()); + IrisSamplers.addCustomImages(samplerHolder, customImages); if (isShadowPass || IrisSamplers.hasShadowSamplers(samplerHolder)) { if (!isShadowPass) { shadowTargetsSupplier.get(); } - IrisSamplers.addShadowSamplers(samplerHolder, Objects.requireNonNull(shadowRenderTargets), null); + IrisSamplers.addShadowSamplers(samplerHolder, Objects.requireNonNull(shadowRenderTargets), null, separateHardwareSamplers); } if (isShadowPass || IrisImages.hasShadowImages(images)) { @@ -667,6 +864,12 @@ public void onSetShaderTexture(int id) { } } + @Override + public void onShadowBufferChange() { + this.shadowClearPasses = ClearPassCreator.createShadowClearPasses(shadowRenderTargets, false, shadowDirectives); + this.shadowClearPassesFull = ClearPassCreator.createShadowClearPasses(shadowRenderTargets, true, shadowDirectives); + } + @Override public void beginLevelRendering() { isRenderingWorld = true; @@ -675,6 +878,10 @@ public void beginLevelRendering() { RenderSystem.activeTexture(GL15C.GL_TEXTURE0); Vector4f emptyClearColor = new Vector4f(1.0F); + for (GlImage image : clearImages) { + ARBClearTexture.glClearTexImage(image.getId(), 0, image.getFormat().getGlFormat(), image.getPixelType().getGlFormat(), (int[]) null); + } + if (shadowRenderTargets != null) { if (packDirectives.getShadowDirectives().isShadowEnabled() == OptionalBoolean.FALSE) { if (shadowRenderTargets.isFullClearRequired()) { @@ -727,10 +934,16 @@ public void beginLevelRendering() { main.height, depthBufferFormat, packDirectives); if (changed) { + beginRenderer.recalculateSizes(); prepareRenderer.recalculateSizes(); deferredRenderer.recalculateSizes(); compositeRenderer.recalculateSizes(); finalPassRenderer.recalculateSwapPassSize(); + if (shaderStorageBufferHolder != null) { + shaderStorageBufferHolder.hasResizedScreen(main.width, main.height); + } + + customImages.forEach(image -> image.updateNewSize(main.width, main.height)); this.clearPassesFull.forEach(clearPass -> renderTargets.destroyFramebuffer(clearPass.getFramebuffer())); this.clearPasses.forEach(clearPass -> renderTargets.destroyFramebuffer(clearPass.getFramebuffer())); @@ -741,6 +954,11 @@ public void beginLevelRendering() { packDirectives.getRenderTargetDirectives()); } + if (changed || IrisVideoSettings.colorSpace != currentColorSpace) { + currentColorSpace = IrisVideoSettings.colorSpace; + colorSpaceConverter.rebuildProgram(main.width, main.height, currentColorSpace); + } + final ImmutableList passes; if (renderTargets.isFullClearRequired()) { @@ -768,8 +986,26 @@ public void beginLevelRendering() { main.bindWrite(true); isMainBound = true; + if (changed) { + boolean hasRun = false; + + for (ComputeProgram program : setup) { + if (program != null) { + hasRun = true; + program.use(); + program.dispatch(1, 1); + } + } + + if (hasRun) { + ComputeProgram.unbind(); + } + } + isBeforeTranslucent = true; + beginRenderer.renderAll(); + setPhase(WorldRenderingPhase.SKY); // Render our horizon box before actual sky rendering to avoid being broken by mods that do weird things @@ -793,17 +1029,11 @@ public void beginLevelRendering() { @Override public void renderShadows(LevelRendererAccessor worldRenderer, Camera playerCamera) { - if (prepareBeforeShadow) { - prepareRenderer.renderAll(); - } - if (shadowRenderer != null) { this.shadowRenderer.renderShadows(worldRenderer, playerCamera); } - if (!prepareBeforeShadow) { - prepareRenderer.renderAll(); - } + prepareRenderer.renderAll(); } @Override @@ -824,6 +1054,8 @@ public OptionalInt getForcedShadowRenderDistanceChunksForDisplay() { @Override public void beginHand() { + centerDepthSampler.sampleCenterDepth(); + // We need to copy the current depth texture so that depthtex2 can contain the depth values for // all non-translucent content excluding the hand, as required. renderTargets.copyPreHandDepth(); @@ -861,11 +1093,15 @@ public void beginTranslucents() { @Override public void finalizeLevelRendering() { isRenderingWorld = false; - centerDepthSampler.sampleCenterDepth(); compositeRenderer.renderAll(); finalPassRenderer.renderFinalPass(); } + @Override + public void finalizeGameRendering() { + colorSpaceConverter.process(Minecraft.getInstance().getMainRenderTarget().getColorTextureId()); + } + @Override public boolean shouldDisableVanillaEntityShadows() { // OptiFine seems to disable vanilla shadows when the shaderpack uses shadow mapping? @@ -907,11 +1143,21 @@ public boolean allowConcurrentCompute() { return allowConcurrentCompute; } + @Override + public boolean hasFeature(FeatureFlags flag) { + return pack.hasFeature(flag); + } + @Override public boolean shouldDisableDirectionalShading() { return !oldLighting; } + @Override + public boolean shouldDisableFrustumCulling() { + return !frustumCulling; + } + @Override public CloudSetting getCloudSetting() { return cloudSetting; @@ -945,6 +1191,7 @@ public void destroy() { // Without this code, there will be weird issues when reloading certain shaderpacks. for (int i = 0; i < 16; i++) { GlStateManager.glActiveTexture(GL20C.GL_TEXTURE0 + i); + IrisRenderSystem.unbindAllSamplers(); GlStateManager._bindTexture(0); } @@ -980,9 +1227,15 @@ public void destroy() { renderTargets.destroy(); + customImages.forEach(GlImage::destroy); + if (shadowRenderer != null) { shadowRenderer.destroy(); } + + if (shaderStorageBufferHolder != null) { + shaderStorageBufferHolder.destroyBuffers(); + } } @Override @@ -1005,6 +1258,11 @@ public float getSunPathRotation() { return sunPathRotation; } + @Override + public DHCompat getDHCompat() { + return dhCompat; + } + protected AbstractTexture getWhitePixel() { return whitePixel; } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderAttributeInputs.java b/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderAttributeInputs.java index b01c98ff65..0f37a37c73 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderAttributeInputs.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderAttributeInputs.java @@ -11,12 +11,18 @@ public class ShaderAttributeInputs { private boolean light; private boolean normal; private boolean newLines; + private boolean glint; + private boolean text; + // WARNING: adding new fields requires updating hashCode and equals methods! - public ShaderAttributeInputs(VertexFormat format, boolean isFullbright) { - if (format == DefaultVertexFormat.POSITION_COLOR_NORMAL) { + public ShaderAttributeInputs(VertexFormat format, boolean isFullbright, boolean isLines, boolean glint, boolean text) { + if (format == DefaultVertexFormat.POSITION_COLOR_NORMAL && !isLines) { newLines = true; } + this.text = text; + this.glint = glint; + format.getElementAttributeNames().forEach(name -> { if ("Color".equals(name)) { color = true; @@ -81,11 +87,13 @@ public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (color ? 1231 : 1237); + result = prime * result + (tex ? 1231 : 1237); + result = prime * result + (overlay ? 1231 : 1237); result = prime * result + (light ? 1231 : 1237); - result = prime * result + (newLines ? 1231 : 1237); result = prime * result + (normal ? 1231 : 1237); - result = prime * result + (overlay ? 1231 : 1237); - result = prime * result + (tex ? 1231 : 1237); + result = prime * result + (newLines ? 1231 : 1237); + result = prime * result + (glint ? 1231 : 1237); + result = prime * result + (text ? 1231 : 1237); return result; } @@ -100,16 +108,22 @@ public boolean equals(Object obj) { ShaderAttributeInputs other = (ShaderAttributeInputs) obj; if (color != other.color) return false; - if (light != other.light) + if (tex != other.tex) return false; - if (newLines != other.newLines) + if (overlay != other.overlay) + return false; + if (light != other.light) return false; if (normal != other.normal) return false; - if (overlay != other.overlay) + if (newLines != other.newLines) return false; - if (tex != other.tex) + if (text != other.text) return false; return true; } + + public boolean isText() { + return text; + } } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderInstanceInterface.java b/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderInstanceInterface.java index 1d4a6c683d..a06505c06d 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderInstanceInterface.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderInstanceInterface.java @@ -1,10 +1,9 @@ package net.coderbot.iris.pipeline.newshader; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceProvider; import java.io.IOException; public interface ShaderInstanceInterface { - void iris$createGeometryShader(ResourceProvider factory, ResourceLocation name) throws IOException; + void iris$createExtraShaders(ResourceProvider factory, String name) throws IOException; } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderKey.java b/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderKey.java index 9e308632ef..67615e2bc7 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderKey.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderKey.java @@ -20,9 +20,8 @@ public enum ShaderKey { SKY_TEXTURED (ProgramId.SkyTextured, AlphaTests.OFF, DefaultVertexFormat.POSITION_TEX, FogMode.OFF, LightingModel.LIGHTMAP ), SKY_TEXTURED_COLOR (ProgramId.SkyTextured, AlphaTests.OFF, DefaultVertexFormat.POSITION_TEX_COLOR, FogMode.OFF, LightingModel.LIGHTMAP ), CLOUDS (ProgramId.Clouds, AlphaTests.ONE_TENTH_ALPHA, DefaultVertexFormat.POSITION_TEX_COLOR_NORMAL, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), - TERRAIN_SOLID (ProgramId.Terrain, AlphaTests.OFF, IrisVertexFormats.TERRAIN, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), - TERRAIN_CUTOUT (ProgramId.Terrain, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.TERRAIN, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), - TERRAIN_CUTOUT_MIPPED (ProgramId.Terrain, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.TERRAIN, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + TERRAIN_SOLID (ProgramId.TerrainSolid,AlphaTests.OFF, IrisVertexFormats.TERRAIN, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + TERRAIN_CUTOUT (ProgramId.TerrainCutout,AlphaTests.ONE_TENTH_ALPHA,IrisVertexFormats.TERRAIN, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), TERRAIN_TRANSLUCENT (ProgramId.Water, AlphaTests.OFF, IrisVertexFormats.TERRAIN, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), MOVING_BLOCK (ProgramId.Block, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.TERRAIN, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), ENTITIES_ALPHA (ProgramId.Entities, AlphaTests.VERTEX_ALPHA, IrisVertexFormats.ENTITY, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), @@ -36,26 +35,28 @@ public enum ShaderKey { HAND_CUTOUT (ProgramId.Hand, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.ENTITY, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), HAND_CUTOUT_BRIGHT (ProgramId.Hand, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.ENTITY, FogMode.PER_VERTEX, LightingModel.FULLBRIGHT), HAND_CUTOUT_DIFFUSE (ProgramId.Hand, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.ENTITY, FogMode.PER_VERTEX, LightingModel.DIFFUSE_LM), - HAND_TEXT (ProgramId.Hand, AlphaTests.NON_ZERO_ALPHA, IrisVertexFormats.TERRAIN , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), - HAND_TEXT_INTENSITY (ProgramId.Hand, AlphaTests.NON_ZERO_ALPHA, IrisVertexFormats.TERRAIN , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + HAND_TEXT (ProgramId.Hand, AlphaTests.NON_ZERO_ALPHA, IrisVertexFormats.ENTITY , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + HAND_TEXT_INTENSITY (ProgramId.Hand, AlphaTests.NON_ZERO_ALPHA, IrisVertexFormats.ENTITY , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), HAND_TRANSLUCENT (ProgramId.HandWater, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.ENTITY, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), HAND_WATER_BRIGHT (ProgramId.HandWater, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.ENTITY, FogMode.PER_VERTEX, LightingModel.FULLBRIGHT), HAND_WATER_DIFFUSE (ProgramId.HandWater, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.ENTITY, FogMode.PER_VERTEX, LightingModel.DIFFUSE_LM), LIGHTNING (ProgramId.Entities, AlphaTests.OFF, DefaultVertexFormat.POSITION_COLOR, FogMode.PER_VERTEX, LightingModel.FULLBRIGHT), LEASH (ProgramId.Basic, AlphaTests.OFF, DefaultVertexFormat.POSITION_COLOR_LIGHTMAP, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), - PARTICLES (ProgramId.TexturedLit, AlphaTests.ONE_TENTH_ALPHA, DefaultVertexFormat.PARTICLE, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + PARTICLES (ProgramId.Particles, AlphaTests.ONE_TENTH_ALPHA, DefaultVertexFormat.PARTICLE, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + PARTICLES_TRANS (ProgramId.ParticlesTrans,AlphaTests.ONE_TENTH_ALPHA,DefaultVertexFormat.PARTICLE, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), WEATHER (ProgramId.Weather, AlphaTests.ONE_TENTH_ALPHA, DefaultVertexFormat.PARTICLE, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), CRUMBLING (ProgramId.DamagedBlock,AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.TERRAIN, FogMode.OFF, LightingModel.LIGHTMAP ), - TEXT (ProgramId.Entities, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.TERRAIN , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), - TEXT_INTENSITY (ProgramId.Entities, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.TERRAIN , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), - TEXT_BE (ProgramId.Block, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.TERRAIN , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), - TEXT_INTENSITY_BE (ProgramId.Block, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.TERRAIN , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + TEXT (ProgramId.EntitiesTrans,AlphaTests.ONE_TENTH_ALPHA,IrisVertexFormats.ENTITY , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + TEXT_INTENSITY (ProgramId.EntitiesTrans,AlphaTests.ONE_TENTH_ALPHA,IrisVertexFormats.ENTITY , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + TEXT_BE (ProgramId.BlockTrans, AlphaTests.ONE_TENTH_ALPHA,IrisVertexFormats.ENTITY , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + TEXT_INTENSITY_BE (ProgramId.BlockTrans, AlphaTests.ONE_TENTH_ALPHA,IrisVertexFormats.ENTITY , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), BLOCK_ENTITY (ProgramId.Block, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.ENTITY, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), BLOCK_ENTITY_BRIGHT (ProgramId.Block, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.ENTITY, FogMode.PER_VERTEX, LightingModel.FULLBRIGHT), BLOCK_ENTITY_DIFFUSE (ProgramId.Block, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.ENTITY, FogMode.PER_VERTEX, LightingModel.DIFFUSE_LM), + BE_TRANSLUCENT (ProgramId.BlockTrans, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.ENTITY, FogMode.PER_VERTEX, LightingModel.DIFFUSE_LM), BEACON (ProgramId.BeaconBeam, AlphaTests.OFF, DefaultVertexFormat.BLOCK, FogMode.PER_FRAGMENT, LightingModel.FULLBRIGHT), GLINT (ProgramId.ArmorGlint, AlphaTests.NON_ZERO_ALPHA, DefaultVertexFormat.POSITION_TEX, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), - LINES (ProgramId.Basic, AlphaTests.OFF, DefaultVertexFormat.POSITION_COLOR_NORMAL, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + LINES (ProgramId.Line, AlphaTests.OFF, DefaultVertexFormat.POSITION_COLOR_NORMAL, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), // Note: These must be at the very end (NewWorldRenderingPipeline implementation details) SHADOW_TERRAIN_CUTOUT (ProgramId.Shadow, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.TERRAIN, FogMode.OFF, LightingModel.LIGHTMAP ), @@ -70,8 +71,8 @@ public enum ShaderKey { SHADOW_LEASH (ProgramId.Shadow, AlphaTests.OFF, DefaultVertexFormat.POSITION_COLOR_LIGHTMAP, FogMode.OFF, LightingModel.LIGHTMAP ), SHADOW_LIGHTNING (ProgramId.Shadow, AlphaTests.OFF, DefaultVertexFormat.POSITION_COLOR, FogMode.OFF, LightingModel.FULLBRIGHT), SHADOW_PARTICLES (ProgramId.Shadow, AlphaTests.ONE_TENTH_ALPHA, DefaultVertexFormat.PARTICLE, FogMode.OFF, LightingModel.LIGHTMAP ), - SHADOW_TEXT (ProgramId.Shadow, AlphaTests.NON_ZERO_ALPHA, IrisVertexFormats.TERRAIN , FogMode.OFF, LightingModel.LIGHTMAP ), - SHADOW_TEXT_INTENSITY (ProgramId.Shadow, AlphaTests.NON_ZERO_ALPHA, IrisVertexFormats.TERRAIN , FogMode.OFF, LightingModel.LIGHTMAP ); + SHADOW_TEXT (ProgramId.Shadow, AlphaTests.NON_ZERO_ALPHA, IrisVertexFormats.ENTITY , FogMode.OFF, LightingModel.LIGHTMAP ), + SHADOW_TEXT_INTENSITY (ProgramId.Shadow, AlphaTests.NON_ZERO_ALPHA, IrisVertexFormats.ENTITY , FogMode.OFF, LightingModel.LIGHTMAP ); private final ProgramId program; private final AlphaTest alphaTest; @@ -123,6 +124,14 @@ public boolean shouldIgnoreLightmap() { return lightingModel == LightingModel.FULLBRIGHT || lightingModel == LightingModel.DIFFUSE; } + public boolean isGlint() { + return this == GLINT; + } + + public boolean isText() { + return this.name().contains("TEXT"); + } + enum LightingModel { FULLBRIGHT, LIGHTMAP, diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/fallback/ShaderSynthesizer.java b/src/main/java/net/coderbot/iris/pipeline/newshader/fallback/ShaderSynthesizer.java index cb20ec4134..5f8577bed9 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/fallback/ShaderSynthesizer.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/fallback/ShaderSynthesizer.java @@ -165,6 +165,8 @@ public static String fsh(ShaderAttributeInputs inputs, FogMode fogMode, AlphaTes } shader.append("in vec4 iris_vertexColor;\n"); + main.append("float iris_vertexColorAlpha = iris_vertexColor.a;"); + if (inputs.hasTex()) { shader.append("uniform sampler2D gtexture;\n"); shader.append("in vec2 texCoord;\n"); diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/PatchShaderType.java b/src/main/java/net/coderbot/iris/pipeline/transform/PatchShaderType.java index 635f2a7df8..a3c8474b69 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/PatchShaderType.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/PatchShaderType.java @@ -3,16 +3,19 @@ import net.coderbot.iris.gl.shader.ShaderType; public enum PatchShaderType { - VERTEX(ShaderType.VERTEX), - GEOMETRY(ShaderType.GEOMETRY), - FRAGMENT(ShaderType.FRAGMENT), - FRAGMENT_CUTOUT(ShaderType.FRAGMENT), - COMPUTE(ShaderType.COMPUTE); + VERTEX(ShaderType.VERTEX, ".vsh"), + GEOMETRY(ShaderType.GEOMETRY, ".gsh"), + TESS_CONTROL(ShaderType.TESSELATION_CONTROL, ".tcs"), + TESS_EVAL(ShaderType.TESSELATION_EVAL, ".tes"), + FRAGMENT(ShaderType.FRAGMENT, ".fsh"), + COMPUTE(ShaderType.COMPUTE, ".csh"); public final ShaderType glShaderType; + public final String extension; - private PatchShaderType(ShaderType glShaderType) { + private PatchShaderType(ShaderType glShaderType, String extension) { this.glShaderType = glShaderType; + this.extension = extension; } public static PatchShaderType[] fromGlShaderType(ShaderType glShaderType) { @@ -21,10 +24,14 @@ public static PatchShaderType[] fromGlShaderType(ShaderType glShaderType) { return new PatchShaderType[] { VERTEX }; case GEOMETRY: return new PatchShaderType[] { GEOMETRY }; + case TESSELATION_CONTROL: + return new PatchShaderType[] { TESS_CONTROL }; + case TESSELATION_EVAL: + return new PatchShaderType[] { TESS_EVAL }; case COMPUTE: return new PatchShaderType[] { COMPUTE }; case FRAGMENT: - return new PatchShaderType[] { FRAGMENT, FRAGMENT_CUTOUT }; + return new PatchShaderType[] { FRAGMENT }; default: throw new IllegalArgumentException("Unknown shader type: " + glShaderType); } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java b/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java index 4a5a38e0e6..49e10f7869 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java @@ -6,8 +6,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import repack.antlr.v4.runtime.RecognitionException; import repack.antlr.v4.runtime.Token; +import repack.antlr.v4.runtime.misc.ParseCancellationException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -17,31 +17,37 @@ import io.github.douira.glsl_transformer.ast.node.VersionStatement; import io.github.douira.glsl_transformer.ast.print.PrintType; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.query.index.PrefixIdentifierIndex; +import io.github.douira.glsl_transformer.ast.query.RootSupplier; import io.github.douira.glsl_transformer.ast.transform.EnumASTTransformer; +import io.github.douira.glsl_transformer.ast.transform.TransformationException; +import io.github.douira.glsl_transformer.parser.ParsingException; import io.github.douira.glsl_transformer.token_filter.ChannelFilter; import io.github.douira.glsl_transformer.token_filter.TokenChannel; import io.github.douira.glsl_transformer.token_filter.TokenFilter; import io.github.douira.glsl_transformer.util.LRUCache; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.Iris; import net.coderbot.iris.gbuffer_overrides.matching.InputAvailability; import net.coderbot.iris.gl.blending.AlphaTest; import net.coderbot.iris.gl.texture.TextureType; import net.coderbot.iris.helpers.Tri; -import net.coderbot.iris.pipeline.PatchedShaderPrinter; +import net.coderbot.iris.pipeline.ShaderPrinter; import net.coderbot.iris.pipeline.newshader.ShaderAttributeInputs; import net.coderbot.iris.pipeline.transform.parameter.AttributeParameters; -import net.coderbot.iris.pipeline.transform.parameter.CompositeParameters; import net.coderbot.iris.pipeline.transform.parameter.ComputeParameters; import net.coderbot.iris.pipeline.transform.parameter.Parameters; import net.coderbot.iris.pipeline.transform.parameter.SodiumParameters; +import net.coderbot.iris.pipeline.transform.parameter.TextureStageParameters; import net.coderbot.iris.pipeline.transform.parameter.VanillaParameters; import net.coderbot.iris.pipeline.transform.transformer.AttributeTransformer; import net.coderbot.iris.pipeline.transform.transformer.CommonTransformer; import net.coderbot.iris.pipeline.transform.transformer.CompatibilityTransformer; +import net.coderbot.iris.pipeline.transform.transformer.CompositeCoreTransformer; import net.coderbot.iris.pipeline.transform.transformer.CompositeTransformer; +import net.coderbot.iris.pipeline.transform.transformer.SodiumCoreTransformer; import net.coderbot.iris.pipeline.transform.transformer.SodiumTransformer; import net.coderbot.iris.pipeline.transform.transformer.TextureTransformer; +import net.coderbot.iris.pipeline.transform.transformer.VanillaCoreTransformer; import net.coderbot.iris.pipeline.transform.transformer.VanillaTransformer; import net.coderbot.iris.shaderpack.texture.TextureStage; @@ -71,13 +77,17 @@ private static class CacheKey { final Parameters parameters; final String vertex; final String geometry; + final String tessControl; + final String tessEval; final String fragment; final String compute; - public CacheKey(Parameters parameters, String vertex, String geometry, String fragment) { + public CacheKey(Parameters parameters, String vertex, String geometry, String tessControl, String tessEval, String fragment) { this.parameters = parameters; this.vertex = vertex; this.geometry = geometry; + this.tessControl = tessControl; + this.tessEval = tessEval; this.fragment = fragment; this.compute = null; } @@ -86,6 +96,8 @@ public CacheKey(Parameters parameters, String compute) { this.parameters = parameters; this.vertex = null; this.geometry = null; + this.tessControl = null; + this.tessEval = null; this.fragment = null; this.compute = compute; } @@ -97,6 +109,8 @@ public int hashCode() { result = prime * result + ((parameters == null) ? 0 : parameters.hashCode()); result = prime * result + ((vertex == null) ? 0 : vertex.hashCode()); result = prime * result + ((geometry == null) ? 0 : geometry.hashCode()); + result = prime * result + ((tessControl == null) ? 0 : tessControl.hashCode()); + result = prime * result + ((tessEval == null) ? 0 : tessEval.hashCode()); result = prime * result + ((fragment == null) ? 0 : fragment.hashCode()); result = prime * result + ((compute == null) ? 0 : compute.hashCode()); return result; @@ -126,6 +140,16 @@ public boolean equals(Object obj) { return false; } else if (!geometry.equals(other.geometry)) return false; + if (tessControl == null) { + if (other.tessControl != null) + return false; + } else if (!tessControl.equals(other.tessControl)) + return false; + if (tessEval == null) { + if (other.tessEval != null) + return false; + } else if (!tessEval.equals(other.tessEval)) + return false; if (fragment == null) { if (other.fragment != null) return false; @@ -156,10 +180,13 @@ public boolean isTokenAllowed(Token token) { private static final List internalPrefixes = List.of("iris_", "irisMain", "moj_import"); static { - Root.identifierIndexFactory = PrefixIdentifierIndex::withPrefix; transformer = new EnumASTTransformer(PatchShaderType.class) { + { + setRootSupplier(RootSupplier.PREFIX_UNORDERED_ED_EXACT); + } + @Override - public TranslationUnit parseTranslationUnit(String input) throws RecognitionException { + public TranslationUnit parseTranslationUnit(Root rootInstance, String input) { // parse #version directive using an efficient regex before parsing so that the // parser can be set to the correct version Matcher matcher = versionPattern.matcher(input); @@ -167,13 +194,9 @@ public TranslationUnit parseTranslationUnit(String input) throws RecognitionExce throw new IllegalArgumentException( "No #version directive found in source code! See debugging.md for more information."); } - Version version = Version.fromNumber(Integer.parseInt(matcher.group(1))); - if (version.number >= 200) { - version = Version.GLSL33; - } - transformer.getLexer().version = version; + transformer.getLexer().version = Version.fromNumber(Integer.parseInt(matcher.group(1))); - return super.parseTranslationUnit(input); + return super.parseTranslationUnit(rootInstance, input); } }; transformer.setTransformation((trees, parameters) -> { @@ -197,7 +220,7 @@ public TranslationUnit parseTranslationUnit(String input) throws RecognitionExce + id.getName() + ". See debugging.md for more information."); }); - Root.indexBuildSession(tree, () -> { + root.indexBuildSession(() -> { VersionStatement versionStatement = tree.getVersionStatement(); if (versionStatement == null) { throw new IllegalStateException("Missing the version statement!"); @@ -206,74 +229,67 @@ public TranslationUnit parseTranslationUnit(String input) throws RecognitionExce Version version = versionStatement.version; switch (parameters.patch) { case ATTRIBUTES: - AttributeParameters attributeParameters = (AttributeParameters) parameters; - AttributeTransformer.transform(transformer, tree, root, attributeParameters); - TextureTransformer.transform(transformer, tree, root, - TextureStage.GBUFFERS_AND_SHADOW, - attributeParameters.getTextureMap()); + AttributeTransformer.transform(transformer, tree, root, (AttributeParameters) parameters); break; case COMPUTE: // we can assume the version is at least 400 because it's a compute shader versionStatement.profile = Profile.CORE; - CommonTransformer.transform(transformer, tree, root, parameters); - TextureTransformer.transform(transformer, tree, root, ((ComputeParameters) parameters).getStage(), ((ComputeParameters) parameters).getTextureMap()); + CommonTransformer.transform(transformer, tree, root, parameters, true); break; default: // TODO: Implement Optifine's special core profile mode - if (profile == Profile.CORE || version.number >= 150 && profile == null) { - if (parameters.type == PatchShaderType.VERTEX) { - throw new IllegalStateException( - "Vertex shaders with existing core profile found, aborting this part of patching. (Compatibility patches are applied nonetheless) See debugging.md for more information."); - } else { - if (parameters instanceof CompositeParameters compositeParameters) { - TextureTransformer.transform(transformer, tree, root, - compositeParameters.stage, - compositeParameters.getTextureMap()); - } else { - TextureTransformer.transform(transformer, tree, root, TextureStage.GBUFFERS_AND_SHADOW, parameters instanceof SodiumParameters parameters1 ? parameters1.getTextureMap() : ((VanillaParameters) parameters).getTextureMap()); - } - break; + // handling of Optifine's special core profile mode + boolean isLine = (parameters.patch == Patch.VANILLA && ((VanillaParameters) parameters).isLines()); + + if (profile == Profile.CORE || version.number >= 150 && profile == null || isLine) { + // patch the version number to at least 330 + if (version.number < 330) { + versionStatement.version = Version.GLSL33; } - } - if (version.number >= 330) { - if (profile != Profile.COMPATIBILITY) { - throw new IllegalStateException( - "Expected \"compatibility\" after the GLSL version: #version " + version + " " - + profile + ". See debugging.md for more information."); + + switch (parameters.patch) { + case COMPOSITE: + CompositeCoreTransformer.transform(transformer, tree, root, parameters); + break; + case SODIUM: + SodiumParameters sodiumParameters = (SodiumParameters) parameters; + SodiumCoreTransformer.transform(transformer, tree, root, sodiumParameters); + break; + case VANILLA: + VanillaCoreTransformer.transform(transformer, tree, root, (VanillaParameters) parameters); + break; + default: + throw new UnsupportedOperationException("Unknown patch type: " + parameters.patch); + } + + if (parameters.type == PatchShaderType.FRAGMENT) { + CompatibilityTransformer.transformFragmentCore(transformer, tree, root, parameters); } - versionStatement.profile = Profile.CORE; } else { - versionStatement.version = Version.GLSL33; + // patch the version number to at least 330 + if (version.number < 330) { + versionStatement.version = Version.GLSL33; + } versionStatement.profile = Profile.CORE; - } - switch (parameters.patch) { - case COMPOSITE: - CompositeParameters compositeParameters = (CompositeParameters) parameters; - CompositeTransformer.transform(transformer, tree, root, parameters); - TextureTransformer.transform(transformer, tree, root, - compositeParameters.stage, - compositeParameters.getTextureMap()); - break; - case SODIUM: - SodiumParameters sodiumParameters = (SodiumParameters) parameters; - sodiumParameters.setAlphaFor(type); - SodiumTransformer.transform(transformer, tree, root, sodiumParameters); - TextureTransformer.transform(transformer, tree, root, - TextureStage.GBUFFERS_AND_SHADOW, - sodiumParameters.getTextureMap()); - break; - case VANILLA: - VanillaParameters vanillaParameters = (VanillaParameters) parameters; - VanillaTransformer.transform(transformer, tree, root, vanillaParameters); - TextureTransformer.transform(transformer, tree, root, - TextureStage.GBUFFERS_AND_SHADOW, - vanillaParameters.getTextureMap()); - break; - default: - throw new UnsupportedOperationException("Unknown patch type: " + parameters.patch); - } + switch (parameters.patch) { + case COMPOSITE: + CompositeTransformer.transform(transformer, tree, root, parameters); + break; + case SODIUM: + SodiumParameters sodiumParameters = (SodiumParameters) parameters; + SodiumTransformer.transform(transformer, tree, root, sodiumParameters); + break; + case VANILLA: + VanillaTransformer.transform(transformer, tree, root, (VanillaParameters) parameters); + break; + default: + throw new UnsupportedOperationException("Unknown patch type: " + parameters.patch); + } + } } + TextureTransformer.transform(transformer, tree, root, + parameters.getTextureStage(), parameters.getTextureMap()); CompatibilityTransformer.transformEach(transformer, tree, root, parameters); }); } @@ -286,10 +302,22 @@ public TranslationUnit parseTranslationUnit(String input) throws RecognitionExce private static final Pattern versionPattern = Pattern.compile("^.*#version\\s+(\\d+)", Pattern.DOTALL); - private static Map transform(String vertex, String geometry, String fragment, + private static Map transformInternal( + Map inputs, + Parameters parameters) { + try { + return transformer.transform(inputs, parameters); + } catch (TransformationException | ParsingException | IllegalStateException | IllegalArgumentException e) { + // print the offending programs and rethrow to stop the loading process + ShaderPrinter.printProgram("errored_program").addSources(inputs).print(); + throw e; + } + } + + private static Map transform(String vertex, String geometry, String tessControl, String tessEval, String fragment, Parameters parameters) { // stop if all are null - if (vertex == null && geometry == null && fragment == null) { + if (vertex == null && geometry == null && tessControl == null && tessEval == null && fragment == null) { return null; } @@ -297,7 +325,7 @@ private static Map transform(String vertex, String geom CacheKey key; Map result = null; if (useCache) { - key = new CacheKey(parameters, vertex, geometry, fragment); + key = new CacheKey(parameters, vertex, geometry, tessControl, tessEval, fragment); if (cache.containsKey(key)) { result = cache.get(key); } @@ -305,18 +333,15 @@ private static Map transform(String vertex, String geom // if there is no cache result, transform the shaders if (result == null) { - transformer.setPrintType(PatchedShaderPrinter.prettyPrintShaders ? PrintType.INDENTED : PrintType.SIMPLE); + transformer.setPrintType(Iris.getIrisConfig().areDebugOptionsEnabled() ? PrintType.INDENTED : PrintType.SIMPLE); EnumMap inputs = new EnumMap<>(PatchShaderType.class); inputs.put(PatchShaderType.VERTEX, vertex); inputs.put(PatchShaderType.GEOMETRY, geometry); + inputs.put(PatchShaderType.TESS_CONTROL, tessControl); + inputs.put(PatchShaderType.TESS_EVAL, tessEval); inputs.put(PatchShaderType.FRAGMENT, fragment); - // the sodium terrain transformer transforms the fragment shader twice - if (parameters instanceof SodiumParameters && ((SodiumParameters) parameters).hasCutoutAlpha()) { - inputs.put(PatchShaderType.FRAGMENT_CUTOUT, fragment); - } - - result = transformer.transform(inputs, parameters); + result = transformInternal(inputs, parameters); if (useCache) { cache.put(key, result); } @@ -342,11 +367,11 @@ private static Map transformCompute(String compute, Par // if there is no cache result, transform the shaders if (result == null) { - transformer.setPrintType(PatchedShaderPrinter.prettyPrintShaders ? PrintType.INDENTED : PrintType.SIMPLE); + transformer.setPrintType(Iris.getIrisConfig().areDebugOptionsEnabled() ? PrintType.INDENTED : PrintType.SIMPLE); EnumMap inputs = new EnumMap<>(PatchShaderType.class); inputs.put(PatchShaderType.COMPUTE, compute); - result = transformer.transform(inputs, parameters); + result = transformInternal(inputs, parameters); if (useCache) { cache.put(key, result); } @@ -354,35 +379,37 @@ private static Map transformCompute(String compute, Par return result; } - public static Map patchAttributes(String vertex, String geometry, String fragment, - InputAvailability inputs, Object2ObjectMap, String> textureMap) { - return transform(vertex, geometry, fragment, - new AttributeParameters(Patch.ATTRIBUTES, geometry != null, inputs, textureMap)); - } - public static Map patchVanilla( - String vertex, String geometry, String fragment, AlphaTest alpha, - boolean hasChunkOffset, ShaderAttributeInputs inputs, + String vertex, String geometry, String tessControl, String tessEval, String fragment, + AlphaTest alpha, boolean isLines, + boolean hasChunkOffset, + ShaderAttributeInputs inputs, Object2ObjectMap, String> textureMap) { - return transform(vertex, geometry, fragment, - new VanillaParameters(Patch.VANILLA, alpha, hasChunkOffset, inputs, geometry != null, textureMap)); + return transform(vertex, geometry, tessControl, tessEval, fragment, + new VanillaParameters(Patch.VANILLA, textureMap, alpha, isLines, hasChunkOffset, inputs, geometry != null, tessControl != null || tessEval != null)); } - public static Map patchSodium(String vertex, String geometry, String fragment, - AlphaTest cutoutAlpha, AlphaTest defaultAlpha, ShaderAttributeInputs inputs, + public static Map patchSodium(String vertex, String geometry, String tessControl, String tessEval, String fragment, + AlphaTest alpha, ShaderAttributeInputs inputs, float positionScale, float positionOffset, float textureScale, Object2ObjectMap, String> textureMap) { - return transform(vertex, geometry, fragment, - new SodiumParameters(Patch.SODIUM, cutoutAlpha, defaultAlpha, inputs, positionScale, positionOffset, - textureScale, textureMap)); + return transform(vertex, geometry, tessControl, tessEval, fragment, + new SodiumParameters(Patch.SODIUM, textureMap, alpha, inputs, positionScale, positionOffset, + textureScale)); } - public static Map patchComposite(String vertex, String geometry, String fragment, - TextureStage stage, Object2ObjectMap, String> textureMap) { - return transform(vertex, geometry, fragment, new CompositeParameters(Patch.COMPOSITE, stage, textureMap)); + public static Map patchComposite( + String vertex, String geometry, String fragment, + TextureStage stage, + Object2ObjectMap, String> textureMap) { + return transform(vertex, geometry, null, null, fragment, new TextureStageParameters(Patch.COMPOSITE, stage, textureMap)); } - public static String patchCompute(String compute, TextureStage stage, Object2ObjectMap, String> textureMap) { - return transformCompute(compute, new ComputeParameters(Patch.COMPUTE, stage, textureMap)).getOrDefault(PatchShaderType.COMPUTE, null); + public static String patchCompute( + String compute, + TextureStage stage, + Object2ObjectMap, String> textureMap) { + return transformCompute(compute, new ComputeParameters(Patch.COMPUTE, stage, textureMap)) + .getOrDefault(PatchShaderType.COMPUTE, null); } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/AttributeParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/AttributeParameters.java index be305f70ab..fd9a81ecfe 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/AttributeParameters.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/AttributeParameters.java @@ -7,18 +7,21 @@ import net.coderbot.iris.pipeline.transform.Patch; import net.coderbot.iris.shaderpack.texture.TextureStage; -public class AttributeParameters extends OverlayParameters { +public class AttributeParameters extends GeometryInfoParameters { public final InputAvailability inputs; - private final Object2ObjectMap, String> textureMap; + // WARNING: adding new fields requires updating hashCode and equals methods! - public AttributeParameters(Patch patch, boolean hasGeometry, InputAvailability inputs, Object2ObjectMap, String> textureMap) { - super(patch, hasGeometry); + public AttributeParameters(Patch patch, + Object2ObjectMap, String> textureMap, + boolean hasGeometry, + InputAvailability inputs) { + super(patch, textureMap, hasGeometry, false); this.inputs = inputs; - this.textureMap = textureMap; } - public Object2ObjectMap, String> getTextureMap() { - return textureMap; + @Override + public TextureStage getTextureStage() { + return TextureStage.GBUFFERS_AND_SHADOW; } @Override @@ -26,7 +29,6 @@ public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((inputs == null) ? 0 : inputs.hashCode()); - result = prime * result + ((textureMap == null) ? 0 : textureMap.hashCode()); return result; } @@ -44,11 +46,6 @@ public boolean equals(Object obj) { return false; } else if (!inputs.equals(other.inputs)) return false; - if (textureMap == null) { - if (other.textureMap != null) - return false; - } else if (!textureMap.equals(other.textureMap)) - return false; return true; } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/CompositeParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/CompositeParameters.java deleted file mode 100644 index 748b337f02..0000000000 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/CompositeParameters.java +++ /dev/null @@ -1,49 +0,0 @@ -package net.coderbot.iris.pipeline.transform.parameter; - -import it.unimi.dsi.fastutil.objects.Object2ObjectMap; -import net.coderbot.iris.gl.blending.AlphaTest; -import net.coderbot.iris.gl.texture.TextureType; -import net.coderbot.iris.helpers.Tri; -import net.coderbot.iris.pipeline.transform.Patch; -import net.coderbot.iris.shaderpack.texture.TextureStage; - -public class CompositeParameters extends Parameters { - public final TextureStage stage; - private final Object2ObjectMap, String> textureMap; - - public CompositeParameters(Patch patch, TextureStage stage, Object2ObjectMap, String> textureMap) { - super(patch); - this.stage = stage; - this.textureMap = textureMap; - } - - public Object2ObjectMap, String> getTextureMap() { - return textureMap; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((stage == null) ? 0 : stage.hashCode()); - result = prime * result + ((textureMap == null) ? 0 : textureMap.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - CompositeParameters other = (CompositeParameters) obj; - return stage == other.stage && textureMap.equals(other.textureMap); - } - - @Override - public AlphaTest getAlphaTest() { - return AlphaTest.ALWAYS; - } -} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/ComputeParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/ComputeParameters.java index 06d51bca1c..327438d45d 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/ComputeParameters.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/ComputeParameters.java @@ -7,14 +7,12 @@ import net.coderbot.iris.pipeline.transform.Patch; import net.coderbot.iris.shaderpack.texture.TextureStage; -public class ComputeParameters extends Parameters { - private TextureStage stage; - private Object2ObjectMap, String> textureMap; +public class ComputeParameters extends TextureStageParameters { + // WARNING: adding new fields requires updating hashCode and equals methods! - public ComputeParameters(Patch patch, TextureStage stage, Object2ObjectMap, String> textureMap) { - super(patch); - this.stage = stage; - this.textureMap = textureMap; + public ComputeParameters(Patch patch, TextureStage stage, + Object2ObjectMap, String> textureMap) { + super(patch, stage, textureMap); } @Override @@ -22,11 +20,6 @@ public AlphaTest getAlphaTest() { return AlphaTest.ALWAYS; } - public TextureStage getStage() { - return stage; - } - - public Object2ObjectMap, String> getTextureMap() { - return textureMap; - } + // since this class has no fields, hashCode() and equals() are inherited from + // TextureStageParameters } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/GeometryInfoParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/GeometryInfoParameters.java new file mode 100644 index 0000000000..dcfec4f283 --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/GeometryInfoParameters.java @@ -0,0 +1,42 @@ +package net.coderbot.iris.pipeline.transform.parameter; + +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.gl.texture.TextureType; +import net.coderbot.iris.helpers.Tri; +import net.coderbot.iris.pipeline.transform.Patch; +import net.coderbot.iris.shaderpack.texture.TextureStage; + +public abstract class GeometryInfoParameters extends Parameters { + public final boolean hasGeometry; + public final boolean hasTesselation; + // WARNING: adding new fields requires updating hashCode and equals methods! + + public GeometryInfoParameters(Patch patch, + Object2ObjectMap, String> textureMap, boolean hasGeometry, boolean hasTesselation) { + super(patch, textureMap); + this.hasGeometry = hasGeometry; + this.hasTesselation = hasTesselation; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + (hasGeometry ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + GeometryInfoParameters other = (GeometryInfoParameters) obj; + if (hasGeometry != other.hasGeometry) + return false; + return true; + } +} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/OverlayParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/OverlayParameters.java deleted file mode 100644 index 712381f606..0000000000 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/OverlayParameters.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.coderbot.iris.pipeline.transform.parameter; - -import net.coderbot.iris.pipeline.transform.Patch; - -public class OverlayParameters extends Parameters { - public final boolean hasGeometry; - - public OverlayParameters(Patch patch, boolean hasGeometry) { - super(patch); - this.hasGeometry = hasGeometry; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + (hasGeometry ? 1231 : 1237); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - OverlayParameters other = (OverlayParameters) obj; - if (hasGeometry != other.hasGeometry) - return false; - return true; - } -} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/Parameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/Parameters.java index 40a7d49b4e..dc63746f87 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/Parameters.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/Parameters.java @@ -1,27 +1,42 @@ package net.coderbot.iris.pipeline.transform.parameter; import io.github.douira.glsl_transformer.ast.transform.JobParameters; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import net.coderbot.iris.gl.blending.AlphaTest; +import net.coderbot.iris.gl.texture.TextureType; +import net.coderbot.iris.helpers.Tri; import net.coderbot.iris.pipeline.transform.Patch; import net.coderbot.iris.pipeline.transform.PatchShaderType; +import net.coderbot.iris.shaderpack.texture.TextureStage; -public class Parameters implements JobParameters { +public abstract class Parameters implements JobParameters { public final Patch patch; - public PatchShaderType type; + public PatchShaderType type; // may only be set by TransformPatcher + private final Object2ObjectMap, String> textureMap; + // WARNING: adding new fields requires updating hashCode and equals methods! - public Parameters(Patch patch) { + public Parameters(Patch patch, Object2ObjectMap, String> textureMap) { this.patch = patch; + this.textureMap = textureMap; } public AlphaTest getAlphaTest() { return null; } + public abstract TextureStage getTextureStage(); + + public Object2ObjectMap, String> getTextureMap() { + return textureMap; + } + @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((patch == null) ? 0 : patch.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((textureMap == null) ? 0 : textureMap.hashCode()); return result; } @@ -36,6 +51,13 @@ public boolean equals(Object obj) { Parameters other = (Parameters) obj; if (patch != other.patch) return false; + if (type != other.type) + return false; + if (textureMap == null) { + if (other.textureMap != null) + return false; + } else if (!textureMap.equals(other.textureMap)) + return false; return true; } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/SodiumParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/SodiumParameters.java index f465e7099f..051ac1f74f 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/SodiumParameters.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/SodiumParameters.java @@ -6,66 +6,50 @@ import net.coderbot.iris.helpers.Tri; import net.coderbot.iris.pipeline.newshader.ShaderAttributeInputs; import net.coderbot.iris.pipeline.transform.Patch; -import net.coderbot.iris.pipeline.transform.PatchShaderType; import net.coderbot.iris.shaderpack.texture.TextureStage; public class SodiumParameters extends Parameters { - private final AlphaTest cutoutAlpha; - private final AlphaTest defaultAlpha; public final ShaderAttributeInputs inputs; public final float positionScale; public final float positionOffset; public final float textureScale; - private final Object2ObjectMap, String> textureMap; + // WARNING: adding new fields requires updating hashCode and equals methods! + // DO NOT include this field in hashCode or equals, it's mutable! + // (See use of setAlphaFor in TransformPatcher) public AlphaTest alpha; - public SodiumParameters(Patch patch, AlphaTest cutoutAlpha, AlphaTest defaultAlpha, ShaderAttributeInputs inputs, - float positionScale, float positionOffset, float textureScale, Object2ObjectMap, String> textureMap) { - super(patch); - this.cutoutAlpha = cutoutAlpha; - this.defaultAlpha = defaultAlpha; + public SodiumParameters(Patch patch, + Object2ObjectMap, String> textureMap, + AlphaTest alpha, + ShaderAttributeInputs inputs, + float positionScale, float positionOffset, float textureScale) { + super(patch, textureMap); this.inputs = inputs; this.positionScale = positionScale; this.positionOffset = positionOffset; this.textureScale = textureScale; - this.textureMap = textureMap; - this.alpha = defaultAlpha; + this.alpha = alpha; } - - public Object2ObjectMap, String> getTextureMap() { - return textureMap; - } - - public void setAlphaFor(PatchShaderType type) { - if (type == PatchShaderType.FRAGMENT_CUTOUT) { - alpha = cutoutAlpha; - } else { - alpha = defaultAlpha; - } - } - - public boolean hasCutoutAlpha() { - return cutoutAlpha != null; - } - @Override public AlphaTest getAlphaTest() { return alpha; } + @Override + public TextureStage getTextureStage() { + return TextureStage.GBUFFERS_AND_SHADOW; + } + @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + ((cutoutAlpha == null) ? 0 : cutoutAlpha.hashCode()); - result = prime * result + ((defaultAlpha == null) ? 0 : defaultAlpha.hashCode()); result = prime * result + ((inputs == null) ? 0 : inputs.hashCode()); result = prime * result + Float.floatToIntBits(positionScale); result = prime * result + Float.floatToIntBits(positionOffset); result = prime * result + Float.floatToIntBits(textureScale); - result = prime * result + ((textureMap == null) ? 0 : textureMap.hashCode()); result = prime * result + ((alpha == null) ? 0 : alpha.hashCode()); return result; } @@ -79,16 +63,6 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; SodiumParameters other = (SodiumParameters) obj; - if (cutoutAlpha == null) { - if (other.cutoutAlpha != null) - return false; - } else if (!cutoutAlpha.equals(other.cutoutAlpha)) - return false; - if (defaultAlpha == null) { - if (other.defaultAlpha != null) - return false; - } else if (!defaultAlpha.equals(other.defaultAlpha)) - return false; if (inputs == null) { if (other.inputs != null) return false; @@ -100,11 +74,6 @@ public boolean equals(Object obj) { return false; if (Float.floatToIntBits(textureScale) != Float.floatToIntBits(other.textureScale)) return false; - if (textureMap == null) { - if (other.textureMap != null) - return false; - } else if (!textureMap.equals(other.textureMap)) - return false; if (alpha == null) { if (other.alpha != null) return false; diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/TextureStageParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/TextureStageParameters.java new file mode 100644 index 0000000000..be2527c7f2 --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/TextureStageParameters.java @@ -0,0 +1,51 @@ +package net.coderbot.iris.pipeline.transform.parameter; + +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.gl.blending.AlphaTest; +import net.coderbot.iris.gl.texture.TextureType; +import net.coderbot.iris.helpers.Tri; +import net.coderbot.iris.pipeline.transform.Patch; +import net.coderbot.iris.shaderpack.texture.TextureStage; + +public class TextureStageParameters extends Parameters { + private final TextureStage stage; + // WARNING: adding new fields requires updating hashCode and equals methods! + + public TextureStageParameters(Patch patch, TextureStage stage, + Object2ObjectMap, String> textureMap) { + super(patch, textureMap); + this.stage = stage; + } + + @Override + public TextureStage getTextureStage() { + return stage; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((stage == null) ? 0 : stage.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + TextureStageParameters other = (TextureStageParameters) obj; + if (stage != other.stage) + return false; + return true; + } + + @Override + public AlphaTest getAlphaTest() { + return AlphaTest.ALWAYS; + } +} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/VanillaParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/VanillaParameters.java index b3485edde9..08f6309aad 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/VanillaParameters.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/VanillaParameters.java @@ -8,23 +8,27 @@ import net.coderbot.iris.pipeline.transform.Patch; import net.coderbot.iris.shaderpack.texture.TextureStage; -public class VanillaParameters extends OverlayParameters { +public class VanillaParameters extends GeometryInfoParameters { public final AlphaTest alpha; public final ShaderAttributeInputs inputs; public final boolean hasChunkOffset; - private final Object2ObjectMap, String> textureMap; + private final boolean isLines; + // WARNING: adding new fields requires updating hashCode and equals methods! - public VanillaParameters(Patch patch, AlphaTest alpha, boolean hasChunkOffset, - ShaderAttributeInputs inputs, boolean hasGeometry, Object2ObjectMap, String> textureMap) { - super(patch, hasGeometry); + public VanillaParameters( + Patch patch, + Object2ObjectMap, String> textureMap, + AlphaTest alpha, boolean isLines, boolean hasChunkOffset, + ShaderAttributeInputs inputs, boolean hasGeometry, boolean hasTesselation) { + super(patch, textureMap, hasGeometry, hasTesselation); this.alpha = alpha; + this.isLines = isLines; this.hasChunkOffset = hasChunkOffset; - this.textureMap = textureMap; this.inputs = inputs; } - public Object2ObjectMap, String> getTextureMap() { - return textureMap; + public boolean isLines() { + return isLines; } @Override @@ -32,6 +36,11 @@ public AlphaTest getAlphaTest() { return alpha; } + @Override + public TextureStage getTextureStage() { + return TextureStage.GBUFFERS_AND_SHADOW; + } + @Override public int hashCode() { final int prime = 31; @@ -39,7 +48,7 @@ public int hashCode() { result = prime * result + ((alpha == null) ? 0 : alpha.hashCode()); result = prime * result + ((inputs == null) ? 0 : inputs.hashCode()); result = prime * result + (hasChunkOffset ? 1231 : 1237); - result = prime * result + ((textureMap == null) ? 0 : textureMap.hashCode()); + result = prime * result + (isLines ? 1231 : 1237); return result; } @@ -64,10 +73,7 @@ public boolean equals(Object obj) { return false; if (hasChunkOffset != other.hasChunkOffset) return false; - if (textureMap == null) { - if (other.textureMap != null) - return false; - } else if (!textureMap.equals(other.textureMap)) + if (isLines != other.isLines) return false; return true; } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/AttributeTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/AttributeTransformer.java index 4093823663..b401ce7f2e 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/AttributeTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/AttributeTransformer.java @@ -1,21 +1,23 @@ package net.coderbot.iris.pipeline.transform.transformer; -import java.util.stream.Stream; - import io.github.douira.glsl_transformer.ast.node.Identifier; import io.github.douira.glsl_transformer.ast.node.TranslationUnit; import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration; import io.github.douira.glsl_transformer.ast.query.Root; import io.github.douira.glsl_transformer.ast.query.match.AutoHintedMatcher; -import io.github.douira.glsl_transformer.ast.query.match.Matcher; import io.github.douira.glsl_transformer.ast.transform.ASTInjectionPoint; import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import io.github.douira.glsl_transformer.ast.transform.TransformationException; +import io.github.douira.glsl_transformer.parser.ParseShape; import net.coderbot.iris.gl.shader.ShaderType; import net.coderbot.iris.pipeline.transform.PatchShaderType; import net.coderbot.iris.pipeline.transform.parameter.AttributeParameters; -import net.coderbot.iris.pipeline.transform.parameter.OverlayParameters; +import net.coderbot.iris.pipeline.transform.parameter.GeometryInfoParameters; import net.coderbot.iris.pipeline.transform.parameter.Parameters; +import net.coderbot.iris.pipeline.transform.parameter.VanillaParameters; + +import java.util.stream.Stream; /** * Implements AttributeShaderTransformer @@ -28,7 +30,7 @@ public static void transform( AttributeParameters parameters) { if (tree.getVersionStatement().getNormalizedProfile().isCore()) { if (parameters.type == PatchShaderType.VERTEX) { - throw new IllegalStateException("Vertex shaders must be in the compatibility profile to run properly!"); + throw new TransformationException("Vertex shaders must be in the compatibility profile to run properly!"); } return; } @@ -123,14 +125,23 @@ private static void patchTextureMatrices( } private static final AutoHintedMatcher uniformVec4EntityColor = new AutoHintedMatcher<>( - "uniform vec4 entityColor;", Matcher.externalDeclarationPattern); + "uniform vec4 entityColor;", ParseShape.EXTERNAL_DECLARATION); + + private static final AutoHintedMatcher uniformIntEntityId = new AutoHintedMatcher<>( + "uniform int entityId;", ParseShape.EXTERNAL_DECLARATION); + + private static final AutoHintedMatcher uniformIntBlockEntityId = new AutoHintedMatcher<>( + "uniform int blockEntityId;", ParseShape.EXTERNAL_DECLARATION); + + private static final AutoHintedMatcher uniformIntCurrentRenderedItemId = new AutoHintedMatcher<>( + "uniform int currentRenderedItemId;", ParseShape.EXTERNAL_DECLARATION); // Add entity color -> overlay color attribute support. public static void patchOverlayColor( ASTParser t, TranslationUnit tree, Root root, - OverlayParameters parameters) { + GeometryInfoParameters parameters) { // delete original declaration root.processMatches(t, uniformVec4EntityColor, ASTNode::detachAndDelete); @@ -156,6 +167,32 @@ public static void patchOverlayColor( // Some shader packs incorrectly ignore the alpha value, and assume that rgb // will be zero if there is no hit flash, we try to emulate that here "entityColor.rgb *= float(entityColor.a != 0.0);"); + } else if (parameters.type.glShaderType == ShaderType.TESSELATION_CONTROL) { + // replace read references to grab the color from the first vertex. + root.replaceReferenceExpressions(t, "entityColor", "entityColor[gl_InvocationID]"); + + // TODO: this is passthrough behavior + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "patch out vec4 entityColorTCS;", + "in vec4 entityColor[];", + "out vec4 iris_vertexColorTCS[];", + "in vec4 iris_vertexColor[];"); + tree.prependMainFunctionBody(t, + "entityColorTCS = entityColor[gl_InvocationID];", + "iris_vertexColorTCS[gl_InvocationID] = iris_vertexColor[gl_InvocationID];"); + } else if (parameters.type.glShaderType == ShaderType.TESSELATION_EVAL) { + // replace read references to grab the color from the first vertex. + root.replaceReferenceExpressions(t, "entityColor", "entityColorTCS"); + + // TODO: this is passthrough behavior + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "out vec4 entityColorTES;", + "patch in vec4 entityColorTCS;", + "out vec4 iris_vertexColorTES;", + "in vec4 iris_vertexColorTCS[];"); + tree.prependMainFunctionBody(t, + "entityColorTES = entityColorTCS;", + "iris_vertexColorTES = iris_vertexColorTCS[0];"); } else if (parameters.type.glShaderType == ShaderType.GEOMETRY) { // replace read references to grab the color from the first vertex. root.replaceReferenceExpressions(t, "entityColor", "entityColor[0]"); @@ -169,14 +206,107 @@ public static void patchOverlayColor( tree.prependMainFunctionBody(t, "entityColorGS = entityColor[0];", "iris_vertexColorGS = iris_vertexColor[0];"); + + if (parameters.hasTesselation) { + root.rename("iris_vertexColor", "iris_vertexColorTES"); + root.rename("entityColor", "entityColorTES"); + } } else if (parameters.type.glShaderType == ShaderType.FRAGMENT) { tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "in vec4 entityColor;", "in vec4 iris_vertexColor;"); + tree.prependMainFunctionBody(t, "float iris_vertexColorAlpha = iris_vertexColor.a;"); + // Different output name to avoid a name collision in the geometry shader. if (parameters.hasGeometry) { root.rename("entityColor", "entityColorGS"); root.rename("iris_vertexColor", "iris_vertexColorGS"); + } else if (parameters.hasTesselation) { + root.rename("entityColor", "entityColorTES"); + root.rename("iris_vertexColor", "iris_vertexColorTES"); + } + } + } + + public static void patchEntityId( + ASTParser t, + TranslationUnit tree, + Root root, + VanillaParameters parameters) { + // delete original declaration + root.processMatches(t, uniformIntEntityId, ASTNode::detachAndDelete); + root.processMatches(t, uniformIntBlockEntityId, ASTNode::detachAndDelete); + root.processMatches(t, uniformIntCurrentRenderedItemId, ASTNode::detachAndDelete); + + + if (parameters.type.glShaderType == ShaderType.GEOMETRY) { + root.replaceReferenceExpressions(t, "entityId", + "iris_entityInfo[0].x"); + + root.replaceReferenceExpressions(t, "blockEntityId", + "iris_entityInfo[0].y"); + + root.replaceReferenceExpressions(t, "currentRenderedItemId", + "iris_entityInfo[0].z"); + } else { + root.replaceReferenceExpressions(t, "entityId", + "iris_entityInfo.x"); + + root.replaceReferenceExpressions(t, "blockEntityId", + "iris_entityInfo.y"); + + root.replaceReferenceExpressions(t, "currentRenderedItemId", + "iris_entityInfo.z"); + } + + if (parameters.type.glShaderType == ShaderType.VERTEX) { + // add our own declarations + // TODO: We're exposing entityColor to this stage even if it isn't declared in + // this stage. But this is needed for the pass-through behavior. + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "flat out ivec3 iris_entityInfo;", + "in ivec3 iris_Entity;"); + + // Create our own main function to wrap the existing main function, so that we + // can pass through the overlay color at the end to the geometry or fragment + // stage. + tree.prependMainFunctionBody(t, + "iris_entityInfo = iris_Entity;"); + } else if (parameters.type.glShaderType == ShaderType.TESSELATION_CONTROL) { + // TODO: this is passthrough behavior + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "flat out ivec3 iris_entityInfoTCS[];", + "flat in ivec3 iris_entityInfo[];"); + root.replaceReferenceExpressions(t, "iris_entityInfo", "iris_EntityInfo[gl_InvocationID]"); + + tree.prependMainFunctionBody(t, + "iris_entityInfoTCS[gl_InvocationID] = iris_entityInfo[gl_InvocationID];"); + } else if (parameters.type.glShaderType == ShaderType.TESSELATION_EVAL) { + // TODO: this is passthrough behavior + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "flat out ivec3 iris_entityInfoTES;", + "flat in ivec3 iris_entityInfoTCS[];"); + tree.prependMainFunctionBody(t, + "iris_entityInfoTES = iris_entityInfoTCS[0];"); + + root.replaceReferenceExpressions(t, "iris_entityInfo", "iris_EntityInfoTCS[0]"); + + } else if (parameters.type.glShaderType == ShaderType.GEOMETRY) { + // TODO: this is passthrough behavior + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "flat out ivec3 iris_entityInfoGS;", + "flat in ivec3 iris_entityInfo" + (parameters.hasTesselation ? "TES" : "") + "[];"); + tree.prependMainFunctionBody(t, + "iris_entityInfoGS = iris_entityInfo" + (parameters.hasTesselation ? "TES" : "") + "[0];"); + } else if (parameters.type.glShaderType == ShaderType.FRAGMENT) { + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "flat in ivec3 iris_entityInfo;"); + + // Different output name to avoid a name collision in the geometry shader. + if (parameters.hasGeometry) { + root.rename("iris_entityInfo", "iris_EntityInfoGS"); + } else if (parameters.hasTesselation) { + root.rename("iris_entityInfo", "iris_entityInfoTES"); } } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CommonTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CommonTransformer.java index f9960eba29..5943f8bc52 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CommonTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CommonTransformer.java @@ -1,11 +1,5 @@ package net.coderbot.iris.pipeline.transform.transformer; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Stream; - import io.github.douira.glsl_transformer.ast.node.Identifier; import io.github.douira.glsl_transformer.ast.node.TranslationUnit; import io.github.douira.glsl_transformer.ast.node.declaration.DeclarationMember; @@ -21,6 +15,7 @@ import io.github.douira.glsl_transformer.ast.node.type.qualifier.StorageQualifier.StorageType; import io.github.douira.glsl_transformer.ast.node.type.specifier.BuiltinFixedTypeSpecifier; import io.github.douira.glsl_transformer.ast.node.type.specifier.BuiltinFixedTypeSpecifier.BuiltinType.TypeKind; +import io.github.douira.glsl_transformer.ast.node.type.specifier.BuiltinNumericTypeSpecifier; import io.github.douira.glsl_transformer.ast.node.type.specifier.TypeSpecifier; import io.github.douira.glsl_transformer.ast.query.Root; import io.github.douira.glsl_transformer.ast.query.match.AutoHintedMatcher; @@ -28,19 +23,28 @@ import io.github.douira.glsl_transformer.ast.transform.ASTInjectionPoint; import io.github.douira.glsl_transformer.ast.transform.ASTParser; import io.github.douira.glsl_transformer.ast.transform.Template; +import io.github.douira.glsl_transformer.parser.ParseShape; import io.github.douira.glsl_transformer.util.Type; import net.coderbot.iris.Iris; import net.coderbot.iris.gl.blending.AlphaTest; import net.coderbot.iris.gl.shader.ShaderType; import net.coderbot.iris.pipeline.transform.parameter.Parameters; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; + public class CommonTransformer { public static final AutoHintedMatcher glTextureMatrix0 = new AutoHintedMatcher<>( - "gl_TextureMatrix[0]", Matcher.expressionPattern); + "gl_TextureMatrix[0]", ParseShape.EXPRESSION); public static final AutoHintedMatcher glTextureMatrix1 = new AutoHintedMatcher<>( - "gl_TextureMatrix[1]", Matcher.expressionPattern); + "gl_TextureMatrix[1]", ParseShape.EXPRESSION); + public static final AutoHintedMatcher glTextureMatrix2 = new AutoHintedMatcher<>( + "gl_TextureMatrix[2]", ParseShape.EXPRESSION); public static final Matcher sampler = new Matcher<>( - "uniform Type name;", Matcher.externalDeclarationPattern) { + "uniform Type name;", ParseShape.EXTERNAL_DECLARATION) { { markClassedPredicateWildcard("type", pattern.getRoot().identifierIndex.getUnique("Type").getAncestor(TypeSpecifier.class), @@ -52,7 +56,7 @@ public class CommonTransformer { }; private static final AutoHintedMatcher glFragDataI = new AutoHintedMatcher<>( - "gl_FragData[index]", Matcher.expressionPattern) { + "gl_FragData[index]", ParseShape.EXPRESSION) { { markClassedPredicateWildcard("index", pattern.getRoot().identifierIndex.getUnique("index").getAncestor(ReferenceExpression.class), @@ -71,29 +75,46 @@ public class CommonTransformer { private static final List replaceExpressions = new ArrayList<>(); private static final List replaceIndexes = new ArrayList<>(); - private static void renameFunctionCall(Root root, String oldName, String newName) { + static void renameFunctionCall(Root root, String oldName, String newName) { root.process(root.identifierIndex.getStream(oldName) .filter(id -> id.getParent() instanceof FunctionCallExpression), id -> id.setName(newName)); } - private static void renameAndWrapShadow(ASTParser t, Root root, String oldName, String innerName) { + static void renameAndWrapShadow(ASTParser t, Root root, String oldName, String innerName) { root.process(root.identifierIndex.getStream(oldName) .filter(id -> id.getParent() instanceof FunctionCallExpression), id -> { FunctionCallExpression functionCall = (FunctionCallExpression) id.getParent(); functionCall.getFunctionName().setName(innerName); - FunctionCallExpression wrapper = (FunctionCallExpression) t.parseExpression(id, "vec4()"); + FunctionCallExpression wrapper = (FunctionCallExpression) t.parseExpression(root, "vec4()"); functionCall.replaceBy(wrapper); wrapper.getParameters().add(functionCall); }); } - public static void transform( + public static void upgradeStorageQualifiers( ASTParser t, TranslationUnit tree, Root root, Parameters parameters) { + for (StorageQualifier qualifier : root.nodeIndex.get(StorageQualifier.class)) { + if (qualifier.storageType == StorageType.ATTRIBUTE) { + qualifier.storageType = StorageType.IN; + } else if (qualifier.storageType == StorageType.VARYING) { + qualifier.storageType = parameters.type.glShaderType == ShaderType.VERTEX + ? StorageType.OUT + : StorageType.IN; + } + } + } + + public static void transform( + ASTParser t, + TranslationUnit tree, + Root root, + Parameters parameters, + boolean core) { // TODO: What if the shader does gl_PerVertex.gl_FogFragCoord ? root.rename("gl_FogFragCoord", "iris_FogFragCoord"); @@ -102,6 +123,7 @@ public static void transform( if (parameters.type.glShaderType == ShaderType.VERTEX) { tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "out float iris_FogFragCoord;"); + tree.prependMainFunctionBody(t, "iris_FogFragCoord = 0.0f;"); } else if (parameters.type.glShaderType == ShaderType.FRAGMENT) { tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "in float iris_FogFragCoord;"); @@ -126,6 +148,16 @@ public static void transform( root.replaceReferenceExpressions(t, "gl_FragColor", "gl_FragData[0]"); } + if (root.identifierIndex.has("gl_TexCoord")) { + root.rename("gl_TexCoord", "irs_texCoords"); + tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "in vec4 irs_texCoords[3];"); + } + + if (root.identifierIndex.has("gl_Color")) { + root.rename("gl_Color", "irs_Color"); + tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "in vec4 irs_Color;"); + } + // change gl_FragData[i] to iris_FragDatai replaceExpressions.clear(); replaceIndexes.clear(); @@ -146,7 +178,7 @@ public static void transform( } for (long index : replaceIndexesSet) { tree.injectNode(ASTInjectionPoint.BEFORE_DECLARATIONS, - fragDataDeclaration.getInstanceFor(tree, + fragDataDeclaration.getInstanceFor(root, new LiteralExpression(Type.INT32, index), new Identifier("iris_FragData" + index))); } @@ -154,22 +186,15 @@ public static void transform( replaceIndexes.clear(); // insert alpha test for iris_FragData0 in the fragment shader - if (parameters.getAlphaTest() != AlphaTest.ALWAYS && replaceIndexesSet.contains(0L)) { + if ((parameters.getAlphaTest() != AlphaTest.ALWAYS && !core) && replaceIndexesSet.contains(0L)) { tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "uniform float iris_currentAlphaTest;"); - tree.appendMainFunctionBody(t, parameters.getAlphaTest().toExpression("iris_FragData0.a", "iris_currentAlphaTest", " ")); + tree.appendMainFunctionBody(t, + parameters.getAlphaTest().toExpression("iris_FragData0.a", "iris_currentAlphaTest", " ")); } } if (parameters.type.glShaderType == ShaderType.VERTEX || parameters.type.glShaderType == ShaderType.FRAGMENT) { - for (StorageQualifier qualifier : root.nodeIndex.get(StorageQualifier.class)) { - if (qualifier.storageType == StorageType.ATTRIBUTE) { - qualifier.storageType = StorageType.IN; - } else if (qualifier.storageType == StorageType.VARYING) { - qualifier.storageType = parameters.type.glShaderType == ShaderType.VERTEX - ? StorageType.OUT - : StorageType.IN; - } - } + upgradeStorageQualifiers(t, tree, root, parameters); } // addition: rename all uses of texture and gcolor to gtexture if it's *not* @@ -336,4 +361,26 @@ public static void replaceGlMultiTexCoordBounded( }), "vec4(0.0, 0.0, 0.0, 1.0)"); } + + private static final Template inputDeclarationTemplate = Template.withExternalDeclaration( + "uniform int __name;"); + + static { + inputDeclarationTemplate.markLocalReplacement( + inputDeclarationTemplate.getSourceRoot().nodeIndex.getOne(StorageQualifier.class)); + inputDeclarationTemplate.markLocalReplacement( + inputDeclarationTemplate.getSourceRoot().nodeIndex.getOne(BuiltinNumericTypeSpecifier.class)); + inputDeclarationTemplate.markIdentifierReplacement("__name"); + } + + public static void addIfNotExists(Root root, ASTParser t, TranslationUnit tree, String name, Type type, + StorageType storageType) { + if (root.externalDeclarationIndex.getStream(name) + .noneMatch((entry) -> entry.declaration() instanceof DeclarationExternalDeclaration)) { + tree.injectNode(ASTInjectionPoint.BEFORE_DECLARATIONS, inputDeclarationTemplate.getInstanceFor(root, + new StorageQualifier(storageType), + new BuiltinNumericTypeSpecifier(type), + new Identifier(name))); + } + } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompatibilityTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompatibilityTransformer.java index 3726869103..cd6a15f62a 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompatibilityTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompatibilityTransformer.java @@ -1,18 +1,5 @@ package net.coderbot.iris.pipeline.transform.transformer; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Stream; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - import io.github.douira.glsl_transformer.ast.node.Identifier; import io.github.douira.glsl_transformer.ast.node.TranslationUnit; import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode; @@ -28,32 +15,39 @@ import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration; import io.github.douira.glsl_transformer.ast.node.external_declaration.FunctionDefinition; import io.github.douira.glsl_transformer.ast.node.statement.Statement; -import io.github.douira.glsl_transformer.ast.node.type.qualifier.StorageQualifier; +import io.github.douira.glsl_transformer.ast.node.type.qualifier.*; import io.github.douira.glsl_transformer.ast.node.type.qualifier.StorageQualifier.StorageType; -import io.github.douira.glsl_transformer.ast.node.type.qualifier.TypeQualifier; -import io.github.douira.glsl_transformer.ast.node.type.qualifier.TypeQualifierPart; +import io.github.douira.glsl_transformer.ast.node.type.specifier.ArraySpecifier; import io.github.douira.glsl_transformer.ast.node.type.specifier.BuiltinNumericTypeSpecifier; import io.github.douira.glsl_transformer.ast.node.type.specifier.FunctionPrototype; import io.github.douira.glsl_transformer.ast.node.type.specifier.TypeSpecifier; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructDeclarator; +import io.github.douira.glsl_transformer.ast.node.type.struct.StructMember; import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.query.index.PrefixIdentifierIndex; import io.github.douira.glsl_transformer.ast.query.match.AutoHintedMatcher; import io.github.douira.glsl_transformer.ast.query.match.Matcher; import io.github.douira.glsl_transformer.ast.transform.ASTInjectionPoint; import io.github.douira.glsl_transformer.ast.transform.ASTParser; import io.github.douira.glsl_transformer.ast.transform.Template; +import io.github.douira.glsl_transformer.ast.transform.TransformationException; +import io.github.douira.glsl_transformer.parser.ParseShape; import io.github.douira.glsl_transformer.util.Type; import net.coderbot.iris.Iris; import net.coderbot.iris.gl.shader.ShaderType; -import net.coderbot.iris.pipeline.PatchedShaderPrinter; import net.coderbot.iris.pipeline.transform.PatchShaderType; import net.coderbot.iris.pipeline.transform.parameter.Parameters; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class CompatibilityTransformer { static Logger LOGGER = LogManager.getLogger(CompatibilityTransformer.class); private static final AutoHintedMatcher sildursWaterFract = new AutoHintedMatcher<>( - "fract(worldpos.y + 0.001)", Matcher.expressionPattern); + "fract(worldpos.y + 0.001)", ParseShape.EXPRESSION); private static StorageQualifier getConstQualifier(TypeQualifier qualifier) { if (qualifier == null) { @@ -104,13 +98,15 @@ public static void transformEach(ASTParser t, TranslationUnit tree, Root root, P // TODO: integrate into debug mode (allow user to disable this behavior for // debugging purposes) unusedFunctions.add(definition); - if (PatchedShaderPrinter.prettyPrintShaders) { - LOGGER.warn("Removing unused function " + functionName); - }/* else if (unusedFunctions.size() == 1) { - LOGGER.warn( - "Removing unused function " + functionName - + " and omitting further such messages outside of debug mode. See debugging.md for more information."); - }*/ + /* + * else if (unusedFunctions.size() == 1) { + * LOGGER.warn( + * "Removing unused function " + functionName + * + + * " and omitting further such messages outside of debug mode. See debugging.md for more information." + * ); + * } + */ continue; } @@ -134,8 +130,10 @@ public static void transformEach(ASTParser t, TranslationUnit tree, Root root, P } // remove collected unused functions - for (FunctionDefinition definition : unusedFunctions) { - definition.detachAndDelete(); + if (!Iris.getIrisConfig().areDebugOptionsEnabled()) { + for (FunctionDefinition definition : unusedFunctions) { + definition.detachAndDelete(); + } } // find the reference expressions for the const parameters @@ -183,7 +181,7 @@ public static void transformEach(ASTParser t, TranslationUnit tree, Root root, P // the name may not be the same as the parameter name if (constIdsInFunction.contains(memberName)) { - throw new IllegalStateException("Illegal redefinition of const parameter " + name); + throw new TransformationException("Illegal redefinition of const parameter " + name); } constIdsInFunction.add(memberName); @@ -222,13 +220,51 @@ public static void transformEach(ASTParser t, TranslationUnit tree, Root root, P LOGGER.warn("Renamed reserved word \"" + reservedWord + "\" to \"" + newName + "\"."); } } + + // transform that moves unsized array specifiers on struct members from the type + // to the identifier of a type and init declaration. Some drivers appear to not + // be able to detect the unsized array if it's on the type. + for (StructMember structMember : root.nodeIndex.get(StructMember.class)) { + // check if the type specifier has an array specifier + TypeSpecifier typeSpecifier = structMember.getType().getTypeSpecifier(); + ArraySpecifier arraySpecifier = typeSpecifier.getArraySpecifier(); + if (arraySpecifier == null) { + continue; + } + + // check if the array specifier is unsized + if (!arraySpecifier.getChildren().isNullEmpty()) { + continue; + } + + // remove itself from the parent (makes it null) + arraySpecifier.detach(); + + // move the empty array specifier to all members + boolean reusedOriginal = false; + for (StructDeclarator declarator : structMember.getDeclarators()) { + if (declarator.getArraySpecifier() != null) { + throw new TransformationException("Member already has an array specifier"); + } + + // clone the array specifier into this member, re-use if possible + declarator.setArraySpecifier(reusedOriginal ? arraySpecifier.cloneInto(root) : arraySpecifier); + reusedOriginal = true; + } + + LOGGER.warn( + "Moved unsized array specifier (of the form []) from the type to each of the the declaration member(s) " + + structMember.getDeclarators().stream().map(StructDeclarator::getName).map(Identifier::getName) + .collect(Collectors.joining(", ")) + + ". See debugging.md for more information."); + } } private static class DeclarationMatcher extends Matcher { private final StorageType storageType; public DeclarationMatcher(StorageType storageType) { - super("out float name;", Matcher.externalDeclarationPattern); + super("out float name;", ParseShape.EXTERNAL_DECLARATION); this.storageType = storageType; } @@ -258,7 +294,7 @@ public boolean matchesExtract(ExternalDeclaration tree) { } } - private static final ShaderType[] pipeline = { ShaderType.VERTEX, ShaderType.GEOMETRY, ShaderType.FRAGMENT }; + private static final ShaderType[] pipeline = { ShaderType.VERTEX, ShaderType.TESSELATION_CONTROL, ShaderType.TESSELATION_EVAL, ShaderType.GEOMETRY, ShaderType.FRAGMENT }; private static final Matcher outDeclarationMatcher = new DeclarationMatcher( StorageType.OUT); private static final Matcher inDeclarationMatcher = new DeclarationMatcher( @@ -301,7 +337,7 @@ private static Statement getInitializer(Root root, String name, Type type) { new Identifier(name), type.isScalar() ? LiteralExpression.getDefaultValue(type) - : Root.indexNodes(root, () -> new FunctionCallExpression( + : root.indexNodes(() -> new FunctionCallExpression( new Identifier(type.getMostCompactName()), Stream.of(LiteralExpression.getDefaultValue(type))))); } @@ -466,6 +502,20 @@ public static void transformGrouped( Type inType = inTypeSpecifier.type; Type outType = outTypeSpecifier.type; + // check if the out declaration is an array-type, if so, skip it. + // this only checks the out declaration because it's the one that when it's an + // array type means that both declarations are arrays and we're not just in the + // case of a geometry shader where the in declaration is an array and the out + // declaration is not + if (outTypeSpecifier.getArraySpecifier() != null) { + LOGGER.warn( + "The out declaration '" + name + "' in the " + prevPatchTypes.glShaderType.name() + + " shader that has a missing corresponding in declaration in the next stage " + + type.name() + + " has an array type and could not be compatibility-patched. See debugging.md for more information."); + continue; + } + // skip if the type matches, nothing has to be done if (inType == outType) { // if the types match but it's never assigned a value, @@ -477,6 +527,12 @@ public static void transformGrouped( // add an initialization statement for this declaration prevTree.prependMainFunctionBody(getInitializer(prevRoot, name, inType)); outDeclarations.put(name, null); + + LOGGER.warn( + "The in declaration '" + name + "' in the " + currentType.glShaderType.name() + + " shader that is never assigned to in the previous stage " + + prevType.name() + + " has been compatibility-patched by adding an initialization for it. See debugging.md for more information."); continue; } @@ -510,7 +566,7 @@ public static void transformGrouped( } } if (outMember == null) { - throw new IllegalStateException("The targeted out declaration member is missing!"); + throw new TransformationException("The targeted out declaration member is missing!"); } outMember.getName().replaceByAndDelete(new Identifier(name)); @@ -562,4 +618,133 @@ public static void transformGrouped( prevType = type; } } + + private static final Matcher nonLayoutOutDeclarationMatcher = new Matcher( + "out float name;", + ParseShape.EXTERNAL_DECLARATION) { + { + markClassWildcard("qualifier", pattern.getRoot().nodeIndex.getUnique(TypeQualifier.class)); + markClassWildcard("type", pattern.getRoot().nodeIndex.getUnique(BuiltinNumericTypeSpecifier.class)); + markClassWildcard("name*", + pattern.getRoot().identifierIndex.getUnique("name").getAncestor(DeclarationMember.class)); + } + + @Override + public boolean matchesExtract(ExternalDeclaration tree) { + boolean result = super.matchesExtract(tree); + if (!result) { + return false; + } + + // look for an out qualifier but no layout qualifier + TypeQualifier qualifier = getNodeMatch("qualifier", TypeQualifier.class); + var hasOutQualifier = false; + for (TypeQualifierPart part : qualifier.getParts()) { + if (part instanceof StorageQualifier) { + StorageQualifier storageQualifier = (StorageQualifier) part; + if (storageQualifier.storageType == StorageType.OUT) { + hasOutQualifier = true; + } + } else if (part instanceof LayoutQualifier) { + return false; + } + } + return hasOutQualifier; + } + }; + + private static final Template layoutedOutDeclarationTemplate = Template + .withExternalDeclaration("out __type __name;"); + + static { + layoutedOutDeclarationTemplate.markLocalReplacement( + layoutedOutDeclarationTemplate.getSourceRoot().nodeIndex.getOne(TypeQualifier.class)); + layoutedOutDeclarationTemplate.markLocalReplacement("__type", TypeSpecifier.class); + layoutedOutDeclarationTemplate.markLocalReplacement("__name", DeclarationMember.class); + } + + record NewDeclarationData(TypeQualifier qualifier, TypeSpecifier type, DeclarationMember member, int number) { + } + + private static final String attachTargetPrefix = "outColor"; + + public static void transformFragmentCore(ASTParser t, TranslationUnit tree, Root root, Parameters parameters) { + // do layout attachment (attaches a location(layout = 4) to the out declaration + // outColor4 for example) + + // iterate the declarations + ArrayList newDeclarationData = new ArrayList(); + ArrayList declarationsToRemove = new ArrayList(); + for (DeclarationExternalDeclaration declaration : root.nodeIndex.get(DeclarationExternalDeclaration.class)) { + if (!nonLayoutOutDeclarationMatcher.matchesExtract(declaration)) { + continue; + } + + // find the matching outColor members + List members = nonLayoutOutDeclarationMatcher + .getNodeMatch("name*", DeclarationMember.class) + .getAncestor(TypeAndInitDeclaration.class) + .getMembers(); + TypeQualifier typeQualifier = nonLayoutOutDeclarationMatcher.getNodeMatch("qualifier", TypeQualifier.class); + BuiltinNumericTypeSpecifier typeSpecifier = nonLayoutOutDeclarationMatcher.getNodeMatch("type", + BuiltinNumericTypeSpecifier.class); + int addedDeclarations = 0; + for (DeclarationMember member : members) { + String name = member.getName().getName(); + if (!name.startsWith(attachTargetPrefix)) { + continue; + } + + // get the number suffix after the prefix + String numberSuffix = name.substring(attachTargetPrefix.length()); + if (numberSuffix.isEmpty()) { + continue; + } + + // make sure it's a number and is between 0 and 7 + int number; + try { + number = Integer.parseInt(numberSuffix); + } catch (NumberFormatException e) { + continue; + } + if (number < 0 || 7 < number) { + continue; + } + + newDeclarationData.add(new NewDeclarationData(typeQualifier, typeSpecifier, member, number)); + addedDeclarations++; + } + + // if the member list is now empty, remove the declaration + if (addedDeclarations == members.size()) { + declarationsToRemove.add(declaration); + } + } + tree.getChildren().removeAll(declarationsToRemove); + for (ExternalDeclaration declaration : declarationsToRemove) { + declaration.detachParent(); + } + + // generate new declarations with layout qualifiers for each outColor member + ArrayList newDeclarations = new ArrayList(); + + // Note: since everything is wrapped in a big Root.indexBuildSession, we don't + // need to do it manually here + for (NewDeclarationData data : newDeclarationData) { + DeclarationMember member = data.member; + member.detach(); + TypeQualifier newQualifier = data.qualifier.cloneInto(root); + newQualifier.getChildren() + .add(new LayoutQualifier(Stream.of(new NamedLayoutQualifierPart( + new Identifier("location"), + new LiteralExpression(Type.INT32, data.number))))); + ExternalDeclaration newDeclaration = layoutedOutDeclarationTemplate.getInstanceFor(root, + newQualifier, + data.type.cloneInto(root), + member); + newDeclarations.add(newDeclaration); + } + tree.injectNodes(ASTInjectionPoint.BEFORE_DECLARATIONS, newDeclarations); + } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompositeCoreTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompositeCoreTransformer.java new file mode 100644 index 0000000000..08af1e7be5 --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompositeCoreTransformer.java @@ -0,0 +1,30 @@ +package net.coderbot.iris.pipeline.transform.transformer; + +import io.github.douira.glsl_transformer.ast.node.TranslationUnit; +import io.github.douira.glsl_transformer.ast.query.Root; +import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import net.coderbot.iris.pipeline.transform.PatchShaderType; +import net.coderbot.iris.pipeline.transform.parameter.Parameters; + +public class CompositeCoreTransformer { + public static void transform( + ASTParser t, + TranslationUnit tree, + Root root, + Parameters parameters) { + CompositeDepthTransformer.transform(t, tree, root); + + if (parameters.type == PatchShaderType.VERTEX) { + root.rename("vaPosition", "Position"); + root.rename("vaUV0", "UV0"); + root.replaceReferenceExpressions(t, "modelViewMatrix", "mat4(1.0)"); + // This is used to scale the quad projection matrix from (0, 1) to (-1, 1). + root.replaceReferenceExpressions(t, "projectionMatrix", + "mat4(vec4(2.0, 0.0, 0.0, 0.0), vec4(0.0, 2.0, 0.0, 0.0), vec4(0.0), vec4(-1.0, -1.0, 0.0, 1.0))"); + root.replaceReferenceExpressions(t, "modelViewMatrixInverse", "mat4(1.0)"); + root.replaceReferenceExpressions(t, "projectionMatrixInverse", + "inverse(mat4(vec4(2.0, 0.0, 0.0, 0.0), vec4(0.0, 2.0, 0.0, 0.0), vec4(0.0), vec4(-1.0, -1.0, 0.0, 1.0)))"); + root.replaceReferenceExpressions(t, "textureMatrix", "mat4(1.0)"); + } + } +} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompositeDepthTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompositeDepthTransformer.java index 2936960453..44415a6b74 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompositeDepthTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompositeDepthTransformer.java @@ -7,13 +7,13 @@ import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration; import io.github.douira.glsl_transformer.ast.query.Root; import io.github.douira.glsl_transformer.ast.query.match.HintedMatcher; -import io.github.douira.glsl_transformer.ast.query.match.Matcher; import io.github.douira.glsl_transformer.ast.transform.ASTInjectionPoint; import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import io.github.douira.glsl_transformer.parser.ParseShape; class CompositeDepthTransformer { private static final HintedMatcher uniformFloatCenterDepthSmooth = new HintedMatcher<>( - "uniform float name;", Matcher.externalDeclarationPattern, "centerDepthSmooth") { + "uniform float name;", ParseShape.EXTERNAL_DECLARATION, "centerDepthSmooth") { { markClassWildcard("name*", pattern.getRoot().identifierIndex.getUnique("name").getAncestor(DeclarationMember.class)); diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompositeTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompositeTransformer.java index 61153406b9..d077f20378 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompositeTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompositeTransformer.java @@ -6,15 +6,15 @@ import io.github.douira.glsl_transformer.ast.node.expression.ReferenceExpression; import io.github.douira.glsl_transformer.ast.query.Root; import io.github.douira.glsl_transformer.ast.query.match.AutoHintedMatcher; -import io.github.douira.glsl_transformer.ast.query.match.Matcher; import io.github.douira.glsl_transformer.ast.transform.ASTInjectionPoint; import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import io.github.douira.glsl_transformer.parser.ParseShape; import net.coderbot.iris.gl.shader.ShaderType; import net.coderbot.iris.pipeline.transform.parameter.Parameters; public class CompositeTransformer { private static final AutoHintedMatcher glTextureMatrix0To7 = new AutoHintedMatcher( - "gl_TextureMatrix[index]", Matcher.expressionPattern) { + "gl_TextureMatrix[index]", ParseShape.EXPRESSION) { { markClassedPredicateWildcard("index", pattern.getRoot().identifierIndex.getOne("index").getAncestor(ReferenceExpression.class), @@ -34,7 +34,7 @@ public static void transform( TranslationUnit tree, Root root, Parameters parameters) { - CommonTransformer.transform(t, tree, root, parameters); + CommonTransformer.transform(t, tree, root, parameters, true); CompositeDepthTransformer.transform(t, tree, root); // TODO: More solid way to handle texture matrices diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/SodiumCoreTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/SodiumCoreTransformer.java new file mode 100644 index 0000000000..d6675cb199 --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/SodiumCoreTransformer.java @@ -0,0 +1,37 @@ +package net.coderbot.iris.pipeline.transform.transformer; + +import io.github.douira.glsl_transformer.ast.node.TranslationUnit; +import io.github.douira.glsl_transformer.ast.query.Root; +import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import net.coderbot.iris.pipeline.transform.PatchShaderType; +import net.coderbot.iris.pipeline.transform.parameter.SodiumParameters; + +public class SodiumCoreTransformer { + public static void transform( + ASTParser t, + TranslationUnit tree, + Root root, + SodiumParameters parameters) { + root.rename("alphaTestRef", "iris_currentAlphaTest"); + root.rename("modelViewMatrix", "iris_ModelViewMatrix"); + root.rename("modelViewMatrixInverse", "iris_ModelViewMatrixInverse"); + root.rename("projectionMatrix", "iris_ProjectionMatrix"); + root.rename("projectionMatrixInverse", "iris_ProjectionMatrixInverse"); + root.rename("normalMatrix", "iris_NormalMatrix"); + root.rename("chunkOffset", "u_RegionOffset"); + + if (parameters.type == PatchShaderType.VERTEX) { + // _draw_translation replaced with Chunks[_draw_id].offset.xyz + root.replaceReferenceExpressions(t, "vaPosition", "Chunks[_draw_id].offset.xyz + _vert_position"); + root.replaceReferenceExpressions(t, "vaColor", "_vert_color"); + root.rename("vaNormal", "iris_Normal"); + root.replaceReferenceExpressions(t, "vaUV0", "_vert_tex_diffuse_coord"); + root.replaceReferenceExpressions(t, "vaUV1", "ivec2(0, 10)"); + root.rename("vaUV2", "a_LightCoord"); + + root.replaceReferenceExpressions(t, "textureMatrix", "mat4(1.0)"); + + SodiumTransformer.injectVertInit(t, tree, root, parameters); + } + } +} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/SodiumTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/SodiumTransformer.java index 6a823f5706..90e9cd88d2 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/SodiumTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/SodiumTransformer.java @@ -1,19 +1,29 @@ package net.coderbot.iris.pipeline.transform.transformer; +import io.github.douira.glsl_transformer.ast.node.Identifier; import io.github.douira.glsl_transformer.ast.node.TranslationUnit; +import io.github.douira.glsl_transformer.ast.node.declaration.TypeAndInitDeclaration; +import io.github.douira.glsl_transformer.ast.node.external_declaration.DeclarationExternalDeclaration; +import io.github.douira.glsl_transformer.ast.node.type.qualifier.StorageQualifier; +import io.github.douira.glsl_transformer.ast.node.type.specifier.BuiltinNumericTypeSpecifier; import io.github.douira.glsl_transformer.ast.query.Root; import io.github.douira.glsl_transformer.ast.transform.ASTInjectionPoint; import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import io.github.douira.glsl_transformer.util.Type; import net.coderbot.iris.gl.shader.ShaderType; import net.coderbot.iris.pipeline.transform.parameter.SodiumParameters; +import static net.coderbot.iris.pipeline.transform.transformer.CommonTransformer.addIfNotExists; + public class SodiumTransformer { public static void transform( ASTParser t, TranslationUnit tree, Root root, SodiumParameters parameters) { - CommonTransformer.transform(t, tree, root, parameters); + CommonTransformer.transform(t, tree, root, parameters, false); + + replaceMidTexCoord(t, tree, root, parameters.textureScale); root.replaceExpressionMatches(t, CommonTransformer.glTextureMatrix0, "mat4(1.0)"); root.rename("gl_ProjectionMatrix", "iris_ProjectionMatrix"); @@ -62,9 +72,9 @@ public static void transform( // TODO: Should probably add the normal matrix as a proper uniform that's // computed on the CPU-side of things root.replaceReferenceExpressions(t, "gl_NormalMatrix", - "mat3(iris_NormalMatrix)"); + "iris_NormalMatrix"); tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, - "uniform mat4 iris_NormalMatrix;"); + "uniform mat3 iris_NormalMatrix;"); tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "uniform mat4 iris_ModelViewMatrixInverse;"); @@ -86,39 +96,17 @@ public static void transform( "vec4 ftransform() { return gl_ModelViewProjectionMatrix * gl_Vertex; }"); } tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, - // translated from sodium's chunk_vertex.glsl - "vec3 _vert_position;", - "vec2 _vert_tex_diffuse_coord;", - "vec2 _vert_tex_light_coord;", - "vec4 _vert_color;", - "uint _draw_id;", - "in vec4 a_PosId;", - "in vec4 a_Color;", - "in vec2 a_TexCoord;", - "in vec2 a_LightCoord;", - "void _vert_init() {" + - "_vert_position = (a_PosId.xyz * " + String.valueOf(parameters.positionScale) + " + " - + String.valueOf(parameters.positionOffset) + ");" + - "_vert_tex_diffuse_coord = (a_TexCoord * " + String.valueOf(parameters.textureScale) + ");" + - "_vert_tex_light_coord = a_LightCoord;" + - "_vert_color = a_Color;" + - "_draw_id = uint(a_PosId.w); }", - - // translated from sodium's chunk_parameters.glsl - // Comment on the struct: - // Older AMD drivers can't handle vec3 in std140 layouts correctly The alignment - // requirement is 16 bytes (4 float components) anyways, so we're not wasting - // extra memory with this, only fixing broken drivers. - "struct DrawParameters { vec4 offset; };", - "layout(std140) uniform ubo_DrawParameters {DrawParameters Chunks[256]; };", - "uniform mat4 iris_ProjectionMatrix;", "uniform mat4 iris_ModelViewMatrix;", "uniform vec3 u_RegionOffset;", // _draw_translation replaced with Chunks[_draw_id].offset.xyz "vec4 getVertexPosition() { return vec4(u_RegionOffset + Chunks[_draw_id].offset.xyz + _vert_position, 1.0); }"); - tree.prependMainFunctionBody(t, "_vert_init();"); root.replaceReferenceExpressions(t, "gl_Vertex", "getVertexPosition()"); + + // inject here so that _vert_position is available to the above. (injections + // inject in reverse order if performed piece-wise but in correct order if + // performed as an array of injections) + injectVertInit(t, tree, root, parameters); } else { tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "uniform mat4 iris_ModelViewMatrix;", @@ -130,4 +118,88 @@ public static void transform( CommonTransformer.applyIntelHd4000Workaround(root); } + + public static void injectVertInit( + ASTParser t, + TranslationUnit tree, + Root root, + SodiumParameters parameters) { + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_FUNCTIONS, + // translated from sodium's chunk_vertex.glsl + "vec3 _vert_position;", + "vec2 _vert_tex_diffuse_coord;", + "ivec2 _vert_tex_light_coord;", + "vec4 _vert_color;", + "uint _draw_id;", + "void _vert_init() {" + + "_vert_position = (a_PosId.xyz * " + parameters.positionScale + " + " + + parameters.positionOffset + ");" + + "_vert_tex_diffuse_coord = (a_TexCoord * " + parameters.textureScale + ");" + + "_vert_tex_light_coord = a_LightCoord;" + + "_vert_color = a_Color;" + + "_draw_id = uint(a_PosId.w); }", + + // translated from sodium's chunk_parameters.glsl + // Comment on the struct: + // Older AMD drivers can't handle vec3 in std140 layouts correctly The alignment + // requirement is 16 bytes (4 float components) anyways, so we're not wasting + // extra memory with this, only fixing broken drivers. + "struct DrawParameters { vec4 offset; };", + "layout(std140) uniform ubo_DrawParameters {DrawParameters Chunks[256]; };"); + addIfNotExists(root, t, tree, "a_PosId", Type.F32VEC4, StorageQualifier.StorageType.IN); + addIfNotExists(root, t, tree, "a_TexCoord", Type.F32VEC2, StorageQualifier.StorageType.IN); + addIfNotExists(root, t, tree, "a_Color", Type.F32VEC4, StorageQualifier.StorageType.IN); + addIfNotExists(root, t, tree, "a_LightCoord", Type.I32VEC2, StorageQualifier.StorageType.IN); + tree.prependMainFunctionBody(t, "_vert_init();"); + } + + + public static void replaceMidTexCoord(ASTParser t, + TranslationUnit tree, Root root, float textureScale) { + Type dimension = Type.BOOL; + for (Identifier id : root.identifierIndex.get("mc_midTexCoord")) { + TypeAndInitDeclaration initDeclaration = (TypeAndInitDeclaration) id.getAncestor( + 2, 0, TypeAndInitDeclaration.class::isInstance); + if (initDeclaration == null) { + continue; + } + DeclarationExternalDeclaration declaration = (DeclarationExternalDeclaration) initDeclaration.getAncestor( + 1, 0, DeclarationExternalDeclaration.class::isInstance); + if (declaration == null) { + continue; + } + if (initDeclaration.getType().getTypeSpecifier() instanceof BuiltinNumericTypeSpecifier numeric) { + dimension = numeric.type; + + declaration.detachAndDelete(); + initDeclaration.detachAndDelete(); + id.detachAndDelete(); + break; + } + } + + + root.replaceReferenceExpressions(t, "mc_midTexCoord", "iris_MidTex"); + + switch (dimension) { + case BOOL: + return; + case FLOAT32: + tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "float iris_MidTex = (mc_midTexCoord.x * " + textureScale + ").x;"); + break; + case F32VEC2: + tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "vec2 iris_MidTex = (mc_midTexCoord.xy * " + textureScale + ").xy;"); + break; + case F32VEC3: + tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "vec3 iris_MidTex = vec3(mc_midTexCoord.xy * " + textureScale + ", 0.0);"); + break; + case F32VEC4: + tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "vec4 iris_MidTex = vec4(mc_midTexCoord.xy * " + textureScale + ", 0.0, 1.0);"); + break; + default: + throw new IllegalStateException("Somehow got a midTexCoord that is *above* 4 dimensions???"); + } + + tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "in vec2 mc_midTexCoord;"); + } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/TextureTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/TextureTransformer.java index ffc54fd7ae..416ea5d1cb 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/TextureTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/TextureTransformer.java @@ -46,24 +46,26 @@ && isTypeValid(stringTextureTypeTextureStageTri.getSecond(), fixed.type)) { } private static boolean isTypeValid(TextureType expectedType, BuiltinFixedTypeSpecifier.BuiltinType extractedType) { - if (expectedType == TextureType.TEXTURE_1D) { - return extractedType == BuiltinFixedTypeSpecifier.BuiltinType.SAMPLER1D || - extractedType == BuiltinFixedTypeSpecifier.BuiltinType.ISAMPLER1D || - extractedType == BuiltinFixedTypeSpecifier.BuiltinType.USAMPLER1D; - } else if (expectedType == TextureType.TEXTURE_RECTANGLE) { - return extractedType == BuiltinFixedTypeSpecifier.BuiltinType.SAMPLER2DRECT || - extractedType == BuiltinFixedTypeSpecifier.BuiltinType.ISAMPLER2DRECT || - extractedType == BuiltinFixedTypeSpecifier.BuiltinType.USAMPLER2DRECT; - } else if (expectedType == TextureType.TEXTURE_2D) { - return extractedType == BuiltinFixedTypeSpecifier.BuiltinType.SAMPLER2D || - extractedType == BuiltinFixedTypeSpecifier.BuiltinType.ISAMPLER2D || - extractedType == BuiltinFixedTypeSpecifier.BuiltinType.USAMPLER2D; - } else if (expectedType == TextureType.TEXTURE_3D) { - return extractedType == BuiltinFixedTypeSpecifier.BuiltinType.SAMPLER3D || - extractedType == BuiltinFixedTypeSpecifier.BuiltinType.ISAMPLER3D || - extractedType == BuiltinFixedTypeSpecifier.BuiltinType.USAMPLER3D; - } else { - throw new IllegalStateException("Unexpected enum! " + expectedType); + switch (expectedType) { + case TEXTURE_1D: + return extractedType == BuiltinFixedTypeSpecifier.BuiltinType.SAMPLER1D || + extractedType == BuiltinFixedTypeSpecifier.BuiltinType.ISAMPLER1D || + extractedType == BuiltinFixedTypeSpecifier.BuiltinType.USAMPLER1D; + case TEXTURE_RECTANGLE: + return extractedType == BuiltinFixedTypeSpecifier.BuiltinType.SAMPLER2DRECT || + extractedType == BuiltinFixedTypeSpecifier.BuiltinType.ISAMPLER2DRECT || + extractedType == BuiltinFixedTypeSpecifier.BuiltinType.USAMPLER2DRECT; + case TEXTURE_2D: + return extractedType == BuiltinFixedTypeSpecifier.BuiltinType.SAMPLER2D || + extractedType == BuiltinFixedTypeSpecifier.BuiltinType.ISAMPLER2D || + extractedType == BuiltinFixedTypeSpecifier.BuiltinType.USAMPLER2D; + case TEXTURE_3D: + return extractedType == BuiltinFixedTypeSpecifier.BuiltinType.SAMPLER3D || + extractedType == BuiltinFixedTypeSpecifier.BuiltinType.ISAMPLER3D || + extractedType == BuiltinFixedTypeSpecifier.BuiltinType.USAMPLER3D; + default: + // not TransformationException because this should never happen + throw new IllegalStateException("Unexpected enum! " + expectedType); } } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/VanillaCoreTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/VanillaCoreTransformer.java new file mode 100644 index 0000000000..4b838304bf --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/VanillaCoreTransformer.java @@ -0,0 +1,91 @@ +package net.coderbot.iris.pipeline.transform.transformer; + +import static net.coderbot.iris.pipeline.transform.transformer.CommonTransformer.addIfNotExists; + +import io.github.douira.glsl_transformer.ast.node.TranslationUnit; +import io.github.douira.glsl_transformer.ast.node.type.qualifier.StorageQualifier.StorageType; +import io.github.douira.glsl_transformer.ast.query.Root; +import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import io.github.douira.glsl_transformer.util.Type; +import net.coderbot.iris.pipeline.transform.PatchShaderType; +import net.coderbot.iris.pipeline.transform.parameter.VanillaParameters; + +public class VanillaCoreTransformer { + public static void transform( + ASTParser t, + TranslationUnit tree, + Root root, + VanillaParameters parameters) { + + if (parameters.inputs.hasOverlay()) { + if (!parameters.inputs.isText()) { + AttributeTransformer.patchOverlayColor(t, tree, root, parameters); + } + AttributeTransformer.patchEntityId(t, tree, root, parameters); + } + + CommonTransformer.transform(t, tree, root, parameters, true); + root.rename("alphaTestRef", "iris_currentAlphaTest"); + root.rename("modelViewMatrix", "iris_ModelViewMat"); + root.rename("gl_ModelViewMatrix", "iris_ModelViewMat"); + root.rename("modelViewMatrixInverse", "iris_ModelViewMatInverse"); + root.rename("gl_ModelViewMatrixInverse", "iris_ModelViewMatInverse"); + root.rename("projectionMatrix", "iris_ProjMat"); + root.rename("gl_ProjectionMatrix", "iris_ProjMat"); + root.rename("projectionMatrixInverse", "iris_ProjMatInverse"); + root.rename("gl_ProjectionMatrixInverse", "iris_ProjMatInverse"); + root.rename("textureMatrix", "iris_TextureMat"); + + root.replaceExpressionMatches(t, CommonTransformer.glTextureMatrix0, "iris_TextureMat"); + root.replaceExpressionMatches(t, CommonTransformer.glTextureMatrix1, + "mat4(vec4(0.00390625, 0.0, 0.0, 0.0), vec4(0.0, 0.00390625, 0.0, 0.0), vec4(0.0, 0.0, 0.00390625, 0.0), vec4(0.03125, 0.03125, 0.03125, 1.0))"); + root.replaceExpressionMatches(t, CommonTransformer.glTextureMatrix2, + "mat4(vec4(0.00390625, 0.0, 0.0, 0.0), vec4(0.0, 0.00390625, 0.0, 0.0), vec4(0.0, 0.0, 0.00390625, 0.0), vec4(0.03125, 0.03125, 0.03125, 1.0))"); + addIfNotExists(root, t, tree, "iris_TextureMat", Type.F32MAT4X4, StorageType.UNIFORM); + addIfNotExists(root, t, tree, "iris_ProjMat", Type.F32MAT4X4, StorageType.UNIFORM); + addIfNotExists(root, t, tree, "iris_ProjMatInverse", Type.F32MAT4X4, StorageType.UNIFORM); + addIfNotExists(root, t, tree, "iris_ModelViewMat", Type.F32MAT4X4, StorageType.UNIFORM); + addIfNotExists(root, t, tree, "iris_ModelViewMatInverse", Type.F32MAT4X4, StorageType.UNIFORM); + root.rename("normalMatrix", "iris_NormalMat"); + root.rename("gl_NormalMatrix", "iris_NormalMat"); + addIfNotExists(root, t, tree, "iris_NormalMat", Type.F32MAT3X3, StorageType.UNIFORM); + root.rename("chunkOffset", "iris_ChunkOffset"); + addIfNotExists(root, t, tree, "iris_ChunkOffset", Type.F32VEC3, StorageType.UNIFORM); + + CommonTransformer.upgradeStorageQualifiers(t, tree, root, parameters); + + if (parameters.type == PatchShaderType.VERTEX) { + root.replaceReferenceExpressions(t, "gl_Vertex", "vec4(iris_Position, 1.0)"); + root.rename("vaPosition", "iris_Position"); + if (parameters.inputs.hasColor()) { + root.replaceReferenceExpressions(t, "vaColor", "iris_Color * iris_ColorModulator"); + root.replaceReferenceExpressions(t, "gl_Color", "iris_Color * iris_ColorModulator"); + } else { + root.replaceReferenceExpressions(t, "vaColor", "iris_ColorModulator"); + root.replaceReferenceExpressions(t, "gl_Color", "iris_ColorModulator"); + } + root.rename("vaNormal", "iris_Normal"); + root.rename("gl_Normal", "iris_Normal"); + root.rename("vaUV0", "iris_UV0"); + root.replaceReferenceExpressions(t, "gl_MultiTexCoord0", "vec4(iris_UV0, 0.0, 1.0)"); + if (parameters.inputs.hasLight()) { + root.replaceReferenceExpressions(t, "gl_MultiTexCoord1", "vec4(iris_UV2, 0.0, 1.0)"); + root.replaceReferenceExpressions(t, "gl_MultiTexCoord2", "vec4(iris_UV2, 0.0, 1.0)"); + root.rename("vaUV2", "iris_UV2"); + } else { + root.replaceReferenceExpressions(t, "gl_MultiTexCoord1", "vec4(240.0, 240.0, 0.0, 1.0)"); + root.replaceReferenceExpressions(t, "gl_MultiTexCoord2", "vec4(240.0, 240.0, 0.0, 1.0)"); + root.rename("vaUV2", "iris_UV2"); + } + root.rename("vaUV1", "iris_UV1"); + + addIfNotExists(root, t, tree, "iris_Color", Type.F32VEC4, StorageType.IN); + addIfNotExists(root, t, tree, "iris_ColorModulator", Type.F32VEC4, StorageType.UNIFORM); + addIfNotExists(root, t, tree, "iris_Position", Type.F32VEC3, StorageType.IN); + addIfNotExists(root, t, tree, "iris_Normal", Type.F32VEC3, StorageType.IN); + addIfNotExists(root, t, tree, "iris_UV0", Type.F32VEC2, StorageType.IN); + addIfNotExists(root, t, tree, "iris_UV1", Type.F32VEC2, StorageType.IN); + addIfNotExists(root, t, tree, "iris_UV2", Type.F32VEC2, StorageType.IN); + } + } +} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/VanillaTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/VanillaTransformer.java index 283448181c..9daf155061 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/VanillaTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/VanillaTransformer.java @@ -6,6 +6,7 @@ import io.github.douira.glsl_transformer.ast.transform.ASTParser; import net.coderbot.iris.gl.shader.ShaderType; import net.coderbot.iris.pipeline.newshader.AlphaTests; +import net.coderbot.iris.pipeline.transform.PatchShaderType; import net.coderbot.iris.pipeline.transform.parameter.VanillaParameters; public class VanillaTransformer { @@ -17,10 +18,13 @@ public static void transform( // this happens before common to make sure the renaming of attributes is done on // attribute inserted by this if (parameters.inputs.hasOverlay()) { - AttributeTransformer.patchOverlayColor(t, tree, root, parameters); + if (!parameters.inputs.isText()) { + AttributeTransformer.patchOverlayColor(t, tree, root, parameters); + } + AttributeTransformer.patchEntityId(t, tree, root, parameters); } - CommonTransformer.transform(t, tree, root, parameters); + CommonTransformer.transform(t, tree, root, parameters, false); if (parameters.type.glShaderType == ShaderType.VERTEX) { // Alias of gl_MultiTexCoord1 on 1.15+ for OptiFine @@ -58,7 +62,7 @@ public static void transform( tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "uniform vec4 iris_ColorModulator;"); - if (parameters.inputs.hasColor()) { + if (parameters.inputs.hasColor() && parameters.type == PatchShaderType.VERTEX) { // TODO: Handle the fragment / geometry shader here if (parameters.alpha == AlphaTests.VERTEX_ALPHA) { root.replaceReferenceExpressions(t, "gl_Color", diff --git a/src/main/java/net/coderbot/iris/postprocess/CompositeRenderer.java b/src/main/java/net/coderbot/iris/postprocess/CompositeRenderer.java index 22a9690e95..c50646d327 100644 --- a/src/main/java/net/coderbot/iris/postprocess/CompositeRenderer.java +++ b/src/main/java/net/coderbot/iris/postprocess/CompositeRenderer.java @@ -1,41 +1,41 @@ package net.coderbot.iris.postprocess; -import java.util.Arrays; -import java.util.Map; -import java.util.Objects; -import java.util.function.IntSupplier; -import java.util.function.Supplier; - import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gl.IrisRenderSystem; +import net.coderbot.iris.gl.blending.BlendModeOverride; +import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; import net.coderbot.iris.gl.framebuffer.GlFramebuffer; -import net.coderbot.iris.gl.program.ComputeProgram; -import net.coderbot.iris.gl.program.Program; -import net.coderbot.iris.gl.program.ProgramBuilder; -import net.coderbot.iris.gl.program.ProgramSamplers; -import net.coderbot.iris.gl.program.ProgramUniforms; +import net.coderbot.iris.gl.framebuffer.ViewportData; +import net.coderbot.iris.gl.image.GlImage; +import net.coderbot.iris.gl.program.*; import net.coderbot.iris.gl.sampler.SamplerLimits; import net.coderbot.iris.gl.texture.TextureAccess; +import net.coderbot.iris.mixin.GlStateManagerAccessor; import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline; import net.coderbot.iris.pipeline.WorldRenderingPipeline; import net.coderbot.iris.rendertarget.RenderTarget; -import net.coderbot.iris.pipeline.PatchedShaderPrinter; +import net.coderbot.iris.pipeline.ShaderPrinter; +import net.coderbot.iris.pipeline.WorldRenderingPipeline; +import net.coderbot.iris.pipeline.newshader.FogMode; import net.coderbot.iris.pipeline.transform.PatchShaderType; import net.coderbot.iris.pipeline.transform.TransformPatcher; -import net.coderbot.iris.pipeline.newshader.FogMode; +import net.coderbot.iris.rendertarget.RenderTarget; import net.coderbot.iris.rendertarget.RenderTargets; import net.coderbot.iris.samplers.IrisImages; import net.coderbot.iris.samplers.IrisSamplers; import net.coderbot.iris.shaderpack.ComputeSource; +import net.coderbot.iris.shaderpack.FilledIndirectPointer; import net.coderbot.iris.shaderpack.PackDirectives; import net.coderbot.iris.shaderpack.PackRenderTargetDirectives; import net.coderbot.iris.shaderpack.ProgramDirectives; import net.coderbot.iris.shaderpack.ProgramSource; +import net.coderbot.iris.shaderpack.*; import net.coderbot.iris.shaderpack.texture.TextureStage; import net.coderbot.iris.shadows.ShadowRenderTargets; import net.coderbot.iris.uniforms.CommonUniforms; @@ -45,9 +45,12 @@ import org.lwjgl.opengl.GL15C; import org.lwjgl.opengl.GL20C; import org.lwjgl.opengl.GL30C; +import org.lwjgl.opengl.GL43C; +import java.util.Arrays; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.function.Supplier; public class CompositeRenderer { @@ -61,14 +64,15 @@ public class CompositeRenderer { private final ImmutableSet flippedAtLeastOnceFinal; private final CustomUniforms customUniforms; private final Object2ObjectMap irisCustomTextures; + private final Set customImages; private TextureStage textureStage; private WorldRenderingPipeline pipeline; - public CompositeRenderer(WorldRenderingPipeline pipeline, PackDirectives packDirectives, ProgramSource[] sources, ComputeSource[][] computes, RenderTargets renderTargets, + public CompositeRenderer(WorldRenderingPipeline pipeline, PackDirectives packDirectives, ProgramSource[] sources, ComputeSource[][] computes, RenderTargets renderTargets, ShaderStorageBufferHolder holder, TextureAccess noiseTexture, FrameUpdateNotifier updateNotifier, CenterDepthSampler centerDepthSampler, BufferFlipper bufferFlipper, Supplier shadowTargetsSupplier, TextureStage textureStage, - Object2ObjectMap customTextureIds, Object2ObjectMap irisCustomTextures, ImmutableMap explicitPreFlips, + Object2ObjectMap customTextureIds, Object2ObjectMap irisCustomTextures, Set customImages, ImmutableMap explicitPreFlips, CustomUniforms customUniforms) { this.pipeline = pipeline; this.noiseTexture = noiseTexture; @@ -78,6 +82,7 @@ public CompositeRenderer(WorldRenderingPipeline pipeline, PackDirectives packDir this.customTextureIds = customTextureIds; this.customUniforms = customUniforms; this.irisCustomTextures = irisCustomTextures; + this.customImages = customImages; this.textureStage = textureStage; final PackRenderTargetDirectives renderTargetDirectives = packDirectives.getRenderTargetDirectives(); @@ -103,7 +108,7 @@ public CompositeRenderer(WorldRenderingPipeline pipeline, PackDirectives packDir if (source == null || !source.isValid()) { if (computes[i] != null) { ComputeOnlyPass pass = new ComputeOnlyPass(); - pass.computes = createComputes(computes[i], flipped, flippedAtLeastOnceSnapshot, shadowTargetsSupplier); + pass.computes = createComputes(computes[i], flipped, flippedAtLeastOnceSnapshot, shadowTargetsSupplier, holder); passes.add(pass); } continue; @@ -113,7 +118,8 @@ public CompositeRenderer(WorldRenderingPipeline pipeline, PackDirectives packDir ProgramDirectives directives = source.getDirectives(); pass.program = createProgram(source, flipped, flippedAtLeastOnceSnapshot, shadowTargetsSupplier); - pass.computes = createComputes(computes[i], flipped, flippedAtLeastOnceSnapshot, shadowTargetsSupplier); + pass.blendModeOverride = source.getDirectives().getBlendModeOverride().orElse(null); + pass.computes = createComputes(computes[i], flipped, flippedAtLeastOnceSnapshot, shadowTargetsSupplier, holder); int[] drawBuffers = directives.getDrawBuffers(); @@ -121,6 +127,8 @@ public CompositeRenderer(WorldRenderingPipeline pipeline, PackDirectives packDir // Flip the buffers that this shader wrote to, and set pass width and height ImmutableMap explicitFlips = directives.getExplicitFlips(); + GlFramebuffer framebuffer = renderTargets.createColorFramebuffer(flipped, drawBuffers); + for (int buffer : drawBuffers) { RenderTarget target = renderTargets.get(buffer); if ((passWidth > 0 && passWidth != target.getWidth()) || (passHeight > 0 && passHeight != target.getHeight())) { @@ -138,8 +146,6 @@ public CompositeRenderer(WorldRenderingPipeline pipeline, PackDirectives packDir flippedAtLeastOnce.add(buffer); } - GlFramebuffer framebuffer = renderTargets.createColorFramebuffer(flipped, drawBuffers); - explicitFlips.forEach((buffer, shouldFlip) -> { if (shouldFlip) { bufferFlipper.flip(buffer); @@ -196,12 +202,13 @@ private static class Pass { int viewWidth; int viewHeight; Program program; + BlendModeOverride blendModeOverride; ComputeProgram[] computes; GlFramebuffer framebuffer; ImmutableSet flippedAtLeastOnce; ImmutableSet stageReadsFromAlt; ImmutableSet mipmappedBuffers; - float viewportScale; + ViewportData viewportScale; protected void destroy() { this.program.destroy(); @@ -242,7 +249,7 @@ public void renderAll() { } if (ranCompute) { - IrisRenderSystem.memoryBarrier(40); + IrisRenderSystem.memoryBarrier(GL43C.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL43C.GL_TEXTURE_FETCH_BARRIER_BIT | GL43C.GL_SHADER_STORAGE_BARRIER_BIT); } Program.unbind(); @@ -259,17 +266,26 @@ public void renderAll() { } } - float scaledWidth = renderPass.viewWidth * renderPass.viewportScale; - float scaledHeight = renderPass.viewHeight * renderPass.viewportScale; - RenderSystem.viewport(0, 0, (int) scaledWidth, (int) scaledHeight); + float scaledWidth = renderPass.viewWidth * renderPass.viewportScale.scale(); + float scaledHeight = renderPass.viewHeight * renderPass.viewportScale.scale(); + int beginWidth = (int) (renderPass.viewWidth * renderPass.viewportScale.viewportX()); + int beginHeight = (int) (renderPass.viewHeight * renderPass.viewportScale.viewportY()); + RenderSystem.viewport(beginWidth, beginHeight, (int) scaledWidth, (int) scaledHeight); renderPass.framebuffer.bind(); renderPass.program.use(); + if (renderPass.blendModeOverride != null) { + renderPass.blendModeOverride.apply(); + } else { + RenderSystem.disableBlend(); + } // program is the identifier for composite :shrug: this.customUniforms.push(renderPass.program); FullScreenQuadRenderer.INSTANCE.renderQuad(); + + BlendModeOverride.restore(); } FullScreenQuadRenderer.INSTANCE.end(); @@ -285,14 +301,18 @@ public void renderAll() { for (int i = 0; i < SamplerLimits.get().getMaxTextureUnits(); i++) { // Unbind all textures that we may have used. // NB: This is necessary for shader pack reloading to work propely - RenderSystem.activeTexture(GL15C.GL_TEXTURE0 + i); - RenderSystem.bindTexture(0); + if (GlStateManagerAccessor.getTEXTURES()[i].binding != 0) { + RenderSystem.activeTexture(GL15C.GL_TEXTURE0 + i); + RenderSystem.bindTexture(0); + } } RenderSystem.activeTexture(GL15C.GL_TEXTURE0); } private static void setupMipmapping(net.coderbot.iris.rendertarget.RenderTarget target, boolean readFromAlt) { + if (target == null) return; + int texture = readFromAlt ? target.getAltTexture() : target.getMainTexture(); // TODO: Only generate the mipmap if a valid mipmap hasn't been generated or if we've written to the buffer @@ -327,7 +347,8 @@ private Program createProgram(ProgramSource source, ImmutableSet flippe String vertex = transformed.get(PatchShaderType.VERTEX); String geometry = transformed.get(PatchShaderType.GEOMETRY); String fragment = transformed.get(PatchShaderType.FRAGMENT); - PatchedShaderPrinter.debugPatchedShaders(source.getName(), vertex, geometry, fragment); + + ShaderPrinter.printProgram(source.getName()).addSources(transformed).print(); Objects.requireNonNull(flipped); ProgramBuilder builder; @@ -337,7 +358,7 @@ private Program createProgram(ProgramSource source, ImmutableSet flippe IrisSamplers.COMPOSITE_RESERVED_TEXTURE_UNITS); } catch (RuntimeException e) { // TODO: Better error handling - throw new RuntimeException("Shader compilation failed!", e); + throw new RuntimeException("Shader compilation failed for " + source.getName() + "!", e); } @@ -348,14 +369,16 @@ private Program createProgram(ProgramSource source, ImmutableSet flippe IrisSamplers.addRenderTargetSamplers(customTextureSamplerInterceptor, () -> flipped, renderTargets, true); IrisSamplers.addCustomTextures(builder, irisCustomTextures); + IrisSamplers.addCustomImages(customTextureSamplerInterceptor, customImages); IrisImages.addRenderTargetImages(builder, () -> flipped, renderTargets); + IrisImages.addCustomImages(builder, customImages); IrisSamplers.addNoiseSampler(customTextureSamplerInterceptor, noiseTexture); IrisSamplers.addCompositeSamplers(customTextureSamplerInterceptor, renderTargets); if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, pipeline.hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS)); IrisImages.addShadowColorImages(builder, shadowTargetsSupplier.get(), null); } @@ -371,7 +394,7 @@ private Program createProgram(ProgramSource source, ImmutableSet flippe return build; } - private ComputeProgram[] createComputes(ComputeSource[] compute, ImmutableSet flipped, ImmutableSet flippedAtLeastOnceSnapshot, Supplier shadowTargetsSupplier) { + private ComputeProgram[] createComputes(ComputeSource[] compute, ImmutableSet flipped, ImmutableSet flippedAtLeastOnceSnapshot, Supplier shadowTargetsSupplier, ShaderStorageBufferHolder holder) { ComputeProgram[] programs = new ComputeProgram[compute.length]; for (int i = 0; i < programs.length; i++) { ComputeSource source = compute[i]; @@ -383,10 +406,14 @@ private ComputeProgram[] createComputes(ComputeSource[] compute, ImmutableSet flipped, renderTargets, true); IrisSamplers.addCustomTextures(builder, irisCustomTextures); + IrisSamplers.addCustomImages(customTextureSamplerInterceptor, customImages); IrisImages.addRenderTargetImages(builder, () -> flipped, renderTargets); + IrisImages.addCustomImages(builder, customImages); IrisSamplers.addNoiseSampler(customTextureSamplerInterceptor, noiseTexture); IrisSamplers.addCompositeSamplers(customTextureSamplerInterceptor, renderTargets); if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, pipeline.hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS)); IrisImages.addShadowColorImages(builder, shadowTargetsSupplier.get(), null); } @@ -415,7 +444,7 @@ private ComputeProgram[] createComputes(ComputeSource[] compute, ImmutableSet irisCustomTextures; + private final Set customImages; private int lastColorTextureId; private int lastColorTextureVersion; private final TextureAccess noiseTexture; @@ -66,18 +67,19 @@ public class FinalPassRenderer { private final CustomUniforms customUniforms; // TODO: The length of this argument list is getting a bit ridiculous - public FinalPassRenderer(WorldRenderingPipeline pipeline, ProgramSet pack, RenderTargets renderTargets, TextureAccess noiseTexture, + public FinalPassRenderer(WorldRenderingPipeline pipeline, ProgramSet pack, RenderTargets renderTargets, TextureAccess noiseTexture, ShaderStorageBufferHolder holder, FrameUpdateNotifier updateNotifier, ImmutableSet flippedBuffers, CenterDepthSampler centerDepthSampler, Supplier shadowTargetsSupplier, Object2ObjectMap customTextureIds, - Object2ObjectMap irisCustomTextures, ImmutableSet flippedAtLeastOnce + Object2ObjectMap irisCustomTextures, Set customImages, ImmutableSet flippedAtLeastOnce , CustomUniforms customUniforms) { this.pipeline = pipeline; this.updateNotifier = updateNotifier; this.centerDepthSampler = centerDepthSampler; this.customTextureIds = customTextureIds; this.irisCustomTextures = irisCustomTextures; + this.customImages = customImages; final PackRenderTargetDirectives renderTargetDirectives = pack.getPackDirectives().getRenderTargetDirectives(); final Map renderTargetSettings = @@ -91,7 +93,7 @@ public FinalPassRenderer(WorldRenderingPipeline pipeline, ProgramSet pack, Rende ProgramDirectives directives = source.getDirectives(); pass.program = createProgram(source, flippedBuffers, flippedAtLeastOnce, shadowTargetsSupplier); - pass.computes = createComputes(pack.getFinalCompute(), flippedBuffers, flippedAtLeastOnce, shadowTargetsSupplier); + pass.computes = createComputes(pack.getFinalCompute(), flippedBuffers, flippedAtLeastOnce, shadowTargetsSupplier, holder); pass.stageReadsFromAlt = flippedBuffers; pass.mipmappedBuffers = directives.getMipmappedBuffers(); @@ -123,7 +125,7 @@ public FinalPassRenderer(WorldRenderingPipeline pipeline, ProgramSet pack, Rende } SwapPass swap = new SwapPass(); - RenderTarget target1 = renderTargets.get(target); + RenderTarget target1 = renderTargets.getOrCreate(target); swap.target = target; swap.width = target1.getWidth(); swap.height = target1.getHeight(); @@ -202,7 +204,7 @@ public void renderFinalPass() { } } - IrisRenderSystem.memoryBarrier(40); + IrisRenderSystem.memoryBarrier(GL43C.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL43C.GL_TEXTURE_FETCH_BARRIER_BIT | GL43C.GL_SHADER_STORAGE_BARRIER_BIT); if (!finalPass.mipmappedBuffers.isEmpty()) { RenderSystem.activeTexture(GL15C.GL_TEXTURE0); @@ -268,8 +270,10 @@ public void renderFinalPass() { for (int i = 0; i < SamplerLimits.get().getMaxTextureUnits(); i++) { // Unbind all textures that we may have used. // NB: This is necessary for shader pack reloading to work properly - RenderSystem.activeTexture(GL15C.GL_TEXTURE0 + i); - RenderSystem.bindTexture(0); + if (GlStateManagerAccessor.getTEXTURES()[i].binding != 0) { + RenderSystem.activeTexture(GL15C.GL_TEXTURE0 + i); + RenderSystem.bindTexture(0); + } } RenderSystem.activeTexture(GL15C.GL_TEXTURE0); @@ -287,6 +291,8 @@ public void recalculateSwapPassSize() { } private static void setupMipmapping(RenderTarget target, boolean readFromAlt) { + if (target == null) return; + int texture = readFromAlt ? target.getAltTexture() : target.getMainTexture(); // TODO: Only generate the mipmap if a valid mipmap hasn't been generated or if we've written to the buffer @@ -311,6 +317,7 @@ private static void setupMipmapping(RenderTarget target, boolean readFromAlt) { } private static void resetRenderTarget(RenderTarget target) { + if (target == null) return; // Resets the sampling mode of the given render target and then unbinds it to prevent accidental sampling of it // elsewhere. int filter = GL20C.GL_LINEAR; @@ -335,7 +342,8 @@ private Program createProgram(ProgramSource source, ImmutableSet flippe String vertex = transformed.get(PatchShaderType.VERTEX); String geometry = transformed.get(PatchShaderType.GEOMETRY); String fragment = transformed.get(PatchShaderType.FRAGMENT); - PatchedShaderPrinter.debugPatchedShaders(source.getName(), vertex, geometry, fragment); + + ShaderPrinter.printProgram(source.getName()).addSources(transformed).print(); Objects.requireNonNull(flipped); @@ -343,10 +351,10 @@ private Program createProgram(ProgramSource source, ImmutableSet flippe try { builder = ProgramBuilder.begin(source.getName(), vertex, geometry, fragment, - IrisSamplers.COMPOSITE_RESERVED_TEXTURE_UNITS); + IrisSamplers.COMPOSITE_RESERVED_TEXTURE_UNITS); } catch (RuntimeException e) { // TODO: Better error handling - throw new RuntimeException("Shader compilation failed!", e); + throw new RuntimeException("Shader compilation failed for final!", e); } CommonUniforms.addDynamicUniforms(builder, FogMode.OFF); @@ -355,13 +363,16 @@ private Program createProgram(ProgramSource source, ImmutableSet flippe ProgramSamplers.CustomTextureSamplerInterceptor customTextureSamplerInterceptor = ProgramSamplers.customTextureSamplerInterceptor(builder, customTextureIds, flippedAtLeastOnceSnapshot); IrisSamplers.addRenderTargetSamplers(customTextureSamplerInterceptor, () -> flipped, renderTargets, true); + IrisSamplers.addCustomImages(customTextureSamplerInterceptor, customImages); IrisImages.addRenderTargetImages(builder, () -> flipped, renderTargets); + IrisImages.addCustomImages(builder, customImages); + IrisSamplers.addCustomTextures(builder, irisCustomTextures); IrisSamplers.addNoiseSampler(customTextureSamplerInterceptor, noiseTexture); IrisSamplers.addCompositeSamplers(customTextureSamplerInterceptor, renderTargets); if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, pipeline.hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS)); IrisImages.addShadowColorImages(builder, shadowTargetsSupplier.get(), null); } @@ -377,7 +388,7 @@ private Program createProgram(ProgramSource source, ImmutableSet flippe return build; } - private ComputeProgram[] createComputes(ComputeSource[] compute, ImmutableSet flipped, ImmutableSet flippedAtLeastOnceSnapshot, Supplier shadowTargetsSupplier) { + private ComputeProgram[] createComputes(ComputeSource[] compute, ImmutableSet flipped, ImmutableSet flippedAtLeastOnceSnapshot, Supplier shadowTargetsSupplier, ShaderStorageBufferHolder holder) { ComputeProgram[] programs = new ComputeProgram[compute.length]; for (int i = 0; i < programs.length; i++) { ComputeSource source = compute[i]; @@ -389,10 +400,14 @@ private ComputeProgram[] createComputes(ComputeSource[] compute, ImmutableSet flipped, renderTargets, true); IrisSamplers.addCustomTextures(builder, irisCustomTextures); + IrisSamplers.addCustomImages(customTextureSamplerInterceptor, customImages); IrisImages.addRenderTargetImages(builder, () -> flipped, renderTargets); + IrisImages.addCustomImages(builder, customImages); IrisSamplers.addNoiseSampler(customTextureSamplerInterceptor, noiseTexture); IrisSamplers.addCompositeSamplers(customTextureSamplerInterceptor, renderTargets); if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, pipeline.hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS)); IrisImages.addShadowColorImages(builder, shadowTargetsSupplier.get(), null); } @@ -420,7 +437,7 @@ private ComputeProgram[] createComputes(ComputeSource[] compute, ImmutableSet ownedFramebuffers; + private final Map targetSettingsMap; + private final PackDirectives packDirectives; private int cachedWidth; private int cachedHeight; @@ -43,13 +45,8 @@ public class RenderTargets { public RenderTargets(int width, int height, int depthTexture, int depthBufferVersion, DepthBufferFormat depthFormat, Map renderTargets, PackDirectives packDirectives) { targets = new RenderTarget[renderTargets.size()]; - renderTargets.forEach((index, settings) -> { - // TODO: Handle mipmapping? - Vector2i dimensions = packDirectives.getTextureScaleOverride(index, width, height); - targets[index] = RenderTarget.builder().setDimensions(dimensions.x, dimensions.y) - .setInternalFormat(settings.getInternalFormat()) - .setPixelFormat(settings.getInternalFormat().getPixelFormat()).build(); - }); + targetSettingsMap = renderTargets; + this.packDirectives = packDirectives; this.currentDepthTexture = depthTexture; this.currentDepthFormat = depthFormat; @@ -88,7 +85,9 @@ public void destroy() { } for (RenderTarget target : targets) { - target.destroy(); + if (target != null) { + target.destroy(); + } } noTranslucents.destroy(); @@ -104,9 +103,33 @@ public RenderTarget get(int index) { throw new IllegalStateException("Tried to use destroyed RenderTargets"); } + if (targets[index] == null) { + return null; + } + + return targets[index]; + } + + public RenderTarget getOrCreate(int index) { + if (destroyed) { + throw new IllegalStateException("Tried to use destroyed RenderTargets"); + } + + if (targets[index] != null) return targets[index]; + + create(index); + return targets[index]; } + private void create(int index) { + PackRenderTargetDirectives.RenderTargetSettings settings = targetSettingsMap.get(index); + Vector2i dimensions = packDirectives.getTextureScaleOverride(index, cachedWidth, cachedHeight); + targets[index] = RenderTarget.builder().setDimensions(dimensions.x, dimensions.y) + .setInternalFormat(settings.getInternalFormat()) + .setPixelFormat(settings.getInternalFormat().getPixelFormat()).build(); + } + public int getDepthTexture() { return currentDepthTexture; } @@ -174,7 +197,9 @@ public boolean resizeIfNeeded(int newDepthBufferVersion, int newDepthTextureId, cachedHeight = newHeight; for (int i = 0; i < targets.length; i++) { - targets[i].resize(packDirectives.getTextureScaleOverride(i, newWidth, newHeight)); + if (targets[i] != null) { + targets[i].resize(packDirectives.getTextureScaleOverride(i, newWidth, newHeight)); + } } fullClearRequired = true; @@ -253,7 +278,7 @@ private GlFramebuffer createEmptyFramebuffer() { // NB: Before OpenGL 3.0, all framebuffers are required to have a color // attachment no matter what. - framebuffer.addColorAttachment(0, get(0).getMainTexture()); + framebuffer.addColorAttachment(0, getOrCreate(0).getMainTexture()); framebuffer.noDrawBuffers(); return framebuffer; @@ -316,7 +341,7 @@ public GlFramebuffer createColorFramebuffer(ImmutableSet stageWritesToM + getRenderTargetCount() + " render targets are supported."); } - RenderTarget target = this.get(drawBuffers[i]); + RenderTarget target = this.getOrCreate(drawBuffers[i]); int textureId = stageWritesToMain.contains(drawBuffers[i]) ? target.getMainTexture() : target.getAltTexture(); @@ -347,4 +372,10 @@ public int getCurrentWidth() { public int getCurrentHeight() { return cachedHeight; } + + public void createIfUnsure(int index) { + if (targets[index] == null) { + create(index); + } + } } diff --git a/src/main/java/net/coderbot/iris/samplers/IrisImages.java b/src/main/java/net/coderbot/iris/samplers/IrisImages.java index 2eea64c0cf..d5a39e1d95 100644 --- a/src/main/java/net/coderbot/iris/samplers/IrisImages.java +++ b/src/main/java/net/coderbot/iris/samplers/IrisImages.java @@ -1,12 +1,15 @@ package net.coderbot.iris.samplers; import com.google.common.collect.ImmutableSet; +import net.coderbot.iris.gl.image.GlImage; import net.coderbot.iris.gl.image.ImageHolder; +import net.coderbot.iris.gl.program.ProgramImages; import net.coderbot.iris.gl.texture.InternalTextureFormat; import net.coderbot.iris.rendertarget.RenderTarget; import net.coderbot.iris.rendertarget.RenderTargets; import net.coderbot.iris.shadows.ShadowRenderTargets; +import java.util.Set; import java.util.function.IntSupplier; import java.util.function.Supplier; @@ -16,10 +19,16 @@ public static void addRenderTargetImages(ImageHolder images, Supplier { ImmutableSet flippedBuffers = flipped.get(); - RenderTarget target = renderTargets.get(index); + RenderTarget target = renderTargets.getOrCreate(index); if (flippedBuffers.contains(index)) { return target.getAltTexture(); @@ -28,8 +37,7 @@ public static void addRenderTargetImages(ImageHolder images, Supplier shadowRenderTargets.getColorTextureId(index); } else { - textureID = () -> flipped.contains(index) ? shadowRenderTargets.get(index).getAltTexture() : shadowRenderTargets.get(index).getMainTexture(); + textureID = () -> flipped.contains(index) ? shadowRenderTargets.getOrCreate(index).getAltTexture() : shadowRenderTargets.getOrCreate(index).getMainTexture(); } InternalTextureFormat format = shadowRenderTargets.getColorTextureFormat(index); images.addTextureImage(textureID, format, "shadowcolorimg" + i); } } + + public static void addCustomImages(ImageHolder images, Set customImages) { + customImages.forEach(image -> { + images.addTextureImage(image::getId, image.getInternalFormat(), image.getName()); + }); + } } diff --git a/src/main/java/net/coderbot/iris/samplers/IrisSamplers.java b/src/main/java/net/coderbot/iris/samplers/IrisSamplers.java index fec71ab0e0..f9f9aa55b5 100644 --- a/src/main/java/net/coderbot/iris/samplers/IrisSamplers.java +++ b/src/main/java/net/coderbot/iris/samplers/IrisSamplers.java @@ -4,10 +4,14 @@ import com.google.common.collect.ImmutableSet; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import net.coderbot.iris.gbuffer_overrides.matching.InputAvailability; -import net.coderbot.iris.gl.program.ProgramBuilder; +import net.coderbot.iris.gl.IrisRenderSystem; +import net.coderbot.iris.gl.image.GlImage; +import net.coderbot.iris.gl.sampler.GlSampler; import net.coderbot.iris.gl.sampler.SamplerHolder; +import net.coderbot.iris.gl.sampler.SamplerLimits; import net.coderbot.iris.gl.state.StateUpdateNotifiers; import net.coderbot.iris.gl.texture.TextureAccess; +import net.coderbot.iris.gl.texture.TextureType; import net.coderbot.iris.pipeline.WorldRenderingPipeline; import net.coderbot.iris.rendertarget.RenderTarget; import net.coderbot.iris.rendertarget.RenderTargets; @@ -15,7 +19,9 @@ import net.coderbot.iris.shaderpack.PackShadowDirectives; import net.coderbot.iris.shadows.ShadowRenderTargets; import net.minecraft.client.renderer.texture.AbstractTexture; +import org.lwjgl.opengl.GL33C; +import java.util.Set; import java.util.function.IntSupplier; import java.util.function.Supplier; @@ -29,11 +35,22 @@ public class IrisSamplers { // TODO: In composite programs, there shouldn't be any reserved textures. // We need a way to restore these texture bindings. public static final ImmutableSet COMPOSITE_RESERVED_TEXTURE_UNITS = ImmutableSet.of(1, 2); + private static GlSampler SHADOW_SAMPLER_NEAREST; + private static GlSampler SHADOW_SAMPLER_LINEAR; + private static GlSampler LINEAR_MIPMAP; + private static GlSampler NEAREST_MIPMAP; private IrisSamplers() { // no construction allowed } + public static void initRenderer() { + SHADOW_SAMPLER_NEAREST = new GlSampler(false, false, true, true); + SHADOW_SAMPLER_LINEAR = new GlSampler(true, false, true, true); + LINEAR_MIPMAP = new GlSampler(true, true, false, false); + NEAREST_MIPMAP = new GlSampler(false, true, false, false); + } + public static void addRenderTargetSamplers(SamplerHolder samplers, Supplier> flipped, RenderTargets renderTargets, boolean isFullscreenPass) { // colortex0,1,2,3 are only able to be sampled from fullscreen passes. @@ -43,9 +60,9 @@ public static void addRenderTargetSamplers(SamplerHolder samplers, Supplier { + IntSupplier texture = () -> { ImmutableSet flippedBuffers = flipped.get(); - RenderTarget target = renderTargets.get(index); + RenderTarget target = renderTargets.getOrCreate(index); if (flippedBuffers.contains(index)) { return target.getAltTexture(); @@ -61,14 +78,22 @@ public static void addRenderTargetSamplers(SamplerHolder samplers, Supplier shadowSamplers = ImmutableList.builder().add("shadowtex0", "shadowtex0HW", "shadowtex1", "shadowtex1HW", "shadow", "watershadow", "shadowcolor"); - for (int i = 0; i < PackShadowDirectives.MAX_SHADOW_COLOR_BUFFERS; i++) { + for (int i = 0; i < PackShadowDirectives.MAX_SHADOW_COLOR_BUFFERS_IRIS; i++) { shadowSamplers.add("shadowcolor" + i); shadowSamplers.add("shadowcolorimg" + i); } @@ -98,7 +123,7 @@ public static boolean hasShadowSamplers(SamplerHolder samplers) { return false; } - public static boolean addShadowSamplers(SamplerHolder samplers, ShadowRenderTargets shadowRenderTargets, ImmutableSet flipped) { + public static boolean addShadowSamplers(SamplerHolder samplers, ShadowRenderTargets shadowRenderTargets, ImmutableSet flipped, boolean separateHardwareSamplers) { boolean usesShadows; // TODO: figure this out from parsing the shader source code to be 100% compatible with the legacy @@ -107,34 +132,43 @@ public static boolean addShadowSamplers(SamplerHolder samplers, ShadowRenderTarg if (waterShadowEnabled) { usesShadows = true; - samplers.addDynamicSampler(shadowRenderTargets.getDepthTexture()::getTextureId, "shadowtex0", "watershadow"); - samplers.addDynamicSampler(shadowRenderTargets.getDepthTextureNoTranslucents()::getTextureId, + samplers.addDynamicSampler(TextureType.TEXTURE_2D, shadowRenderTargets.getDepthTexture()::getTextureId, separateHardwareSamplers ? null : (shadowRenderTargets.isHardwareFiltered(0) ? shadowRenderTargets.isLinearFiltered(0) ? SHADOW_SAMPLER_LINEAR : SHADOW_SAMPLER_NEAREST : null), "shadowtex0", "watershadow"); + samplers.addDynamicSampler(TextureType.TEXTURE_2D, shadowRenderTargets.getDepthTextureNoTranslucents()::getTextureId, separateHardwareSamplers ? null : (shadowRenderTargets.isHardwareFiltered(1) ? shadowRenderTargets.isLinearFiltered(1) ? SHADOW_SAMPLER_LINEAR : SHADOW_SAMPLER_NEAREST : null), "shadowtex1", "shadow"); } else { - usesShadows = samplers.addDynamicSampler(shadowRenderTargets.getDepthTexture()::getTextureId, "shadowtex0", "shadow"); - usesShadows |= samplers.addDynamicSampler(shadowRenderTargets.getDepthTextureNoTranslucents()::getTextureId, "shadowtex1"); + usesShadows = samplers.addDynamicSampler(TextureType.TEXTURE_2D, shadowRenderTargets.getDepthTexture()::getTextureId, separateHardwareSamplers ? null : (shadowRenderTargets.isHardwareFiltered(0) ? shadowRenderTargets.isLinearFiltered(0) ? SHADOW_SAMPLER_LINEAR : SHADOW_SAMPLER_NEAREST : null), "shadowtex0", "shadow"); + usesShadows |= samplers.addDynamicSampler(TextureType.TEXTURE_2D, shadowRenderTargets.getDepthTextureNoTranslucents()::getTextureId, separateHardwareSamplers ? null : (shadowRenderTargets.isHardwareFiltered(1) ? shadowRenderTargets.isLinearFiltered(1) ? SHADOW_SAMPLER_LINEAR : SHADOW_SAMPLER_NEAREST : null), "shadowtex1"); } if (flipped == null) { - samplers.addDynamicSampler(() -> shadowRenderTargets.getColorTextureId(0), "shadowcolor"); - for (int i = 0; i < PackShadowDirectives.MAX_SHADOW_COLOR_BUFFERS; i++) { + if (samplers.addDynamicSampler(() -> shadowRenderTargets.getColorTextureId(0), "shadowcolor")) { + shadowRenderTargets.createIfEmpty(0); + } + for (int i = 0; i < shadowRenderTargets.getRenderTargetCount(); i++) { int finalI = i; - samplers.addDynamicSampler(() -> shadowRenderTargets.getColorTextureId(finalI), "shadowcolor" + i); + if (samplers.addDynamicSampler(() -> shadowRenderTargets.getColorTextureId(finalI), "shadowcolor" + i)) { + shadowRenderTargets.createIfEmpty(finalI); + } } } else { - samplers.addDynamicSampler(() -> flipped.contains(0) ? shadowRenderTargets.get(0).getAltTexture() : shadowRenderTargets.get(0).getMainTexture(), "shadowcolor"); - for (int i = 0; i < PackShadowDirectives.MAX_SHADOW_COLOR_BUFFERS; i++) { + if (samplers.addDynamicSampler(() -> flipped.contains(0) ? shadowRenderTargets.get(0).getAltTexture() : shadowRenderTargets.get(0).getMainTexture(), "shadowcolor")) { + shadowRenderTargets.createIfEmpty(0); + } + + for (int i = 0; i < shadowRenderTargets.getRenderTargetCount(); i++) { int finalI = i; - samplers.addDynamicSampler(() -> flipped.contains(finalI) ? shadowRenderTargets.get(finalI).getAltTexture() : shadowRenderTargets.get(finalI).getMainTexture(), "shadowcolor" + i); + if (samplers.addDynamicSampler(() -> flipped.contains(finalI) ? shadowRenderTargets.get(finalI).getAltTexture() : shadowRenderTargets.get(finalI).getMainTexture(), "shadowcolor" + i)) { + shadowRenderTargets.createIfEmpty(finalI); + } } } - if (shadowRenderTargets.isHardwareFiltered(0)) { - samplers.addDynamicSampler(shadowRenderTargets.getDepthTexture()::getTextureId, "shadowtex0HW"); + if (shadowRenderTargets.isHardwareFiltered(0) && separateHardwareSamplers) { + samplers.addDynamicSampler(TextureType.TEXTURE_2D, shadowRenderTargets.getDepthTexture()::getTextureId, shadowRenderTargets.isLinearFiltered(0) ? SHADOW_SAMPLER_LINEAR : SHADOW_SAMPLER_NEAREST, "shadowtex0HW"); } - if (shadowRenderTargets.isHardwareFiltered(1)) { - samplers.addDynamicSampler(shadowRenderTargets.getDepthTextureNoTranslucents()::getTextureId, "shadowtex1HW"); + if (shadowRenderTargets.isHardwareFiltered(1) && separateHardwareSamplers) { + samplers.addDynamicSampler(TextureType.TEXTURE_2D, shadowRenderTargets.getDepthTextureNoTranslucents()::getTextureId, shadowRenderTargets.isLinearFiltered(1) ? SHADOW_SAMPLER_LINEAR : SHADOW_SAMPLER_NEAREST, "shadowtex1HW"); } return usesShadows; @@ -186,7 +220,15 @@ public static void addCompositeSamplers(SamplerHolder samplers, RenderTargets re public static void addCustomTextures(SamplerHolder samplers, Object2ObjectMap irisCustomTextures) { irisCustomTextures.forEach((name, texture) -> { - samplers.addDynamicSampler(texture.getType(), texture.getTextureId(), name); + samplers.addDynamicSampler(texture.getType(), texture.getTextureId(), null, name); + }); + } + + public static void addCustomImages(SamplerHolder images, Set customImages) { + customImages.forEach(image -> { + if (image.getSamplerName() != null) { + images.addDynamicSampler(image.getTarget(), image::getId, null, image.getSamplerName()); + } }); } } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ComputeSource.java b/src/main/java/net/coderbot/iris/shaderpack/ComputeSource.java index bbc43ff94e..f3766a305b 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ComputeSource.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ComputeSource.java @@ -12,11 +12,13 @@ public class ComputeSource { private final ProgramSet parent; private Vector3i workGroups; private Vector2f workGroupRelative; + private IndirectPointer indirectPointer; - public ComputeSource(String name, String source, ProgramSet parent) { + public ComputeSource(String name, String source, ProgramSet parent, ShaderProperties properties) { this.name = name; this.source = source; this.parent = parent; + this.indirectPointer = properties.getIndirectPointers().get(name); } public String getName() { @@ -51,6 +53,10 @@ public Vector3i getWorkGroups() { return workGroups; } + public IndirectPointer getIndirectPointer() { + return indirectPointer; + } + public Optional requireValid() { if (this.isValid()) { return Optional.of(this); diff --git a/src/main/java/net/coderbot/iris/shaderpack/DimensionId.java b/src/main/java/net/coderbot/iris/shaderpack/DimensionId.java index 8254ca8106..fe17145777 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/DimensionId.java +++ b/src/main/java/net/coderbot/iris/shaderpack/DimensionId.java @@ -1,7 +1,9 @@ package net.coderbot.iris.shaderpack; -public enum DimensionId { - OVERWORLD, - NETHER, - END +import net.coderbot.iris.shaderpack.materialmap.NamespacedId; + +public class DimensionId { + public static NamespacedId OVERWORLD = new NamespacedId("minecraft", "overworld"); + public static NamespacedId NETHER = new NamespacedId("minecraft", "the_nether"); + public static NamespacedId END = new NamespacedId("minecraft", "the_end"); } diff --git a/src/main/java/net/coderbot/iris/shaderpack/FilledIndirectPointer.java b/src/main/java/net/coderbot/iris/shaderpack/FilledIndirectPointer.java new file mode 100644 index 0000000000..f0e503d5c3 --- /dev/null +++ b/src/main/java/net/coderbot/iris/shaderpack/FilledIndirectPointer.java @@ -0,0 +1,11 @@ +package net.coderbot.iris.shaderpack; + +import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; + +public record FilledIndirectPointer(int buffer, long offset) { + public static FilledIndirectPointer basedOff(ShaderStorageBufferHolder holder, IndirectPointer pointer) { + if (pointer == null || holder == null) return null; + + return new FilledIndirectPointer(holder.getBufferIndex(pointer.buffer()), pointer.offset()); + } +} diff --git a/src/main/java/net/coderbot/iris/shaderpack/IdMap.java b/src/main/java/net/coderbot/iris/shaderpack/IdMap.java index 836c0aba12..f84347057f 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/IdMap.java +++ b/src/main/java/net/coderbot/iris/shaderpack/IdMap.java @@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMaps; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import net.coderbot.iris.Iris; import net.coderbot.iris.shaderpack.materialmap.BlockEntry; import net.coderbot.iris.shaderpack.materialmap.BlockRenderType; @@ -253,6 +254,29 @@ private static Map parseRenderTypeMap(Properties return overrides; } + + private static Map parseDimensionMap(Properties properties, String keyPrefix, String fileName) { + Map overrides = new Object2ObjectArrayMap<>(); + + properties.forEach((keyObject, valueObject) -> { + String key = (String) keyObject; + String value = (String) valueObject; + + if (!key.startsWith(keyPrefix)) { + // Not a valid line, ignore it + return; + } + + key = key.substring(keyPrefix.length()); + + for (String part : value.split("\\s+")) { + overrides.put(new NamespacedId(part), key); + } + }); + + return overrides; + } + public Int2ObjectMap> getBlockProperties() { return blockPropertiesMap; } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ImageInformation.java b/src/main/java/net/coderbot/iris/shaderpack/ImageInformation.java new file mode 100644 index 0000000000..8e8c2602c2 --- /dev/null +++ b/src/main/java/net/coderbot/iris/shaderpack/ImageInformation.java @@ -0,0 +1,10 @@ +package net.coderbot.iris.shaderpack; + +import net.coderbot.iris.gl.texture.InternalTextureFormat; +import net.coderbot.iris.gl.texture.PixelFormat; +import net.coderbot.iris.gl.texture.PixelType; +import net.coderbot.iris.gl.texture.TextureType; + +public record ImageInformation(String name, String samplerName, TextureType target, PixelFormat format, InternalTextureFormat internalTextureFormat, + PixelType type, int width, int height, int depth, boolean clear, boolean isRelative, float relativeWidth, float relativeHeight) { +} diff --git a/src/main/java/net/coderbot/iris/shaderpack/IndirectPointer.java b/src/main/java/net/coderbot/iris/shaderpack/IndirectPointer.java new file mode 100644 index 0000000000..827588a4de --- /dev/null +++ b/src/main/java/net/coderbot/iris/shaderpack/IndirectPointer.java @@ -0,0 +1,4 @@ +package net.coderbot.iris.shaderpack; + +public record IndirectPointer(int buffer, long offset) { +} diff --git a/src/main/java/net/coderbot/iris/shaderpack/IrisDefines.java b/src/main/java/net/coderbot/iris/shaderpack/IrisDefines.java new file mode 100644 index 0000000000..d99ead8f3d --- /dev/null +++ b/src/main/java/net/coderbot/iris/shaderpack/IrisDefines.java @@ -0,0 +1,41 @@ +package net.coderbot.iris.shaderpack; + +import com.google.common.collect.ImmutableList; +import net.coderbot.iris.Iris; +import net.coderbot.iris.gl.shader.StandardMacros; +import net.coderbot.iris.uniforms.BiomeParameters; +import net.minecraft.world.level.biome.Biome; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.regex.Pattern; + +public class IrisDefines { + private static final Pattern SEMVER_PATTERN = Pattern.compile("(?\\d+)\\.(?\\d+)\\.*(?\\d*)(.*)"); + + private static void define(List defines, String key) { + defines.add(new StringPair(key, "")); + } + + private static void define(List defines, String key, String value) { + defines.add(new StringPair(key, value)); + } + + public static ImmutableList createIrisReplacements() { + ArrayList s = new ArrayList<>(StandardMacros.createStandardEnvironmentDefines()); + define(s, "PPT_NONE", "0"); + define(s, "PPT_RAIN", "1"); + define(s, "PPT_SNOW", "2"); + define(s, "BIOME_SWAMP_HILLS", "-1"); + + BiomeParameters.getBiomeMap().forEach((biome, id) -> define(s, "BIOME_" + biome.location().getPath().toUpperCase(Locale.ROOT), String.valueOf(id))); + + Biome.BiomeCategory[] categories = Biome.BiomeCategory.values(); + for (int i = 0; i < categories.length; i++) { + define(s, "CAT_" + categories[i].getName().toUpperCase(Locale.ROOT), String.valueOf(i)); + } + + return ImmutableList.copyOf(s); + } +} diff --git a/src/main/java/net/coderbot/iris/shaderpack/PackDirectives.java b/src/main/java/net/coderbot/iris/shaderpack/PackDirectives.java index 3f7f9ea517..8543480fb2 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/PackDirectives.java +++ b/src/main/java/net/coderbot/iris/shaderpack/PackDirectives.java @@ -1,11 +1,14 @@ package net.coderbot.iris.shaderpack; import com.google.common.collect.ImmutableMap; +import it.unimi.dsi.fastutil.ints.Int2IntArrayMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.Object2BooleanMap; import it.unimi.dsi.fastutil.objects.Object2BooleanMaps; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.coderbot.iris.Iris; +import net.coderbot.iris.gl.buffer.ShaderStorageInfo; import net.coderbot.iris.gl.texture.TextureScaleOverride; import net.coderbot.iris.gl.texture.TextureType; import net.coderbot.iris.helpers.Tri; @@ -16,6 +19,7 @@ import java.util.Set; public class PackDirectives { + private boolean supportsColorCorrection; private int noiseTextureResolution; private float sunPathRotation; private float ambientOcclusionLevel; @@ -30,6 +34,9 @@ public class PackDirectives { private boolean moon; private boolean rainDepth; private boolean separateAo; + private boolean voxelizeLightBlocks; + private boolean separateEntityDraws; + private boolean frustumCulling; private boolean oldLighting; private boolean concurrentCompute; private boolean oldHandLight; @@ -37,6 +44,7 @@ public class PackDirectives { private Object2ObjectMap> explicitFlips = new Object2ObjectOpenHashMap<>(); private Object2ObjectMap scaleOverrides = new Object2ObjectOpenHashMap<>(); private Object2ObjectMap, String> textureMap; + private Int2ObjectArrayMap bufferObjects; private final PackRenderTargetDirectives renderTargetDirectives; private final PackShadowDirectives shadowDirectives; @@ -45,11 +53,13 @@ public class PackDirectives { private PackDirectives(Set supportedRenderTargets, PackShadowDirectives packShadowDirectives) { noiseTextureResolution = 256; sunPathRotation = 0.0F; + supportsColorCorrection = false; ambientOcclusionLevel = 1.0F; wetnessHalfLife = 600.0f; drynessHalfLife = 200.0f; eyeBrightnessHalfLife = 10.0f; centerDepthHalfLife = 1.0F; + bufferObjects = new Int2ObjectArrayMap<>(); renderTargetDirectives = new PackRenderTargetDirectives(supportedRenderTargets); shadowDirectives = packShadowDirectives; } @@ -63,7 +73,11 @@ private PackDirectives(Set supportedRenderTargets, PackShadowDirectives moon = properties.getMoon().orElse(true); rainDepth = properties.getRainDepth().orElse(false); separateAo = properties.getSeparateAo().orElse(false); + voxelizeLightBlocks = properties.getVoxelizeLightBlocks().orElse(false); + separateEntityDraws = properties.getSeparateEntityDraws().orElse(false); + frustumCulling = properties.getFrustumCulling().orElse(true); oldLighting = properties.getOldLighting().orElse(false); + supportsColorCorrection = properties.supportsColorCorrection().orElse(false); concurrentCompute = properties.getConcurrentCompute().orElse(false); oldHandLight = properties.getOldHandLight().orElse(true); explicitFlips = properties.getExplicitFlips(); @@ -71,12 +85,16 @@ private PackDirectives(Set supportedRenderTargets, PackShadowDirectives prepareBeforeShadow = properties.getPrepareBeforeShadow().orElse(false); particleRenderingSettings = properties.getParticleRenderingSettings(); textureMap = properties.getCustomTexturePatching(); + bufferObjects = properties.getBufferObjects(); } PackDirectives(Set supportedRenderTargets, PackDirectives directives) { this(supportedRenderTargets, new PackShadowDirectives(directives.getShadowDirectives())); cloudSetting = directives.cloudSetting; separateAo = directives.separateAo; + voxelizeLightBlocks = directives.voxelizeLightBlocks; + separateEntityDraws = directives.separateEntityDraws; + frustumCulling = directives.frustumCulling; oldLighting = directives.oldLighting; concurrentCompute = directives.concurrentCompute; explicitFlips = directives.explicitFlips; @@ -84,6 +102,7 @@ private PackDirectives(Set supportedRenderTargets, PackShadowDirectives prepareBeforeShadow = directives.prepareBeforeShadow; particleRenderingSettings = directives.particleRenderingSettings; textureMap = directives.textureMap; + bufferObjects = directives.bufferObjects; } public int getNoiseTextureResolution() { @@ -146,6 +165,18 @@ public boolean shouldUseSeparateAo() { return separateAo; } + public boolean shouldVoxelizeLightBlocks() { + return voxelizeLightBlocks; + } + + public boolean shouldUseSeparateEntityDraws() { + return separateEntityDraws; + } + + public boolean shouldUseFrustumCulling() { + return frustumCulling; + } + public boolean isOldLighting() { return oldLighting; } @@ -173,6 +204,14 @@ public PackShadowDirectives getShadowDirectives() { return shadowDirectives; } + public Int2ObjectArrayMap getBufferObjects() { + return bufferObjects; + } + + public boolean supportsColorCorrection() { + return supportsColorCorrection; + } + private static float clamp(float val, float lo, float hi) { return Math.max(lo, Math.min(hi, val)); } diff --git a/src/main/java/net/coderbot/iris/shaderpack/PackShadowDirectives.java b/src/main/java/net/coderbot/iris/shaderpack/PackShadowDirectives.java index b233209e61..e00ce55793 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/PackShadowDirectives.java +++ b/src/main/java/net/coderbot/iris/shaderpack/PackShadowDirectives.java @@ -1,17 +1,22 @@ package net.coderbot.iris.shaderpack; import com.google.common.collect.ImmutableList; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import net.coderbot.iris.Iris; import net.coderbot.iris.gl.texture.InternalTextureFormat; import net.coderbot.iris.vendored.joml.Vector4f; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; public class PackShadowDirectives { // Bump this up if you want more shadow color buffers! // This is currently set at 2 for ShadersMod / OptiFine parity but can theoretically be bumped up to 8. // TODO: Make this configurable? - public static final int MAX_SHADOW_COLOR_BUFFERS = 2; + public static final int MAX_SHADOW_COLOR_BUFFERS_IRIS = 8; + public static final int MAX_SHADOW_COLOR_BUFFERS_OF = 2; private final OptionalBoolean shadowEnabled; @@ -19,6 +24,7 @@ public class PackShadowDirectives { // Use a boxed form so we can use null to indicate that there is not an FOV specified. private Float fov; private float distance; + private float voxelDistance; private float distanceRenderMul; private float entityShadowDistanceMul; private boolean explicitRenderDistance; @@ -29,10 +35,10 @@ public class PackShadowDirectives { private final boolean shouldRenderEntities; private final boolean shouldRenderPlayer; private final boolean shouldRenderBlockEntities; - private final OptionalBoolean cullingState; + private final ShadowCullState cullingState; private final ImmutableList depthSamplingSettings; - private final ImmutableList colorSamplingSettings; + private final Int2ObjectMap colorSamplingSettings; public PackShadowDirectives(ShaderProperties properties) { // By default, the shadow map has a resolution of 1024x1024. It's recommended to increase this for better @@ -53,6 +59,7 @@ public PackShadowDirectives(ShaderProperties properties) { // shadowRenderDistanceMul to a nonzero value, since having a high shadow render distance will impact // performance quite heavily on most systems. this.distance = 160.0f; + this.voxelDistance = 0.0f; // By default, shadows are not culled based on distance from the player. However, pack authors may // enable this by setting shadowRenderDistanceMul to a nonzero value. @@ -85,17 +92,14 @@ public PackShadowDirectives(ShaderProperties properties) { ImmutableList.Builder colorSamplingSettings = ImmutableList.builder(); - for (int i = 0; i < MAX_SHADOW_COLOR_BUFFERS; i++) { - colorSamplingSettings.add(new SamplingSettings()); - } - - this.colorSamplingSettings = colorSamplingSettings.build(); + this.colorSamplingSettings = new Int2ObjectArrayMap<>(); } public PackShadowDirectives(PackShadowDirectives shadowDirectives) { this.resolution = shadowDirectives.resolution; this.fov = shadowDirectives.fov; this.distance = shadowDirectives.distance; + this.voxelDistance = shadowDirectives.voxelDistance; this.distanceRenderMul = shadowDirectives.distanceRenderMul; this.entityShadowDistanceMul = shadowDirectives.entityShadowDistanceMul; this.explicitRenderDistance = shadowDirectives.explicitRenderDistance; @@ -123,6 +127,10 @@ public float getDistance() { return distance; } + public float getVoxelDistance() { + return voxelDistance; + } + public float getDistanceRenderMul() { return distanceRenderMul; } @@ -159,7 +167,7 @@ public boolean shouldRenderBlockEntities() { return shouldRenderBlockEntities; } - public OptionalBoolean getCullingState() { + public ShadowCullState getCullingState() { return cullingState; } @@ -171,7 +179,7 @@ public ImmutableList getDepthSamplingSettings() { return depthSamplingSettings; } - public ImmutableList getColorSamplingSettings() { + public Int2ObjectMap getColorSamplingSettings() { return colorSamplingSettings; } @@ -184,6 +192,7 @@ public void acceptDirectives(DirectiveHolder directives) { directives.acceptCommentFloatDirective("SHADOWHPL", distance -> this.distance = distance); directives.acceptConstFloatDirective("shadowDistance", distance -> this.distance = distance); + directives.acceptConstFloatDirective("voxelDistance", distance -> this.voxelDistance = distance); directives.acceptConstFloatDirective("entityShadowDistanceMul", distance -> this.entityShadowDistanceMul = distance); @@ -193,7 +202,7 @@ public void acceptDirectives(DirectiveHolder directives) { }); directives.acceptConstFloatDirective("shadowIntervalSize", - intervalSize -> this.intervalSize = intervalSize); + intervalSize -> this.intervalSize = intervalSize); acceptHardwareFilteringSettings(directives, depthSamplingSettings); acceptDepthMipmapSettings(directives, depthSamplingSettings); @@ -245,21 +254,19 @@ private static void acceptDepthMipmapSettings(DirectiveHolder directives, Immuta } } - private static void acceptColorMipmapSettings(DirectiveHolder directives, ImmutableList samplers) { + private static void acceptColorMipmapSettings(DirectiveHolder directives, Int2ObjectMap samplers) { // Get the default base value for the shadow depth mipmap setting directives.acceptConstBooleanDirective("generateShadowColorMipmap", mipmap -> { - for (SamplingSettings samplerSettings : samplers) { - samplerSettings.setMipmap(mipmap); - } + samplers.forEach((i, sampler) -> sampler.setMipmap(mipmap)); }); // Find any per-sampler overrides for the shadow depth mipmap setting for (int i = 0; i < samplers.size(); i++) { String name = "shadowcolor" + i + "Mipmap"; - directives.acceptConstBooleanDirective(name, samplers.get(i)::setMipmap); + directives.acceptConstBooleanDirective(name, samplers.computeIfAbsent(i, sa -> new SamplingSettings())::setMipmap); name = "shadowColor" + i + "Mipmap"; - directives.acceptConstBooleanDirective(name, samplers.get(i)::setMipmap); + directives.acceptConstBooleanDirective(name, samplers.computeIfAbsent(i, sa -> new SamplingSettings())::setMipmap); } } @@ -279,31 +286,31 @@ private static void acceptDepthFilteringSettings(DirectiveHolder directives, Imm } } - private static void acceptColorFilteringSettings(DirectiveHolder directives, ImmutableList samplers) { + private static void acceptColorFilteringSettings(DirectiveHolder directives, Int2ObjectMap samplers) { for (int i = 0; i < samplers.size(); i++) { String name = "shadowcolor" + i + "Nearest"; - directives.acceptConstBooleanDirective(name, samplers.get(i)::setNearest); + directives.acceptConstBooleanDirective(name, samplers.computeIfAbsent(i, sa -> new SamplingSettings())::setNearest); name = "shadowColor" + i + "Nearest"; - directives.acceptConstBooleanDirective(name, samplers.get(i)::setNearest); + directives.acceptConstBooleanDirective(name, samplers.computeIfAbsent(i, sa -> new SamplingSettings())::setNearest); name = "shadowColor" + i + "MinMagNearest"; - directives.acceptConstBooleanDirective(name, samplers.get(i)::setNearest); + directives.acceptConstBooleanDirective(name, samplers.computeIfAbsent(i, sa -> new SamplingSettings())::setNearest); } } - private void acceptBufferDirectives(DirectiveHolder directives, ImmutableList settings) { - for (int i = 0; i < settings.size(); i++) { + private void acceptBufferDirectives(DirectiveHolder directives, Int2ObjectMap settings) { + for (int i = 0; i < PackShadowDirectives.MAX_SHADOW_COLOR_BUFFERS_IRIS; i++) { String bufferName = "shadowcolor" + i; int finalI = i; directives.acceptConstStringDirective(bufferName + "Format", format -> { Optional internalFormat = InternalTextureFormat.fromString(format); if (internalFormat.isPresent()) { - settings.get(finalI).setFormat(internalFormat.get()); + settings.computeIfAbsent(finalI, sa -> new SamplingSettings()).setFormat(internalFormat.get()); } else { Iris.logger.warn("Unrecognized internal texture format " + format + " specified for " + bufferName + "Format, ignoring."); } @@ -311,29 +318,29 @@ private void acceptBufferDirectives(DirectiveHolder directives, ImmutableList settings.get(finalI).setClear(shouldClear)); + shouldClear -> settings.computeIfAbsent(finalI, sa -> new SamplingSettings()).setClear(shouldClear)); // TODO: Only for composite, deferred, and final // Note: This is still relevant even if shouldClear is false, // since this will be the initial color of the buffer. directives.acceptConstVec4Directive(bufferName + "ClearColor", - clearColor -> settings.get(finalI).setClearColor(clearColor)); + clearColor -> settings.computeIfAbsent(finalI, sa -> new SamplingSettings()).setClearColor(clearColor)); } } @Override public String toString() { return "PackShadowDirectives{" + - "resolution=" + resolution + - ", fov=" + fov + - ", distance=" + distance + - ", distanceRenderMul=" + distanceRenderMul + - ", entityDistanceRenderMul=" + entityShadowDistanceMul + - ", intervalSize=" + intervalSize + - ", depthSamplingSettings=" + depthSamplingSettings + - ", colorSamplingSettings=" + colorSamplingSettings + - '}'; + "resolution=" + resolution + + ", fov=" + fov + + ", distance=" + distance + + ", distanceRenderMul=" + distanceRenderMul + + ", entityDistanceRenderMul=" + entityShadowDistanceMul + + ", intervalSize=" + intervalSize + + ", depthSamplingSettings=" + depthSamplingSettings + + ", colorSamplingSettings=" + colorSamplingSettings + + '}'; } public static class SamplingSettings { @@ -396,7 +403,7 @@ public boolean getMipmap() { } public boolean getNearest() { - return this.nearest; + return this.nearest || this.format.getPixelFormat().isInteger(); } public boolean getClear() { @@ -414,12 +421,12 @@ public InternalTextureFormat getFormat() { @Override public String toString() { return "SamplingSettings{" + - "mipmap=" + mipmap + - ", nearest=" + nearest + - ", clear=" + clear + - ", clearColor=" + clearColor + - ", format=" + format.name() + - '}'; + "mipmap=" + mipmap + + ", nearest=" + nearest + + ", clear=" + clear + + ", clearColor=" + clearColor + + ", format=" + format.name() + + '}'; } } @@ -441,10 +448,10 @@ public boolean getHardwareFiltering() { @Override public String toString() { return "DepthSamplingSettings{" + - "mipmap=" + getMipmap() + - ", nearest=" + getNearest() + - ", hardwareFiltering=" + hardwareFiltering + - '}'; + "mipmap=" + getMipmap() + + ", nearest=" + getNearest() + + ", hardwareFiltering=" + hardwareFiltering + + '}'; } } } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ProgramDirectives.java b/src/main/java/net/coderbot/iris/shaderpack/ProgramDirectives.java index fc5961f227..35bd46f851 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ProgramDirectives.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ProgramDirectives.java @@ -11,6 +11,7 @@ import net.coderbot.iris.gl.blending.BlendMode; import net.coderbot.iris.gl.blending.BlendModeOverride; import net.coderbot.iris.gl.blending.BufferBlendInformation; +import net.coderbot.iris.gl.framebuffer.ViewportData; import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -24,7 +25,7 @@ public class ProgramDirectives { private static final ImmutableList LEGACY_RENDER_TARGETS = PackRenderTargetDirectives.LEGACY_RENDER_TARGETS; private final int[] drawBuffers; - private final float viewportScale; + private final ViewportData viewportScale; @Nullable private final AlphaTest alphaTestOverride; @@ -32,8 +33,9 @@ public class ProgramDirectives { private final List bufferBlendInformations; private final ImmutableSet mipmappedBuffers; private final ImmutableMap explicitFlips; + private boolean unknownDrawBuffers; - private ProgramDirectives(int[] drawBuffers, float viewportScale, @Nullable AlphaTest alphaTestOverride, + private ProgramDirectives(int[] drawBuffers, ViewportData viewportScale, @Nullable AlphaTest alphaTestOverride, Optional blendModeOverride, List bufferBlendInformations, ImmutableSet mipmappedBuffers, ImmutableMap explicitFlips) { this.drawBuffers = drawBuffers; @@ -43,6 +45,7 @@ private ProgramDirectives(int[] drawBuffers, float viewportScale, @Nullable Alph this.bufferBlendInformations = bufferBlendInformations; this.mipmappedBuffers = mipmappedBuffers; this.explicitFlips = explicitFlips; + this.unknownDrawBuffers = false; } ProgramDirectives(ProgramSource source, ShaderProperties properties, Set supportedRenderTargets, @@ -66,10 +69,13 @@ private ProgramDirectives(int[] drawBuffers, float viewportScale, @Nullable Alph } else { throw new IllegalStateException("Unhandled comment directive type!"); } - }).orElse(new int[] { 0 }); + }).orElseGet(() -> { + unknownDrawBuffers = true; + return new int[] { 0 }; + }); if (properties != null) { - viewportScale = properties.getViewportScaleOverrides().getOrDefault(source.getName(), 1.0f); + viewportScale = properties.getViewportScaleOverrides().getOrDefault(source.getName(), ViewportData.defaultValue()); alphaTestOverride = properties.getAlphaTestOverrides().get(source.getName()); BlendModeOverride blendModeOverride = properties.getBlendModeOverrides().get(source.getName()); @@ -79,7 +85,7 @@ private ProgramDirectives(int[] drawBuffers, float viewportScale, @Nullable Alph explicitFlips = source.getParent().getPackDirectives().getExplicitFlips(source.getName()); } else { - viewportScale = 1.0f; + viewportScale = ViewportData.defaultValue(); alphaTestOverride = null; blendModeOverride = Optional.ofNullable(defaultBlendOverride); bufferBlendInformations = Collections.emptyList(); @@ -140,8 +146,8 @@ private static int[] parseDigits(char[] directiveChars) { private static int[] parseDigitList(String digitListString) { return Arrays.stream(digitListString.split(",")) - .mapToInt(Integer::parseInt) - .toArray(); + .mapToInt(Integer::parseInt) + .toArray(); } private static Optional getAppliedDirective(Optional optionalDrawbuffersDirective, Optional optionalRendertargetsDirective) { @@ -164,7 +170,11 @@ public int[] getDrawBuffers() { return drawBuffers; } - public float getViewportScale() { + public boolean hasUnknownDrawBuffers() { + return unknownDrawBuffers; + } + + public ViewportData getViewportScale() { return viewportScale; } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ProgramFallbackResolver.java b/src/main/java/net/coderbot/iris/shaderpack/ProgramFallbackResolver.java index aab07205f5..f8c20ef680 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ProgramFallbackResolver.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ProgramFallbackResolver.java @@ -20,6 +20,10 @@ public Optional resolve(ProgramId id) { return Optional.ofNullable(resolveNullable(id)); } + public boolean has(ProgramId id) { + return programs.get(id).isPresent(); + } + @Nullable public ProgramSource resolveNullable(ProgramId id) { if (cache.containsKey(id)) { diff --git a/src/main/java/net/coderbot/iris/shaderpack/ProgramSet.java b/src/main/java/net/coderbot/iris/shaderpack/ProgramSet.java index 700667da53..db86619a59 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ProgramSet.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ProgramSet.java @@ -1,6 +1,7 @@ package net.coderbot.iris.shaderpack; import net.coderbot.iris.Iris; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gl.blending.BlendMode; import net.coderbot.iris.gl.blending.BlendModeFunction; import net.coderbot.iris.gl.blending.BlendModeOverride; @@ -15,7 +16,7 @@ import java.util.Optional; import java.util.function.Function; -public class ProgramSet { +public class ProgramSet implements ProgramSetInterface { private final PackDirectives packDirectives; private final ProgramSource shadow; @@ -23,8 +24,11 @@ public class ProgramSet { private final ProgramSource[] shadowcomp; private final ComputeSource[][] shadowCompCompute; + private final ProgramSource[] begin; + private final ComputeSource[][] beginCompute; private final ProgramSource[] prepare; private final ComputeSource[][] prepareCompute; + private final ComputeSource[] setup; private final ProgramSource gbuffersBasic; private final ProgramSource gbuffersLine; @@ -32,6 +36,8 @@ public class ProgramSet { private final ProgramSource gbuffersTextured; private final ProgramSource gbuffersTexturedLit; private final ProgramSource gbuffersTerrain; + private final ProgramSource gbuffersTerrainSolid; + private final ProgramSource gbuffersTerrainCutout; private ProgramSource gbuffersDamagedBlock; private final ProgramSource gbuffersSkyBasic; private final ProgramSource gbuffersSkyTextured; @@ -39,10 +45,13 @@ public class ProgramSet { private final ProgramSource gbuffersWeather; private final ProgramSource gbuffersEntities; private final ProgramSource gbuffersEntitiesTrans; + private final ProgramSource gbuffersParticles; + private final ProgramSource gbuffersParticlesTrans; private final ProgramSource gbuffersEntitiesGlowing; private final ProgramSource gbuffersGlint; private final ProgramSource gbuffersEntityEyes; private final ProgramSource gbuffersBlock; + private final ProgramSource gbuffersBlockTrans; private final ProgramSource gbuffersHand; private final ProgramSource[] deferred; @@ -74,58 +83,73 @@ public ProgramSet(AbsolutePackPath directory, Function // // - https://github.com/IrisShaders/Iris/issues/483 // - https://github.com/IrisShaders/Iris/issues/987 + boolean readTesselation = pack.hasFeature(FeatureFlags.TESSELATION_SHADERS); + this.shadow = readProgramSource(directory, sourceProvider, "shadow", this, shaderProperties, - BlendModeOverride.OFF); - this.shadowCompute = readComputeArray(directory, sourceProvider, "shadow"); + BlendModeOverride.OFF, readTesselation); + this.shadowCompute = readComputeArray(directory, sourceProvider, "shadow", shaderProperties); - this.shadowcomp = readProgramArray(directory, sourceProvider, "shadowcomp", shaderProperties); + this.shadowcomp = readProgramArray(directory, sourceProvider, "shadowcomp", shaderProperties, readTesselation); this.shadowCompCompute = new ComputeSource[shadowcomp.length][]; for (int i = 0; i < shadowcomp.length; i++) { - this.shadowCompCompute[i] = readComputeArray(directory, sourceProvider, "shadowcomp" + ((i == 0) ? "" : i)); + this.shadowCompCompute[i] = readComputeArray(directory, sourceProvider, "shadowcomp" + ((i == 0) ? "" : i), shaderProperties); + } + + this.setup = readProgramArray(directory, sourceProvider, "setup", shaderProperties); + + this.begin = readProgramArray(directory, sourceProvider, "begin", shaderProperties, readTesselation); + this.beginCompute = new ComputeSource[begin.length][]; + for (int i = 0; i < begin.length; i++) { + this.beginCompute[i] = readComputeArray(directory, sourceProvider, "begin" + ((i == 0) ? "" : i), shaderProperties); } - this.prepare = readProgramArray(directory, sourceProvider, "prepare", shaderProperties); + this.prepare = readProgramArray(directory, sourceProvider, "prepare", shaderProperties, readTesselation); this.prepareCompute = new ComputeSource[prepare.length][]; for (int i = 0; i < prepare.length; i++) { - this.prepareCompute[i] = readComputeArray(directory, sourceProvider, "prepare" + ((i == 0) ? "" : i)); + this.prepareCompute[i] = readComputeArray(directory, sourceProvider, "prepare" + ((i == 0) ? "" : i), shaderProperties); } - this.gbuffersBasic = readProgramSource(directory, sourceProvider, "gbuffers_basic", this, shaderProperties); - this.gbuffersLine = readProgramSource(directory, sourceProvider, "gbuffers_line", this, shaderProperties); - this.gbuffersBeaconBeam = readProgramSource(directory, sourceProvider, "gbuffers_beaconbeam", this, shaderProperties); - this.gbuffersTextured = readProgramSource(directory, sourceProvider, "gbuffers_textured", this, shaderProperties); - this.gbuffersTexturedLit = readProgramSource(directory, sourceProvider, "gbuffers_textured_lit", this, shaderProperties); - this.gbuffersTerrain = readProgramSource(directory, sourceProvider, "gbuffers_terrain", this, shaderProperties); - this.gbuffersDamagedBlock = readProgramSource(directory, sourceProvider, "gbuffers_damagedblock", this, shaderProperties); - this.gbuffersSkyBasic = readProgramSource(directory, sourceProvider, "gbuffers_skybasic", this, shaderProperties); - this.gbuffersSkyTextured = readProgramSource(directory, sourceProvider, "gbuffers_skytextured", this, shaderProperties); - this.gbuffersClouds = readProgramSource(directory, sourceProvider, "gbuffers_clouds", this, shaderProperties); - this.gbuffersWeather = readProgramSource(directory, sourceProvider, "gbuffers_weather", this, shaderProperties); - this.gbuffersEntities = readProgramSource(directory, sourceProvider, "gbuffers_entities", this, shaderProperties); - this.gbuffersEntitiesTrans = readProgramSource(directory, sourceProvider, "gbuffers_entities_translucent", this, shaderProperties); - this.gbuffersEntitiesGlowing = readProgramSource(directory, sourceProvider, "gbuffers_entities_glowing", this, shaderProperties); - this.gbuffersGlint = readProgramSource(directory, sourceProvider, "gbuffers_armor_glint", this, shaderProperties); - this.gbuffersEntityEyes = readProgramSource(directory, sourceProvider, "gbuffers_spidereyes", this, shaderProperties); - this.gbuffersBlock = readProgramSource(directory, sourceProvider, "gbuffers_block", this, shaderProperties); - this.gbuffersHand = readProgramSource(directory, sourceProvider, "gbuffers_hand", this, shaderProperties); - - this.deferred = readProgramArray(directory, sourceProvider, "deferred", shaderProperties); + this.gbuffersBasic = readProgramSource(directory, sourceProvider, "gbuffers_basic", this, shaderProperties, readTesselation); + this.gbuffersLine = readProgramSource(directory, sourceProvider, "gbuffers_line", this, shaderProperties, readTesselation); + this.gbuffersBeaconBeam = readProgramSource(directory, sourceProvider, "gbuffers_beaconbeam", this, shaderProperties, readTesselation); + this.gbuffersTextured = readProgramSource(directory, sourceProvider, "gbuffers_textured", this, shaderProperties, readTesselation); + this.gbuffersTexturedLit = readProgramSource(directory, sourceProvider, "gbuffers_textured_lit", this, shaderProperties, readTesselation); + this.gbuffersTerrain = readProgramSource(directory, sourceProvider, "gbuffers_terrain", this, shaderProperties, readTesselation); + this.gbuffersTerrainSolid = readProgramSource(directory, sourceProvider, "gbuffers_terrain_solid", this, shaderProperties, readTesselation); + this.gbuffersTerrainCutout = readProgramSource(directory, sourceProvider, "gbuffers_terrain_cutout", this, shaderProperties, readTesselation); + this.gbuffersDamagedBlock = readProgramSource(directory, sourceProvider, "gbuffers_damagedblock", this, shaderProperties, readTesselation); + this.gbuffersSkyBasic = readProgramSource(directory, sourceProvider, "gbuffers_skybasic", this, shaderProperties, readTesselation); + this.gbuffersSkyTextured = readProgramSource(directory, sourceProvider, "gbuffers_skytextured", this, shaderProperties, readTesselation); + this.gbuffersClouds = readProgramSource(directory, sourceProvider, "gbuffers_clouds", this, shaderProperties, readTesselation); + this.gbuffersWeather = readProgramSource(directory, sourceProvider, "gbuffers_weather", this, shaderProperties, readTesselation); + this.gbuffersEntities = readProgramSource(directory, sourceProvider, "gbuffers_entities", this, shaderProperties, readTesselation); + this.gbuffersEntitiesTrans = readProgramSource(directory, sourceProvider, "gbuffers_entities_translucent", this, shaderProperties, readTesselation); + this.gbuffersParticles = readProgramSource(directory, sourceProvider, "gbuffers_particles", this, shaderProperties, readTesselation); + this.gbuffersParticlesTrans = readProgramSource(directory, sourceProvider, "gbuffers_particles_translucent", this, shaderProperties, readTesselation); + this.gbuffersEntitiesGlowing = readProgramSource(directory, sourceProvider, "gbuffers_entities_glowing", this, shaderProperties, readTesselation); + this.gbuffersGlint = readProgramSource(directory, sourceProvider, "gbuffers_armor_glint", this, shaderProperties, readTesselation); + this.gbuffersEntityEyes = readProgramSource(directory, sourceProvider, "gbuffers_spidereyes", this, shaderProperties, readTesselation); + this.gbuffersBlock = readProgramSource(directory, sourceProvider, "gbuffers_block", this, shaderProperties, readTesselation); + this.gbuffersBlockTrans = readProgramSource(directory, sourceProvider, "gbuffers_block_translucent", this, shaderProperties, readTesselation); + this.gbuffersHand = readProgramSource(directory, sourceProvider, "gbuffers_hand", this, shaderProperties, readTesselation); + + this.deferred = readProgramArray(directory, sourceProvider, "deferred", shaderProperties, readTesselation); this.deferredCompute = new ComputeSource[deferred.length][]; for (int i = 0; i < deferred.length; i++) { - this.deferredCompute[i] = readComputeArray(directory, sourceProvider, "deferred" + ((i == 0) ? "" : i)); + this.deferredCompute[i] = readComputeArray(directory, sourceProvider, "deferred" + ((i == 0) ? "" : i), shaderProperties); } - this.gbuffersWater = readProgramSource(directory, sourceProvider, "gbuffers_water", this, shaderProperties); - this.gbuffersHandWater = readProgramSource(directory, sourceProvider, "gbuffers_hand_water", this, shaderProperties); + this.gbuffersWater = readProgramSource(directory, sourceProvider, "gbuffers_water", this, shaderProperties, readTesselation); + this.gbuffersHandWater = readProgramSource(directory, sourceProvider, "gbuffers_hand_water", this, shaderProperties, readTesselation); - this.composite = readProgramArray(directory, sourceProvider, "composite", shaderProperties); + this.composite = readProgramArray(directory, sourceProvider, "composite", shaderProperties, readTesselation); this.compositeCompute = new ComputeSource[composite.length][]; for (int i = 0; i < deferred.length; i++) { - this.compositeCompute[i] = readComputeArray(directory, sourceProvider, "composite" + ((i == 0) ? "" : i)); + this.compositeCompute[i] = readComputeArray(directory, sourceProvider, "composite" + ((i == 0) ? "" : i), shaderProperties); } - this.compositeFinal = readProgramSource(directory, sourceProvider, "final", this, shaderProperties); - this.finalCompute = readComputeArray(directory, sourceProvider, "final"); + this.compositeFinal = readProgramSource(directory, sourceProvider, "final", this, shaderProperties, readTesselation); + this.finalCompute = readComputeArray(directory, sourceProvider, "final", shaderProperties); locateDirectives(); @@ -153,28 +177,41 @@ private static Optional first(Optional... candidates) { private ProgramSource[] readProgramArray(AbsolutePackPath directory, Function sourceProvider, String name, - ShaderProperties shaderProperties) { - ProgramSource[] programs = new ProgramSource[99]; + ShaderProperties shaderProperties, boolean readTesselation) { + ProgramSource[] programs = new ProgramSource[100]; + + for (int i = 0; i < programs.length; i++) { + String suffix = i == 0 ? "" : Integer.toString(i); + + programs[i] = readProgramSource(directory, sourceProvider, name + suffix, this, shaderProperties, readTesselation); + } + + return programs; + } + + private ComputeSource[] readProgramArray(AbsolutePackPath directory, + Function sourceProvider, String name, ShaderProperties properties) { + ComputeSource[] programs = new ComputeSource[100]; for (int i = 0; i < programs.length; i++) { String suffix = i == 0 ? "" : Integer.toString(i); - programs[i] = readProgramSource(directory, sourceProvider, name + suffix, this, shaderProperties); + programs[i] = readComputeSource(directory, sourceProvider, name + suffix, this, properties); } return programs; } private ComputeSource[] readComputeArray(AbsolutePackPath directory, - Function sourceProvider, String name) { + Function sourceProvider, String name, ShaderProperties properties) { ComputeSource[] programs = new ComputeSource[27]; - programs[0] = readComputeSource(directory, sourceProvider, name, this); + programs[0] = readComputeSource(directory, sourceProvider, name, this, properties); for (char c = 'a'; c <= 'z'; ++c) { String suffix = "_" + c; - programs[c - 96] = readComputeSource(directory, sourceProvider, name + suffix, this); + programs[c - 96] = readComputeSource(directory, sourceProvider, name + suffix, this, properties); if (programs[c - 96] == null) { break; @@ -190,15 +227,26 @@ private void locateDirectives() { programs.add(shadow); programs.addAll(Arrays.asList(shadowcomp)); + programs.addAll(Arrays.asList(begin)); programs.addAll(Arrays.asList(prepare)); programs.addAll (Arrays.asList( - gbuffersBasic, gbuffersBeaconBeam, gbuffersTextured, gbuffersTexturedLit, gbuffersTerrain, + gbuffersBasic, gbuffersBeaconBeam, gbuffersTextured, gbuffersTexturedLit, gbuffersTerrain, gbuffersTerrainSolid, gbuffersTerrainCutout, gbuffersDamagedBlock, gbuffersSkyBasic, gbuffersSkyTextured, gbuffersClouds, gbuffersWeather, - gbuffersEntities, gbuffersEntitiesTrans, gbuffersEntitiesGlowing, gbuffersGlint, gbuffersEntityEyes, gbuffersBlock, + gbuffersEntities, gbuffersEntitiesTrans, gbuffersEntitiesGlowing, gbuffersGlint, gbuffersEntityEyes, gbuffersBlock, gbuffersBlockTrans, gbuffersHand )); + for (ComputeSource computeSource : setup) { + if (computeSource != null) { + computes.add(computeSource); + } + } + + for (ComputeSource[] computeSources : beginCompute) { + computes.addAll(Arrays.asList(computeSources)); + } + for (ComputeSource[] computeSources : compositeCompute) { computes.addAll(Arrays.asList(computeSources)); } @@ -266,10 +314,18 @@ public ProgramSource[] getShadowComposite() { return shadowcomp; } + public ProgramSource[] getBegin() { + return begin; + } + public ProgramSource[] getPrepare() { return prepare; } + public ComputeSource[] getSetup() { + return setup; + } + public Optional getGbuffersBasic() { return gbuffersBasic.requireValid(); } @@ -290,6 +346,14 @@ public Optional getGbuffersTerrain() { return gbuffersTerrain.requireValid(); } + public Optional getGbuffersTerrainSolid() { + return gbuffersTerrainSolid.requireValid(); + } + + public Optional getGbuffersTerrainCutout() { + return gbuffersTerrainCutout.requireValid(); + } + public Optional getGbuffersDamagedBlock() { return gbuffersDamagedBlock.requireValid(); } @@ -318,6 +382,14 @@ public Optional getGbuffersEntitiesTrans() { return gbuffersEntitiesTrans.requireValid(); } + public Optional getGbuffersParticles() { + return gbuffersParticles.requireValid(); + } + + public Optional getGbuffersParticlesTrans() { + return gbuffersParticlesTrans.requireValid(); + } + public Optional getGbuffersEntitiesGlowing() { return gbuffersEntitiesGlowing.requireValid(); } @@ -334,6 +406,10 @@ public Optional getGbuffersBlock() { return gbuffersBlock.requireValid(); } + public Optional getGbuffersBlockTrans() { + return gbuffersBlockTrans.requireValid(); + } + public Optional getGbuffersHand() { return gbuffersHand.requireValid(); } @@ -349,11 +425,16 @@ public Optional get(ProgramId programId) { case SkyTextured: return getGbuffersSkyTextured(); case Clouds: return getGbuffersClouds(); case Terrain: return getGbuffersTerrain(); + case TerrainSolid: return getGbuffersTerrainSolid(); + case TerrainCutout: return getGbuffersTerrainCutout(); case DamagedBlock: return getGbuffersDamagedBlock(); case Block: return getGbuffersBlock(); + case BlockTrans: return getGbuffersBlockTrans(); case BeaconBeam: return getGbuffersBeaconBeam(); case Entities: return getGbuffersEntities(); case EntitiesTrans: return getGbuffersEntitiesTrans(); + case Particles: return getGbuffersParticles(); + case ParticlesTrans: return getGbuffersParticlesTrans(); case EntitiesGlowing: return getGbuffersEntitiesGlowing(); case ArmorGlint: return getGbuffersGlint(); case SpiderEyes: return getGbuffersEntityEyes(); @@ -394,6 +475,10 @@ public ComputeSource[][] getShadowCompCompute() { return shadowCompCompute; } + public ComputeSource[][] getBeginCompute() { + return beginCompute; + } + public ComputeSource[][] getPrepareCompute() { return prepareCompute; } @@ -420,30 +505,60 @@ public ShaderPack getPack() { private static ProgramSource readProgramSource(AbsolutePackPath directory, Function sourceProvider, String program, - ProgramSet programSet, ShaderProperties properties) { - return readProgramSource(directory, sourceProvider, program, programSet, properties, null); + ProgramSet programSet, ShaderProperties properties, boolean readTesselation) { + return readProgramSource(directory, sourceProvider, program, programSet, properties, null, readTesselation); } private static ProgramSource readProgramSource(AbsolutePackPath directory, Function sourceProvider, String program, ProgramSet programSet, ShaderProperties properties, - BlendModeOverride defaultBlendModeOverride) { + BlendModeOverride defaultBlendModeOverride, boolean readTesselation) { AbsolutePackPath vertexPath = directory.resolve(program + ".vsh"); String vertexSource = sourceProvider.apply(vertexPath); AbsolutePackPath geometryPath = directory.resolve(program + ".gsh"); String geometrySource = sourceProvider.apply(geometryPath); + String tessControlSource = null; + String tessEvalSource = null; + + if (readTesselation) { + AbsolutePackPath tessControlPath = directory.resolve(program + ".tcs"); + tessControlSource = sourceProvider.apply(tessControlPath); + + AbsolutePackPath tessEvalPath = directory.resolve(program + ".tes"); + tessEvalSource = sourceProvider.apply(tessEvalPath); + } + AbsolutePackPath fragmentPath = directory.resolve(program + ".fsh"); String fragmentSource = sourceProvider.apply(fragmentPath); - return new ProgramSource(program, vertexSource, geometrySource, fragmentSource, programSet, properties, + if (vertexSource == null && fragmentSource != null) { + // This is for really old packs that do not use a vertex shader. + Iris.logger.warn("Found a program (" + program + ") that has a fragment shader but no vertex shader? This is very legacy behavior and might not work right."); + vertexSource = """ + #version 120 + + varying vec4 irs_texCoords[3]; + varying vec4 irs_Color; + + void main() { + gl_Position = ftransform(); + irs_texCoords[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + irs_texCoords[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1; + irs_texCoords[2] = gl_TextureMatrix[1] * gl_MultiTexCoord2; + irs_Color = gl_Color; + } + """; + } + + return new ProgramSource(program, vertexSource, geometrySource, tessControlSource, tessEvalSource, fragmentSource, programSet, properties, defaultBlendModeOverride); } private static ComputeSource readComputeSource(AbsolutePackPath directory, Function sourceProvider, String program, - ProgramSet programSet) { + ProgramSet programSet, ShaderProperties properties) { AbsolutePackPath computePath = directory.resolve(program + ".csh"); String computeSource = sourceProvider.apply(computePath); @@ -451,6 +566,6 @@ private static ComputeSource readComputeSource(AbsolutePackPath directory, return null; } - return new ComputeSource(program, computeSource, programSet); + return new ComputeSource(program, computeSource, programSet, properties); } } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ProgramSetInterface.java b/src/main/java/net/coderbot/iris/shaderpack/ProgramSetInterface.java new file mode 100644 index 0000000000..0a83774ec5 --- /dev/null +++ b/src/main/java/net/coderbot/iris/shaderpack/ProgramSetInterface.java @@ -0,0 +1,8 @@ +package net.coderbot.iris.shaderpack; + +public interface ProgramSetInterface { + class Empty implements ProgramSetInterface { + + public static final ProgramSetInterface INSTANCE = new Empty(); + } +} diff --git a/src/main/java/net/coderbot/iris/shaderpack/ProgramSource.java b/src/main/java/net/coderbot/iris/shaderpack/ProgramSource.java index 9ef8500a73..c519567dc8 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ProgramSource.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ProgramSource.java @@ -8,25 +8,31 @@ public class ProgramSource { private final String name; private final String vertexSource; private final String geometrySource; + private final String tessControlSource; + private final String tessEvalSource; private final String fragmentSource; private final ProgramDirectives directives; private final ProgramSet parent; - private ProgramSource(String name, String vertexSource, String geometrySource, String fragmentSource, + private ProgramSource(String name, String vertexSource, String geometrySource, String tessControlSource, String tessEvalSource, String fragmentSource, ProgramDirectives directives, ProgramSet parent) { this.name = name; this.vertexSource = vertexSource; this.geometrySource = geometrySource; + this.tessControlSource = tessControlSource; + this.tessEvalSource = tessEvalSource; this.fragmentSource = fragmentSource; this.directives = directives; this.parent = parent; } - public ProgramSource(String name, String vertexSource, String geometrySource, String fragmentSource, + public ProgramSource(String name, String vertexSource, String geometrySource, String tessControlSource, String tessEvalSource, String fragmentSource, ProgramSet parent, ShaderProperties properties, BlendModeOverride defaultBlendModeOverride) { this.name = name; this.vertexSource = vertexSource; this.geometrySource = geometrySource; + this.tessControlSource = tessControlSource; + this.tessEvalSource = tessEvalSource; this.fragmentSource = fragmentSource; this.parent = parent; this.directives = new ProgramDirectives(this, properties, @@ -34,7 +40,7 @@ public ProgramSource(String name, String vertexSource, String geometrySource, St } public ProgramSource withDirectiveOverride(ProgramDirectives overrideDirectives) { - return new ProgramSource(name, vertexSource, geometrySource, fragmentSource, overrideDirectives, parent); + return new ProgramSource(name, vertexSource, geometrySource, tessControlSource, tessEvalSource, fragmentSource, overrideDirectives, parent); } public String getName() { @@ -49,6 +55,14 @@ public Optional getGeometrySource() { return Optional.ofNullable(geometrySource); } + public Optional getTessControlSource() { + return Optional.ofNullable(tessControlSource); + } + + public Optional getTessEvalSource() { + return Optional.ofNullable(tessEvalSource); + } + public Optional getFragmentSource() { return Optional.ofNullable(fragmentSource); } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ShaderPack.java b/src/main/java/net/coderbot/iris/shaderpack/ShaderPack.java index 3ada882d13..790d557de4 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ShaderPack.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ShaderPack.java @@ -5,9 +5,11 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.stream.JsonReader; +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.coderbot.iris.Iris; +import net.coderbot.iris.colorspace.ColorSpace; import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gui.FeatureMissingErrorScreen; import net.coderbot.iris.gui.screen.ShaderPackScreen; @@ -16,25 +18,31 @@ import net.coderbot.iris.shaderpack.include.IncludeGraph; import net.coderbot.iris.shaderpack.include.IncludeProcessor; import net.coderbot.iris.shaderpack.include.ShaderPackSourceNames; +import net.coderbot.iris.shaderpack.materialmap.NamespacedId; import net.coderbot.iris.shaderpack.option.ProfileSet; import net.coderbot.iris.shaderpack.option.ShaderPackOptions; import net.coderbot.iris.shaderpack.option.menu.OptionMenuContainer; import net.coderbot.iris.shaderpack.option.values.MutableOptionValues; import net.coderbot.iris.shaderpack.option.values.OptionValues; import net.coderbot.iris.shaderpack.preprocessor.JcppProcessor; +import net.coderbot.iris.shaderpack.preprocessor.PropertiesPreprocessor; import net.coderbot.iris.shaderpack.texture.CustomTextureData; import net.coderbot.iris.shaderpack.texture.TextureFilteringData; import net.coderbot.iris.shaderpack.texture.TextureStage; import net.irisshaders.iris.api.v0.IrisApi; import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TranslatableComponent; +import org.apache.commons.lang3.SystemUtils; import org.jetbrains.annotations.Nullable; import java.io.BufferedReader; import net.coderbot.iris.uniforms.custom.CustomUniforms; import java.io.IOException; import java.io.InputStreamReader; +import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.NoSuchFileException; @@ -43,10 +51,13 @@ import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Properties; +import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -55,10 +66,7 @@ public class ShaderPack { private static final Gson GSON = new Gson(); private final ProgramSet base; - @Nullable - private final ProgramSet overworld; - private final ProgramSet nether; - private final ProgramSet end; + private final Map overrides; private final IdMap idMap; private final LanguageMap languageMap; @@ -70,8 +78,14 @@ public class ShaderPack { private final ProfileSet.ProfileResult profile; private final String profileInfo; - - public ShaderPack(Path root, Iterable environmentDefines) throws IOException, IllegalStateException { + private final List irisCustomImages; + private final Set activeFeatures; + private final Function sourceProvider; + private final ShaderProperties shaderProperties; + private List dimensionIds; + private Map dimensionMap; + + public ShaderPack(Path root, ImmutableList environmentDefines) throws IOException, IllegalStateException { this(root, Collections.emptyMap(), environmentDefines); } @@ -85,25 +99,54 @@ public ShaderPack(Path root, Iterable environmentDefines) throws IOE * have completed, and there is no need to hold on to the path for that reason. * @throws IOException if there are any IO errors during shader pack loading. */ - public ShaderPack(Path root, Map changedConfigs, Iterable environmentDefines) throws IOException, IllegalStateException { + public ShaderPack(Path root, Map changedConfigs, ImmutableList environmentDefines) throws IOException, IllegalStateException { // A null path is not allowed. Objects.requireNonNull(root); - + ArrayList envDefines1 = new ArrayList<>(environmentDefines); + envDefines1.addAll(IrisDefines.createIrisReplacements()); + environmentDefines = ImmutableList.copyOf(envDefines1); ImmutableList.Builder starts = ImmutableList.builder(); ImmutableList potentialFileNames = ShaderPackSourceNames.POTENTIAL_STARTS; ShaderPackSourceNames.findPresentSources(starts, root, AbsolutePackPath.fromAbsolutePath("/"), potentialFileNames); - boolean hasWorld0 = ShaderPackSourceNames.findPresentSources(starts, root, - AbsolutePackPath.fromAbsolutePath("/world0"), potentialFileNames); + dimensionIds = new ArrayList<>(); + + final boolean[] hasDimensionIds = {false}; // Thanks Java + + // This cannot be done in IDMap, as we do not have the include graph, and subsequently the shader settings. + List dimensionIdCreator = loadProperties(root, "dimension.properties", environmentDefines).map(dimensionProperties -> { + hasDimensionIds[0] = dimensionProperties.size() > 0; + dimensionMap = parseDimensionMap(dimensionProperties, "dimension.", "dimension.properties"); + return parseDimensionIds(dimensionProperties, "dimension."); + }).orElse(new ArrayList<>()); - boolean hasNether = ShaderPackSourceNames.findPresentSources(starts, root, - AbsolutePackPath.fromAbsolutePath("/world-1"), potentialFileNames); + if (!hasDimensionIds[0]) { + dimensionMap = new Object2ObjectArrayMap<>(); + + if (Files.exists(root.resolve("world0"))) { + dimensionIdCreator.add("world0"); + dimensionMap.putIfAbsent(DimensionId.OVERWORLD, "world0"); + dimensionMap.putIfAbsent(new NamespacedId("*", "*"), "world0"); + } + if (Files.exists(root.resolve("world-1"))) { + dimensionIdCreator.add("world-1"); + dimensionMap.putIfAbsent(DimensionId.NETHER, "world-1"); + } + if (Files.exists(root.resolve("world1"))) { + dimensionIdCreator.add("world1"); + dimensionMap.putIfAbsent(DimensionId.END, "world1"); + } + } - boolean hasEnd = ShaderPackSourceNames.findPresentSources(starts, root, - AbsolutePackPath.fromAbsolutePath("/world1"), potentialFileNames); + for (String id : dimensionIdCreator) { + if (ShaderPackSourceNames.findPresentSources(starts, root, AbsolutePackPath.fromAbsolutePath("/" + id), + potentialFileNames)) { + dimensionIds.add(id); + } + } // Read all files and included files recursively IncludeGraph graph = new IncludeGraph(root, starts.build()); @@ -123,30 +166,59 @@ public ShaderPack(Path root, Map changedConfigs, Iterable finalEnvironmentDefines = environmentDefines; - ShaderProperties shaderProperties = loadProperties(root, "shaders.properties") + this.shaderProperties = loadProperties(root, "shaders.properties") .map(source -> new ShaderProperties(source, shaderPackOptions, finalEnvironmentDefines)) .orElseGet(ShaderProperties::empty); + activeFeatures = new HashSet<>(); + for (int i = 0; i < shaderProperties.getRequiredFeatureFlags().size(); i++) { + activeFeatures.add(FeatureFlags.getValue(shaderProperties.getRequiredFeatureFlags().get(i))); + } + for (int i = 0; i < shaderProperties.getOptionalFeatureFlags().size(); i++) { + activeFeatures.add(FeatureFlags.getValue(shaderProperties.getOptionalFeatureFlags().get(i))); + } + + if (!activeFeatures.contains(FeatureFlags.SSBO) && !shaderProperties.getBufferObjects().isEmpty()) { + throw new IllegalStateException("An SSBO is being used, but the feature flag for SSBO's hasn't been set! Please set either a requirement or check for the SSBO feature using \"iris.features.required/optional = ssbo\"."); + } + + if (!activeFeatures.contains(FeatureFlags.CUSTOM_IMAGES) && !shaderProperties.getIrisCustomImages().isEmpty()) { + throw new IllegalStateException("Custom images are being used, but the feature flag for custom images hasn't been set! Please set either a requirement or check for custom images' feature flag using \"iris.features.required/optional = CUSTOM_IMAGES\"."); + } + List invalidFlagList = shaderProperties.getRequiredFeatureFlags().stream().filter(FeatureFlags::isInvalid).map(FeatureFlags::getValue).collect(Collectors.toList()); List invalidFeatureFlags = invalidFlagList.stream().map(FeatureFlags::getHumanReadableName).collect(Collectors.toList()); if (!invalidFeatureFlags.isEmpty()) { if (Minecraft.getInstance().screen instanceof ShaderPackScreen) { - Minecraft.getInstance().setScreen(new FeatureMissingErrorScreen(Minecraft.getInstance().screen, new TranslatableComponent("iris.unsupported.pack"), new TranslatableComponent("iris.unsupported.pack.description", FeatureFlags.getInvalidStatus(invalidFlagList), invalidFeatureFlags.stream() - .collect(Collectors.joining(", ", ": ", "."))))); + MutableComponent component = new TranslatableComponent("iris.unsupported.pack.description", FeatureFlags.getInvalidStatus(invalidFlagList), invalidFeatureFlags.stream() + .collect(Collectors.joining(", ", ": ", "."))); + if (SystemUtils.IS_OS_MAC) { + component = component.append(new TranslatableComponent("iris.unsupported.pack.macos")); + } + Minecraft.getInstance().setScreen(new FeatureMissingErrorScreen(Minecraft.getInstance().screen, new TranslatableComponent("iris.unsupported.pack"), component)); } IrisApi.getInstance().getConfig().setShadersEnabledAndApply(false); } + List newEnvDefines = new ArrayList<>(); + environmentDefines.forEach(newEnvDefines::add); + + if (shaderProperties.supportsColorCorrection().orElse(false)) { + for (ColorSpace space : ColorSpace.values()) { + newEnvDefines.add(new StringPair("COLOR_SPACE_" + space.name(), String.valueOf(space.ordinal()))); + } + } List optionalFeatureFlags = shaderProperties.getOptionalFeatureFlags().stream().filter(flag -> !FeatureFlags.isInvalid(flag)).collect(Collectors.toList()); if (!optionalFeatureFlags.isEmpty()) { - List newEnvDefines = new ArrayList<>(); - environmentDefines.forEach(newEnvDefines::add); + optionalFeatureFlags.forEach(flag -> Iris.logger.warn("Found flag " + flag)); optionalFeatureFlags.forEach(flag -> newEnvDefines.add(new StringPair("IRIS_FEATURE_" + flag, ""))); - environmentDefines = ImmutableList.copyOf(newEnvDefines); + } + environmentDefines = ImmutableList.copyOf(newEnvDefines); + ProfileSet profiles = ProfileSet.fromTree(shaderProperties.getProfiles(), this.shaderPackOptions.getOptionSet()); this.profile = profiles.scan(this.shaderPackOptions.getOptionSet(), this.shaderPackOptions.getOptionValues()); @@ -181,7 +253,7 @@ public ShaderPack(Path root, Map changedConfigs, Iterable finalEnvironmentDefines1 = environmentDefines; - Function sourceProvider = (path) -> { + this.sourceProvider = (path) -> { String pathString = path.getPathString(); // Removes the first "/" in the path if present, and the file // extension in order to represent the path as its program name @@ -217,14 +289,9 @@ public ShaderPack(Path root, Map changedConfigs, Iterable(); this.idMap = new IdMap(root, shaderPackOptions, environmentDefines); @@ -251,6 +318,8 @@ public ShaderPack(Path root, Map changedConfigs, Iterable { @@ -262,6 +331,79 @@ public ShaderPack(Path root, Map changedConfigs, Iterable loadProperties(Path shaderPath, String name, + Iterable environmentDefines) { + String fileContents = readProperties(shaderPath, name); + if (fileContents == null) { + return Optional.empty(); + } + + String processed = PropertiesPreprocessor.preprocessSource(fileContents, environmentDefines); + + StringReader propertiesReader = new StringReader(processed); + + // Note: ordering of properties is significant + // See https://github.com/IrisShaders/Iris/issues/1327 and the relevant putIfAbsent calls in + // BlockMaterialMapping + Properties properties = new OrderBackedProperties(); + try { + properties.load(propertiesReader); + } catch (IOException e) { + Iris.logger.error("Error loading " + name + " at " + shaderPath, e); + + return Optional.empty(); + } + + return Optional.of(properties); + } + + private List parseDimensionIds(Properties dimensionProperties, String keyPrefix) { + List names = new ArrayList<>(); + + dimensionProperties.forEach((keyObject, value) -> { + String key = (String) keyObject; + if (!key.startsWith(keyPrefix)) { + // Not a valid line, ignore it + return; + } + + key = key.substring(keyPrefix.length()); + + names.add(key); + }); + + return names; + } + + private static Map parseDimensionMap(Properties properties, String keyPrefix, String fileName) { + Map overrides = new Object2ObjectArrayMap<>(); + + properties.forEach((keyObject, valueObject) -> { + String key = (String) keyObject; + String value = (String) valueObject; + + if (!key.startsWith(keyPrefix)) { + // Not a valid line, ignore it + return; + } + + key = key.substring(keyPrefix.length()); + + for (String part : value.split("\\s+")) { + if (part.equals("*")) { + overrides.put(new NamespacedId("*", "*"), key); + } + overrides.put(new NamespacedId(part), key); + } + }); + + return overrides; + } + private String getCurrentProfileName() { return profile.current.map(p -> p.name).orElse("Custom"); } @@ -387,22 +529,22 @@ private static String readProperties(Path shaderPath, String name) { } } - public ProgramSet getProgramSet(DimensionId dimension) { - ProgramSet overrides; - - switch (dimension) { - case OVERWORLD: - overrides = overworld; - break; - case NETHER: - overrides = nether; - break; - case END: - overrides = end; - break; - default: - throw new IllegalArgumentException("Unknown dimension " + dimension); - } + public ProgramSet getProgramSet(NamespacedId dimension) { + ProgramSetInterface overrides; + + overrides = this.overrides.computeIfAbsent(dimension, dim -> { + if (dimensionMap.containsKey(dimension)) { + String name = dimensionMap.get(dimension); + if (dimensionIds.contains(name)) { + return new ProgramSet(AbsolutePackPath.fromAbsolutePath("/" + name), sourceProvider, shaderProperties, this); + } else { + Iris.logger.error("Attempted to load dimension folder " + name + " for dimension " + dimension + ", but it does not exist!"); + return ProgramSetInterface.Empty.INSTANCE; + } + } else { + return ProgramSetInterface.Empty.INSTANCE; + } + }); // NB: If a dimension overrides directory is present, none of the files from the parent directory are "merged" // into the override. Rather, we act as if the overrides directory contains a completely different set of @@ -412,8 +554,8 @@ public ProgramSet getProgramSet(DimensionId dimension) { // impossible to "un-define" the composite pass. It also removes a lot of complexity related to "merging" // program sets. At the same time, this might be desired behavior by shader pack authors. It could make // sense to bring it back as a configurable option, and have a more maintainable set of code backing it. - if (overrides != null) { - return overrides; + if (overrides instanceof ProgramSet) { + return (ProgramSet) overrides; } else { return base; } @@ -427,6 +569,10 @@ public EnumMap> getCus return customTextureDataMap; } + public List getIrisCustomImages() { + return irisCustomImages; + } + public Object2ObjectMap getIrisCustomTextureDataMap() { return irisCustomTextureDataMap; } @@ -446,4 +592,8 @@ public ShaderPackOptions getShaderPackOptions() { public OptionMenuContainer getMenuContainer() { return menuContainer; } + + public boolean hasFeature(FeatureFlags feature) { + return activeFeatures.contains(feature); + } } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ShaderProperties.java b/src/main/java/net/coderbot/iris/shaderpack/ShaderProperties.java index 39a2394212..7298588d84 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ShaderProperties.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ShaderProperties.java @@ -1,6 +1,8 @@ package net.coderbot.iris.shaderpack; import it.unimi.dsi.fastutil.booleans.BooleanConsumer; +import it.unimi.dsi.fastutil.ints.Int2IntArrayMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.Object2BooleanMap; import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2FloatMap; @@ -14,6 +16,8 @@ import net.coderbot.iris.gl.blending.BlendMode; import net.coderbot.iris.gl.blending.BlendModeFunction; import net.coderbot.iris.gl.blending.BlendModeOverride; +import net.coderbot.iris.gl.buffer.ShaderStorageInfo; +import net.coderbot.iris.gl.framebuffer.ViewportData; import net.coderbot.iris.gl.texture.InternalTextureFormat; import net.coderbot.iris.gl.texture.PixelFormat; import net.coderbot.iris.gl.texture.PixelType; @@ -26,9 +30,11 @@ import net.coderbot.iris.shaderpack.preprocessor.PropertiesPreprocessor; import net.coderbot.iris.shaderpack.texture.TextureStage; import net.coderbot.iris.uniforms.custom.CustomUniforms; +import net.minecraftforge.fml.loading.FMLPaths; import java.io.IOException; import java.io.StringReader; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumMap; @@ -52,6 +58,7 @@ public class ShaderProperties { private CloudSetting cloudSetting = CloudSetting.DEFAULT; private OptionalBoolean oldHandLight = OptionalBoolean.DEFAULT; private OptionalBoolean dynamicHandLight = OptionalBoolean.DEFAULT; + private OptionalBoolean supportsColorCorrection = OptionalBoolean.DEFAULT; private OptionalBoolean oldLighting = OptionalBoolean.DEFAULT; private OptionalBoolean shadowTerrain = OptionalBoolean.DEFAULT; private OptionalBoolean shadowTranslucent = OptionalBoolean.DEFAULT; @@ -70,8 +77,10 @@ public class ShaderProperties { private OptionalBoolean concurrentCompute = OptionalBoolean.DEFAULT; private OptionalBoolean beaconBeamDepth = OptionalBoolean.DEFAULT; private OptionalBoolean separateAo = OptionalBoolean.DEFAULT; + private OptionalBoolean voxelizeLightBlocks = OptionalBoolean.DEFAULT; + private OptionalBoolean separateEntityDraws = OptionalBoolean.DEFAULT; private OptionalBoolean frustumCulling = OptionalBoolean.DEFAULT; - private OptionalBoolean shadowCulling = OptionalBoolean.DEFAULT; + private ShadowCullState shadowCulling = ShadowCullState.DEFAULT; private OptionalBoolean shadowEnabled = OptionalBoolean.DEFAULT; private Optional particleRenderingSettings = Optional.empty(); private OptionalBoolean prepareBeforeShadow = OptionalBoolean.DEFAULT; @@ -84,13 +93,16 @@ public class ShaderProperties { // TODO: private Map optifineVersionRequirements; // TODO: Parse custom uniforms / variables private final Object2ObjectMap alphaTestOverrides = new Object2ObjectOpenHashMap<>(); - private final Object2FloatMap viewportScaleOverrides = new Object2FloatOpenHashMap<>(); + private final Object2ObjectMap viewportScaleOverrides = new Object2ObjectOpenHashMap<>(); private final Object2ObjectMap textureScaleOverrides = new Object2ObjectOpenHashMap<>(); private final Object2ObjectMap blendModeOverrides = new Object2ObjectOpenHashMap<>(); + private final Object2ObjectMap indirectPointers = new Object2ObjectOpenHashMap<>(); private final Object2ObjectMap> bufferBlendOverrides = new Object2ObjectOpenHashMap<>(); private final EnumMap> customTextures = new EnumMap<>(TextureStage.class); private final Object2ObjectMap, String> customTexturePatching = new Object2ObjectOpenHashMap<>(); private final Object2ObjectMap irisCustomTextures = new Object2ObjectOpenHashMap<>(); + private final List irisCustomImages = new ArrayList<>(); + private final Int2ObjectArrayMap bufferObjects = new Int2ObjectArrayMap<>(); private final Object2ObjectMap> explicitFlips = new Object2ObjectOpenHashMap<>(); private String noiseTexturePath = null; CustomUniforms.Builder customUniforms = new CustomUniforms.Builder(); @@ -106,6 +118,15 @@ private ShaderProperties() { public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, Iterable environmentDefines) { String preprocessedContents = PropertiesPreprocessor.preprocessSource(contents, shaderPackOptions, environmentDefines); + if (Iris.getIrisConfig().areDebugOptionsEnabled()) { + try { + Files.writeString(FMLPaths.GAMEDIR.get().resolve("preprocessed.properties"), preprocessedContents); + Files.writeString(FMLPaths.GAMEDIR.get().resolve("original.properties"), contents); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + Properties preprocessed = new OrderBackedProperties(); Properties original = new OrderBackedProperties(); try { @@ -136,6 +157,18 @@ public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, It } } + if ("shadow.culling".equals(key)) { + if ("false".equals(value)) { + shadowCulling = ShadowCullState.DISTANCE; + } else if ("true".equals(value)) { + shadowCulling = ShadowCullState.ADVANCED; + } else if ("reversed".equals(value)) { + shadowCulling = ShadowCullState.REVERSED; + } else { + Iris.logger.error("Unrecognized shadow culling setting: " + value); + } + } + handleBooleanDirective(key, value, "oldHandLight", bool -> oldHandLight = bool); handleBooleanDirective(key, value, "dynamicHandLight", bool -> dynamicHandLight = bool); handleBooleanDirective(key, value, "oldLighting", bool -> oldLighting = bool); @@ -156,8 +189,9 @@ public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, It handleBooleanDirective(key, value, "allowConcurrentCompute", bool -> concurrentCompute = bool); handleBooleanDirective(key, value, "beacon.beam.depth", bool -> beaconBeamDepth = bool); handleBooleanDirective(key, value, "separateAo", bool -> separateAo = bool); + handleBooleanDirective(key, value, "voxelizeLightBlocks", bool -> voxelizeLightBlocks = bool); + handleBooleanDirective(key, value, "separateEntityDraws", bool -> separateEntityDraws = bool); handleBooleanDirective(key, value, "frustum.culling", bool -> frustumCulling = bool); - handleBooleanDirective(key, value, "shadow.culling", bool -> shadowCulling = bool); handleBooleanDirective(key, value, "shadow.enabled", bool -> shadowEnabled = bool); handleBooleanDirective(key, value, "particles.before.deferred", bool -> { if (bool.orElse(false) && particleRenderingSettings.isEmpty()) { @@ -165,6 +199,7 @@ public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, It } }); handleBooleanDirective(key, value, "prepareBeforeShadow", bool -> prepareBeforeShadow = bool); + handleBooleanDirective(key, value, "supportsColorCorrection", bool -> supportsColorCorrection = bool); if (key.startsWith("particles.ordering")) { Optional settings = ParticleRenderingSettings.fromString(value.trim().toUpperCase(Locale.US)); @@ -179,16 +214,22 @@ public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, It // TODO: Custom uniforms handlePassDirective("scale.", key, value, pass -> { - float scale; + float scale, offsetX = 0.0f, offsetY = 0.0f; + String[] parts = value.split(" "); try { - scale = Float.parseFloat(value); - } catch (NumberFormatException e) { + scale = Float.parseFloat(parts[0]); + + if (parts.length > 1) { + offsetX = Float.parseFloat(parts[1]); + offsetY = Float.parseFloat(parts[2]); + } + } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { Iris.logger.error("Unable to parse scale directive for " + pass + ": " + value, e); return; } - viewportScaleOverrides.put(pass, scale); + viewportScaleOverrides.put(pass, new ViewportData(scale, offsetX, offsetY)); }); handlePassDirective("size.buffer.", key, value, pass -> { @@ -296,10 +337,63 @@ public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, It blendModeOverrides.put(pass, new BlendModeOverride(new BlendMode(modes[0], modes[1], modes[2], modes[3]))); }); + handlePassDirective("indirect.", key, value, pass -> { + try { + String[] locations = value.split(" "); + + indirectPointers.put(pass, new IndirectPointer(Integer.parseInt(locations[0]), Long.parseLong(locations[1]))); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { + Iris.logger.fatal("Failed to parse indirect command for " + pass + "! " + value); + } + }); + handleProgramEnabledDirective("program.", key, value, program -> { conditionallyEnabledPrograms.put(program, value); }); + handlePassDirective("bufferObject.", key, value, index -> { + int trueIndex; + int trueSize; + boolean isRelative; + float scaleX, scaleY; + String[] parts = value.split(" "); + if (parts.length == 1) { + try { + trueIndex = Integer.parseInt(index); + trueSize = Integer.parseInt(value); + } catch (NumberFormatException e) { + Iris.logger.error("Number format exception parsing SSBO index/size!", e); + return; + } + + if (trueIndex > 8) { + Iris.logger.fatal("SSBO's cannot use buffer numbers higher than 8, they're reserved!"); + return; + } + + bufferObjects.put(trueIndex, new ShaderStorageInfo(trueSize, false, 0, 0)); + } else { + // Assume it's a long one + try { + trueIndex = Integer.parseInt(index); + trueSize = Integer.parseInt(parts[0]); + isRelative = Boolean.parseBoolean(parts[1]); + scaleX = Float.parseFloat(parts[2]); + scaleY = Float.parseFloat(parts[3]); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { + Iris.logger.error("Number format exception parsing SSBO index/size, or not correct format!", e); + return; + } + + if (trueIndex > 8) { + Iris.logger.fatal("SSBO's cannot use buffer numbers higher than 8, they're reserved!"); + return; + } + + bufferObjects.put(trueIndex, new ShaderStorageInfo(trueSize, isRelative, scaleX, scaleY)); + } + }); + handleTwoArgDirective("texture.", key, value, (stageName, samplerName) -> { String[] parts = value.split(" "); // TODO: Is there a better way to achieve this? @@ -369,6 +463,65 @@ public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, It irisCustomTextures.put(samplerName, new TextureDefinition.PNGDefinition(value)); }); + handlePassDirective("image.", key, value, (imageName) -> { + String[] parts = value.split(" "); + String key2 = key.substring(6); + + if (irisCustomImages.size() > 15) { + Iris.logger.error("Only up to 16 images are allowed, but tried to add another image! " + key); + return; + } + + ImageInformation image; + + String samplerName = parts[0]; + if (samplerName.equals("none")) { + samplerName = null; + } + PixelFormat format = PixelFormat.fromString(parts[1]).orElse(null); + InternalTextureFormat internalFormat = InternalTextureFormat.fromString(parts[2]).orElse(null); + PixelType pixelType = PixelType.fromString(parts[3]).orElse(null); + + if (format == null || internalFormat == null || pixelType == null) { + Iris.logger.error("Image " + key2 + " is invalid! Format: " + format + " Internal format: " + internalFormat + " Pixel type: " + pixelType); + } + + boolean clear = Boolean.parseBoolean(parts[4]); + + boolean relative = Boolean.parseBoolean(parts[5]); + + if (relative) { // Is relative? + float relativeWidth = Float.parseFloat(parts[6]); + float relativeHeight = Float.parseFloat(parts[7]); + image = new ImageInformation(key2, samplerName, TextureType.TEXTURE_2D, format, internalFormat, pixelType, 0, 0, 0, clear, true, relativeWidth, relativeHeight); + } else { + TextureType type; + int width, height, depth; + if (parts.length == 7) { + type = TextureType.TEXTURE_1D; + width = Integer.parseInt(parts[6]); + height = 0; + depth = 0; + } else if (parts.length == 8) { + type = TextureType.TEXTURE_2D; + width = Integer.parseInt(parts[6]); + height = Integer.parseInt(parts[7]); + depth = 0; + } else if (parts.length == 9) { + type = TextureType.TEXTURE_3D; + width = Integer.parseInt(parts[6]); + height = Integer.parseInt(parts[7]); + depth = Integer.parseInt(parts[8]); + } else { + Iris.logger.error("Unknown image type! " + key2 + " = " + value); + return; + } + image = new ImageInformation(key2, samplerName, type, format, internalFormat, pixelType, width, height, depth, clear, false, 0, 0); + } + + irisCustomImages.add(image); + }); + handleTwoArgDirective("flip.", key, value, (pass, buffer) -> { handleBooleanValue(key, value, shouldFlip -> { explicitFlips.computeIfAbsent(pass, _pass -> new Object2BooleanOpenHashMap<>()) @@ -396,10 +549,6 @@ public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, It customUniforms.addVariable(parts[0], parts[1], value, true); }); - - handleWhitespacedListDirective(key, value, "iris.features.required", options -> requiredFeatureFlags = options); - handleWhitespacedListDirective(key, value, "iris.features.optional", options -> optionalFeatureFlags = options); - // TODO: Buffer size directives // TODO: Conditional program enabling directives }); @@ -409,6 +558,9 @@ public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, It String key = (String) keyObject; String value = (String) valueObject; + handleWhitespacedListDirective(key, value, "iris.features.required", options -> requiredFeatureFlags = options); + handleWhitespacedListDirective(key, value, "iris.features.optional", options -> optionalFeatureFlags = options); + // Defining "sliders" multiple times in the properties file will only result in // the last definition being used, should be tested if behavior matches OptiFine handleWhitespacedListDirective(key, value, "sliders", sliders -> sliderOptions = sliders); @@ -621,11 +773,19 @@ public OptionalBoolean getSeparateAo() { return separateAo; } + public OptionalBoolean getVoxelizeLightBlocks() { + return voxelizeLightBlocks; + } + + public OptionalBoolean getSeparateEntityDraws() { + return separateEntityDraws; + } + public OptionalBoolean getFrustumCulling() { return frustumCulling; } - public OptionalBoolean getShadowCulling() { + public ShadowCullState getShadowCulling() { return shadowCulling; } @@ -638,6 +798,8 @@ public OptionalBoolean getShadowEnabled() { } public Optional getParticleRenderingSettings() { + // Before is implied if separateEntityDraws is true. + if (separateEntityDraws == OptionalBoolean.TRUE) return Optional.of(ParticleRenderingSettings.MIXED); return particleRenderingSettings; } @@ -649,7 +811,7 @@ public OptionalBoolean getPrepareBeforeShadow() { return prepareBeforeShadow; } - public Object2FloatMap getViewportScaleOverrides() { + public Object2ObjectMap getViewportScaleOverrides() { return viewportScaleOverrides; } @@ -661,10 +823,18 @@ public Object2ObjectMap getBlendModeOverrides() { return blendModeOverrides; } + public Object2ObjectMap getIndirectPointers() { + return indirectPointers; + } + public Object2ObjectMap> getBufferBlendOverrides() { return bufferBlendOverrides; } + public Int2ObjectArrayMap getBufferObjects() { + return bufferObjects; + } + public EnumMap> getCustomTextures() { return customTextures; } @@ -678,6 +848,10 @@ public Object2ObjectMap getIrisCustomTextures() { return irisCustomTextures; } + public List getIrisCustomImages() { + return irisCustomImages; + } + public Optional getNoiseTexturePath() { return Optional.ofNullable(noiseTexturePath); } @@ -721,4 +895,8 @@ public List getRequiredFeatureFlags() { public List getOptionalFeatureFlags() { return optionalFeatureFlags; } + + public OptionalBoolean supportsColorCorrection() { + return supportsColorCorrection; + } } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ShadowCullState.java b/src/main/java/net/coderbot/iris/shaderpack/ShadowCullState.java new file mode 100644 index 0000000000..d407e1c628 --- /dev/null +++ b/src/main/java/net/coderbot/iris/shaderpack/ShadowCullState.java @@ -0,0 +1,8 @@ +package net.coderbot.iris.shaderpack; + +public enum ShadowCullState { + DEFAULT, + ADVANCED, + REVERSED, + DISTANCE +} diff --git a/src/main/java/net/coderbot/iris/shaderpack/include/ShaderPackSourceNames.java b/src/main/java/net/coderbot/iris/shaderpack/include/ShaderPackSourceNames.java index 7709618e0e..31556ab7c9 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/include/ShaderPackSourceNames.java +++ b/src/main/java/net/coderbot/iris/shaderpack/include/ShaderPackSourceNames.java @@ -74,6 +74,8 @@ private static ImmutableList findPotentialStarts() { private static void addStarts(ImmutableList.Builder potentialFileNames, String baseName) { potentialFileNames.add(baseName + ".vsh"); + potentialFileNames.add(baseName + ".tcs"); + potentialFileNames.add(baseName + ".tes"); potentialFileNames.add(baseName + ".gsh"); potentialFileNames.add(baseName + ".fsh"); } diff --git a/src/main/java/net/coderbot/iris/shaderpack/loading/ProgramArrayId.java b/src/main/java/net/coderbot/iris/shaderpack/loading/ProgramArrayId.java index 1a1d0a9410..975faa3410 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/loading/ProgramArrayId.java +++ b/src/main/java/net/coderbot/iris/shaderpack/loading/ProgramArrayId.java @@ -1,10 +1,12 @@ package net.coderbot.iris.shaderpack.loading; public enum ProgramArrayId { - ShadowComposite(ProgramGroup.ShadowComposite, 99), - Prepare(ProgramGroup.Prepare, 99), - Deferred(ProgramGroup.Deferred, 99), - Composite(ProgramGroup.Composite, 99), + Setup(ProgramGroup.Setup, 100), + Begin(ProgramGroup.Begin, 100), + ShadowComposite(ProgramGroup.ShadowComposite, 100), + Prepare(ProgramGroup.Prepare, 100), + Deferred(ProgramGroup.Deferred, 100), + Composite(ProgramGroup.Composite, 100), ; private final ProgramGroup group; diff --git a/src/main/java/net/coderbot/iris/shaderpack/loading/ProgramGroup.java b/src/main/java/net/coderbot/iris/shaderpack/loading/ProgramGroup.java index 468a7cd81a..275f7db650 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/loading/ProgramGroup.java +++ b/src/main/java/net/coderbot/iris/shaderpack/loading/ProgramGroup.java @@ -1,6 +1,8 @@ package net.coderbot.iris.shaderpack.loading; public enum ProgramGroup { + Setup("setup"), + Begin("begin"), Shadow("shadow"), ShadowComposite("shadowcomp"), Prepare("prepare"), diff --git a/src/main/java/net/coderbot/iris/shaderpack/loading/ProgramId.java b/src/main/java/net/coderbot/iris/shaderpack/loading/ProgramId.java index 1ae3ced098..7df6633f96 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/loading/ProgramId.java +++ b/src/main/java/net/coderbot/iris/shaderpack/loading/ProgramId.java @@ -23,20 +23,22 @@ public enum ProgramId { Terrain(ProgramGroup.Gbuffers, "terrain", TexturedLit), TerrainSolid(ProgramGroup.Gbuffers, "terrain_solid", Terrain), - TerrainCutoutMip(ProgramGroup.Gbuffers, "terrain_cutout_mip", Terrain), TerrainCutout(ProgramGroup.Gbuffers, "terrain_cutout", Terrain), DamagedBlock(ProgramGroup.Gbuffers, "damagedblock", Terrain), Block(ProgramGroup.Gbuffers, "block", Terrain), + BlockTrans(ProgramGroup.Gbuffers, "block_translucent", Block), BeaconBeam(ProgramGroup.Gbuffers, "beaconbeam", Textured), Item(ProgramGroup.Gbuffers, "item", TexturedLit), Entities(ProgramGroup.Gbuffers, "entities", TexturedLit), EntitiesTrans(ProgramGroup.Gbuffers, "entities_translucent", Entities), + Particles(ProgramGroup.Gbuffers, "particles", TexturedLit), + ParticlesTrans(ProgramGroup.Gbuffers, "particles_translucent", Particles), EntitiesGlowing(ProgramGroup.Gbuffers, "entities_glowing", Entities), ArmorGlint(ProgramGroup.Gbuffers, "armor_glint", Textured), SpiderEyes(ProgramGroup.Gbuffers, "spidereyes", Textured, - new BlendModeOverride(new BlendMode(BlendModeFunction.SRC_ALPHA.getGlId(), BlendModeFunction.ONE.getGlId(), BlendModeFunction.ZERO.getGlId(), BlendModeFunction.ONE.getGlId()))), + new BlendModeOverride(new BlendMode(BlendModeFunction.SRC_ALPHA.getGlId(), BlendModeFunction.ONE.getGlId(), BlendModeFunction.ZERO.getGlId(), BlendModeFunction.ONE.getGlId()))), Hand(ProgramGroup.Gbuffers, "hand", TexturedLit), Weather(ProgramGroup.Gbuffers, "weather", TexturedLit), diff --git a/src/main/java/net/coderbot/iris/shaderpack/materialmap/NamespacedId.java b/src/main/java/net/coderbot/iris/shaderpack/materialmap/NamespacedId.java index 30540d2aff..6a4cb3ce13 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/materialmap/NamespacedId.java +++ b/src/main/java/net/coderbot/iris/shaderpack/materialmap/NamespacedId.java @@ -48,7 +48,11 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(namespace, name); + final int prime = 31; + int result = 1; + result = prime * result + ((namespace == null) ? 0 : namespace.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; } @Override diff --git a/src/main/java/net/coderbot/iris/shaderpack/option/OptionAnnotatedSource.java b/src/main/java/net/coderbot/iris/shaderpack/option/OptionAnnotatedSource.java index cc6e586f74..6cbabde62e 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/option/OptionAnnotatedSource.java +++ b/src/main/java/net/coderbot/iris/shaderpack/option/OptionAnnotatedSource.java @@ -95,6 +95,7 @@ public final class OptionAnnotatedSource { ImmutableSet.Builder values = ImmutableSet.builder().add( "shadowMapResolution", "shadowDistance", + "voxelDistance", "shadowDistanceRenderMul", "entityShadowDistanceMul", "shadowIntervalSize", @@ -119,7 +120,7 @@ public final class OptionAnnotatedSource { "noiseTextureResolution" ); - for (int i = 0; i < PackShadowDirectives.MAX_SHADOW_COLOR_BUFFERS; i++) { + for (int i = 0; i < PackShadowDirectives.MAX_SHADOW_COLOR_BUFFERS_IRIS; i++) { values.add("shadowcolor" + i + "Mipmap"); values.add("shadowColor" + i + "Mipmap"); values.add("shadowcolor" + i + "Nearest"); diff --git a/src/main/java/net/coderbot/iris/shaderpack/parsing/ParsedString.java b/src/main/java/net/coderbot/iris/shaderpack/parsing/ParsedString.java index 7e96a0cefc..abe7a3ad16 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/parsing/ParsedString.java +++ b/src/main/java/net/coderbot/iris/shaderpack/parsing/ParsedString.java @@ -98,50 +98,23 @@ public String takeNumber() { } int position = 0; - int digitsBefore = 0; - if (text.charAt(0) == '-') { - position += 1; - } + while (position < text.length()) { + if(position + 1 < text.length()) { + if(!Character.isDigit(text.charAt(position)) && !Character.isDigit(text.charAt(position + 1))) { + break; + } + } - while (position < text.length() && Character.isDigit(text.charAt(position))) { - position += 1; - digitsBefore += 1; + position++; } - if (digitsBefore == 0) { + try { + Float.parseFloat(text.substring(0, position)); + } catch (Exception e) { return null; } - if (position < text.length()) { - char next = text.charAt(position); - - if (next == '.') { - position += 1; - - int digitsAfter = 0; - - while (position < text.length() && Character.isDigit(text.charAt(position))) { - position += 1; - digitsAfter += 1; - } - - if (digitsAfter == 0) { - return null; - } - - if (position < text.length()) { - next = text.charAt(position); - - if (next == 'f' || next == 'F') { - position += 1; - } - } - } else if (next == 'f' || next == 'F') { - position += 1; - } - } - return takeCharacters(position); } diff --git a/src/main/java/net/coderbot/iris/shaderpack/preprocessor/PropertiesPreprocessor.java b/src/main/java/net/coderbot/iris/shaderpack/preprocessor/PropertiesPreprocessor.java index 7bb2bd9846..414e877203 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/preprocessor/PropertiesPreprocessor.java +++ b/src/main/java/net/coderbot/iris/shaderpack/preprocessor/PropertiesPreprocessor.java @@ -6,6 +6,7 @@ import org.anarres.cpp.Feature; import org.anarres.cpp.LexerException; import org.anarres.cpp.Preprocessor; +import org.anarres.cpp.PreprocessorCommand; import org.anarres.cpp.StringLexerSource; import org.anarres.cpp.Token; @@ -14,6 +15,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.stream.Collectors; @@ -78,19 +80,21 @@ private static String process(Preprocessor preprocessor, String source) { // Not super efficient, but this removes trailing whitespace on lines, fixing an issue with whitespace after // line continuations (see PreprocessorTest#testWeirdPropertiesLineContinuation) // Required for Voyager Shader - source = Arrays.stream(source.split("\\R")).map(String::trim) - .map(line -> { - if (line.startsWith("#")) { + source = Arrays.stream(source.split("\\R")).map(String::trim) + .map(line -> { + if (line.startsWith("#")) { + for (PreprocessorCommand command : PreprocessorCommand.values()) { + if (line.startsWith("#" + (command.name().replace("PP_", "").toLowerCase(Locale.ROOT)))) { + return line; + } + } + return ""; + } // In PropertyCollectingListener we suppress "unknown preprocessor directive errors" and // assume the line to be a comment, since in .properties files `#` also functions as a comment // marker. - return line; - } else { - // This is a hack to ensure that non-macro lines don't have any preprocessing applied... - // In properties files, we don't substitute #define values except on macro lines. - return "#warning IRIS_PASSTHROUGH " + line; - } - }).collect(Collectors.joining("\n")) + "\n"; + return line.replace("#", ""); + }).collect(Collectors.joining("\n")) + "\n"; // TODO: This is a horrible fix to trick the preprocessor into not seeing the backslashes during processing. We need a better way to do this. source = source.replace("\\", "IRIS_PASSTHROUGHBACKSLASH"); diff --git a/src/main/java/net/coderbot/iris/shaderpack/texture/TextureStage.java b/src/main/java/net/coderbot/iris/shaderpack/texture/TextureStage.java index 687f7e1785..34dd868ca6 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/texture/TextureStage.java +++ b/src/main/java/net/coderbot/iris/shaderpack/texture/TextureStage.java @@ -3,6 +3,18 @@ import java.util.Optional; public enum TextureStage { + /** + * The setup passes. + * + * Exclusive to Iris 1.6. + */ + SETUP, + /** + * The begin pass. + * + * Exclusive to Iris 1.6. + */ + BEGIN, /** * The shadowcomp passes. * @@ -30,6 +42,10 @@ public enum TextureStage { public static Optional parse(String name) { switch (name) { + case "setup": + return Optional.of(SETUP); + case "begin": + return Optional.of(BEGIN); case "shadowcomp": return Optional.of(SHADOWCOMP); case "prepare": diff --git a/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java b/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java index 97f679b14c..8f2124ce2a 100644 --- a/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java +++ b/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java @@ -6,6 +6,11 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.Iris; +import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; +import net.coderbot.iris.gl.framebuffer.ViewportData; +import net.coderbot.iris.gl.image.GlImage; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gl.IrisRenderSystem; import net.coderbot.iris.gl.framebuffer.GlFramebuffer; import net.coderbot.iris.gl.program.ComputeProgram; @@ -14,7 +19,7 @@ import net.coderbot.iris.gl.program.ProgramSamplers; import net.coderbot.iris.gl.program.ProgramUniforms; import net.coderbot.iris.gl.texture.TextureAccess; -import net.coderbot.iris.pipeline.PatchedShaderPrinter; +import net.coderbot.iris.pipeline.ShaderPrinter; import net.coderbot.iris.pipeline.WorldRenderingPipeline; import net.coderbot.iris.pipeline.newshader.FogMode; import net.coderbot.iris.pipeline.transform.PatchShaderType; @@ -24,6 +29,7 @@ import net.coderbot.iris.samplers.IrisImages; import net.coderbot.iris.samplers.IrisSamplers; import net.coderbot.iris.shaderpack.ComputeSource; +import net.coderbot.iris.shaderpack.FilledIndirectPointer; import net.coderbot.iris.shaderpack.PackDirectives; import net.coderbot.iris.shaderpack.PackRenderTargetDirectives; import net.coderbot.iris.shaderpack.ProgramDirectives; @@ -36,9 +42,12 @@ import org.lwjgl.opengl.GL15C; import org.lwjgl.opengl.GL20C; import org.lwjgl.opengl.GL30C; +import org.lwjgl.opengl.GL43C; +import java.util.Arrays; import java.util.Map; import java.util.Objects; +import java.util.Set; public class ShadowCompositeRenderer { private final ShadowRenderTargets renderTargets; @@ -51,16 +60,18 @@ public class ShadowCompositeRenderer { private final CustomUniforms customUniforms; private final Object2ObjectMap irisCustomTextures; private final WorldRenderingPipeline pipeline; + private final Set irisCustomImages; - public ShadowCompositeRenderer(WorldRenderingPipeline pipeline, PackDirectives packDirectives, ProgramSource[] sources, ComputeSource[][] computes, ShadowRenderTargets renderTargets, + public ShadowCompositeRenderer(WorldRenderingPipeline pipeline, PackDirectives packDirectives, ProgramSource[] sources, ComputeSource[][] computes, ShadowRenderTargets renderTargets, ShaderStorageBufferHolder holder, TextureAccess noiseTexture, FrameUpdateNotifier updateNotifier, - Object2ObjectMap customTextureIds, ImmutableMap explicitPreFlips, Object2ObjectMap irisCustomTextures, CustomUniforms customUniforms) { + Object2ObjectMap customTextureIds, Set customImages, ImmutableMap explicitPreFlips, Object2ObjectMap irisCustomTextures, CustomUniforms customUniforms) { this.pipeline = pipeline; this.noiseTexture = noiseTexture; this.updateNotifier = updateNotifier; this.renderTargets = renderTargets; this.customTextureIds = customTextureIds; this.irisCustomTextures = irisCustomTextures; + this.irisCustomImages = customImages; this.customUniforms = customUniforms; final PackRenderTargetDirectives renderTargetDirectives = packDirectives.getRenderTargetDirectives(); @@ -86,7 +97,7 @@ public ShadowCompositeRenderer(WorldRenderingPipeline pipeline, PackDirectives p if (source == null || !source.isValid()) { if (computes[i] != null) { ComputeOnlyPass pass = new ComputeOnlyPass(); - pass.computes = createComputes(computes[i], flipped, flippedAtLeastOnceSnapshot, renderTargets); + pass.computes = createComputes(computes[i], flipped, flippedAtLeastOnceSnapshot, renderTargets, holder); passes.add(pass); } continue; @@ -96,8 +107,8 @@ public ShadowCompositeRenderer(WorldRenderingPipeline pipeline, PackDirectives p ProgramDirectives directives = source.getDirectives(); pass.program = createProgram(source, flipped, flippedAtLeastOnceSnapshot, renderTargets); - pass.computes = createComputes(computes[i], flipped, flippedAtLeastOnceSnapshot, renderTargets); - int[] drawBuffers = new int[]{0, 1}; + pass.computes = createComputes(computes[i], flipped, flippedAtLeastOnceSnapshot, renderTargets, holder); + int[] drawBuffers = source.getDirectives().hasUnknownDrawBuffers() ? new int[]{0, 1} : source.getDirectives().getDrawBuffers(); GlFramebuffer framebuffer = renderTargets.createColorFramebuffer(flipped, drawBuffers); @@ -146,7 +157,7 @@ private static class Pass { ImmutableSet flippedAtLeastOnce; ImmutableSet stageReadsFromAlt; ImmutableSet mipmappedBuffers; - float viewportScale; + ViewportData viewportScale; ComputeProgram[] computes; protected void destroy() { @@ -188,7 +199,7 @@ public void renderAll() { } if (ranCompute) { - IrisRenderSystem.memoryBarrier(40); + IrisRenderSystem.memoryBarrier(GL43C.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL43C.GL_TEXTURE_FETCH_BARRIER_BIT | GL43C.GL_SHADER_STORAGE_BARRIER_BIT); } Program.unbind(); @@ -205,9 +216,11 @@ public void renderAll() { } } - float scaledWidth = renderTargets.getResolution() * renderPass.viewportScale; - float scaledHeight = renderTargets.getResolution() * renderPass.viewportScale; - RenderSystem.viewport(0, 0, (int) scaledWidth, (int) scaledHeight); + float scaledWidth = renderTargets.getResolution() * renderPass.viewportScale.scale(); + float scaledHeight = renderTargets.getResolution() * renderPass.viewportScale.scale(); + int beginWidth = (int) (renderTargets.getResolution() * renderPass.viewportScale.viewportX()); + int beginHeight = (int) (renderTargets.getResolution() * renderPass.viewportScale.viewportY()); + RenderSystem.viewport(beginWidth, beginHeight, (int) scaledWidth, (int) scaledHeight); renderPass.framebuffer.bind(); renderPass.program.use(); @@ -225,7 +238,9 @@ public void renderAll() { for (int i = 0; i < renderTargets.getRenderTargetCount(); i++) { // Reset mipmapping states at the end of the frame. - resetRenderTarget(renderTargets.get(i)); + if (renderTargets.get(i) != null) { + resetRenderTarget(renderTargets.get(i)); + } } RenderSystem.activeTexture(GL15C.GL_TEXTURE0); @@ -246,14 +261,20 @@ private static void setupMipmapping(net.coderbot.iris.rendertarget.RenderTarget // Also note that this only applies to one of the two buffers in a render target buffer pair - making it // unlikely that this issue occurs in practice with most shader packs. IrisRenderSystem.generateMipmaps(texture, GL20C.GL_TEXTURE_2D); - IrisRenderSystem.texParameteri(texture, GL20C.GL_TEXTURE_2D, GL20C.GL_TEXTURE_MIN_FILTER, GL20C.GL_LINEAR_MIPMAP_LINEAR); + IrisRenderSystem.texParameteri(texture, GL20C.GL_TEXTURE_2D, GL20C.GL_TEXTURE_MIN_FILTER, target.getInternalFormat().getPixelFormat().isInteger() ? GL20C.GL_NEAREST_MIPMAP_NEAREST : GL20C.GL_LINEAR_MIPMAP_LINEAR); } private static void resetRenderTarget(RenderTarget target) { // Resets the sampling mode of the given render target and then unbinds it to prevent accidental sampling of it // elsewhere. - IrisRenderSystem.texParameteri(target.getMainTexture(), GL20C.GL_TEXTURE_2D, GL20C.GL_TEXTURE_MIN_FILTER, GL20C.GL_LINEAR); - IrisRenderSystem.texParameteri(target.getAltTexture(), GL20C.GL_TEXTURE_2D, GL20C.GL_TEXTURE_MIN_FILTER, GL20C.GL_LINEAR); + + int filter = GL20C.GL_LINEAR; + if (target.getInternalFormat().getPixelFormat().isInteger()) { + filter = GL20C.GL_NEAREST; + } + + IrisRenderSystem.texParameteri(target.getMainTexture(), GL20C.GL_TEXTURE_2D, GL20C.GL_TEXTURE_MIN_FILTER, filter); + IrisRenderSystem.texParameteri(target.getAltTexture(), GL20C.GL_TEXTURE_2D, GL20C.GL_TEXTURE_MIN_FILTER, filter); } // TODO: Don't just copy this from DeferredWorldRenderingPipeline @@ -267,7 +288,7 @@ private Program createProgram(ProgramSource source, ImmutableSet flippe String vertex = transformed.get(PatchShaderType.VERTEX); String geometry = transformed.get(PatchShaderType.GEOMETRY); String fragment = transformed.get(PatchShaderType.FRAGMENT); - PatchedShaderPrinter.debugPatchedShaders(source.getName(), vertex, geometry, fragment); + ShaderPrinter.printProgram(source.getName()).addSources(transformed).print(); Objects.requireNonNull(flipped); ProgramBuilder builder; @@ -277,7 +298,7 @@ private Program createProgram(ProgramSource source, ImmutableSet flippe IrisSamplers.COMPOSITE_RESERVED_TEXTURE_UNITS); } catch (RuntimeException e) { // TODO: Better error handling - throw new RuntimeException("Shader compilation failed!", e); + throw new RuntimeException("Shader compilation failed for shadow composite " + source.getName() + "!", e); } ProgramSamplers.CustomTextureSamplerInterceptor customTextureSamplerInterceptor = ProgramSamplers.customTextureSamplerInterceptor(builder, customTextureIds, flippedAtLeastOnceSnapshot); @@ -288,9 +309,10 @@ private Program createProgram(ProgramSource source, ImmutableSet flippe IrisSamplers.addNoiseSampler(customTextureSamplerInterceptor, noiseTexture); IrisSamplers.addCustomTextures(customTextureSamplerInterceptor, irisCustomTextures); - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, targets, flipped); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, targets, flipped, pipeline.hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS)); IrisImages.addShadowColorImages(builder, targets, flipped); - + IrisImages.addCustomImages(builder, irisCustomImages); + IrisSamplers.addCustomImages(builder, irisCustomImages); Program build = builder.build(); this.customUniforms.mapholderToPass(builder, build); @@ -298,7 +320,7 @@ private Program createProgram(ProgramSource source, ImmutableSet flippe } private ComputeProgram[] createComputes(ComputeSource[] sources, ImmutableSet flipped, ImmutableSet flippedAtLeastOnceSnapshot, - ShadowRenderTargets targets) { + ShadowRenderTargets targets, ShaderStorageBufferHolder holder) { ComputeProgram[] programs = new ComputeProgram[sources.length]; for (int i = 0; i < programs.length; i++) { ComputeSource source = sources[i]; @@ -309,11 +331,14 @@ private ComputeProgram[] createComputes(ComputeSource[] sources, ImmutableSet ownedFramebuffers; private final int resolution; + private final WorldRenderingPipeline pipeline; private boolean fullClearRequired; private boolean translucentDepthDirty; private boolean[] hardwareFiltered; + private boolean[] linearFiltered; private InternalTextureFormat[] formats; private IntList buffersToBeCleared; - - public ShadowRenderTargets(int resolution, PackShadowDirectives shadowDirectives) { - targets = new RenderTarget[shadowDirectives.getColorSamplingSettings().size()]; - formats = new InternalTextureFormat[shadowDirectives.getColorSamplingSettings().size()]; - flipped = new boolean[shadowDirectives.getColorSamplingSettings().size()]; - hardwareFiltered = new boolean[shadowDirectives.getColorSamplingSettings().size()]; + private int size; + + public ShadowRenderTargets(WorldRenderingPipeline pipeline, int resolution, PackShadowDirectives shadowDirectives) { + this.pipeline = pipeline; + this.shadowDirectives = shadowDirectives; + this.size = pipeline.hasFeature(FeatureFlags.HIGHER_SHADOWCOLOR) ? PackShadowDirectives.MAX_SHADOW_COLOR_BUFFERS_IRIS : PackShadowDirectives.MAX_SHADOW_COLOR_BUFFERS_OF; + targets = new RenderTarget[size]; + formats = new InternalTextureFormat[size]; + flipped = new boolean[size]; + hardwareFiltered = new boolean[size]; + linearFiltered = new boolean[size]; buffersToBeCleared = new IntArrayList(); this.mainDepth = new DepthTexture(resolution, resolution, DepthBufferFormat.DEPTH); this.noTranslucents = new DepthTexture(resolution, resolution, DepthBufferFormat.DEPTH); - int[] drawBuffers = new int[shadowDirectives.getColorSamplingSettings().size()]; - - for (int i = 0; i < shadowDirectives.getColorSamplingSettings().size(); i++) { - PackShadowDirectives.SamplingSettings settings = shadowDirectives.getColorSamplingSettings().get(i); - targets[i] = RenderTarget.builder().setDimensions(resolution, resolution) - .setInternalFormat(settings.getFormat()) - .setPixelFormat(settings.getFormat().getPixelFormat()).build(); - formats[i] = settings.getFormat(); - if (settings.getClear()) { - buffersToBeCleared.add(i); - } - - drawBuffers[i] = i; - - if (settings.getClear()) { - buffersToBeCleared.add(i); - } - } for (int i = 0; i < shadowDirectives.getDepthSamplingSettings().size(); i++) { this.hardwareFiltered[i] = shadowDirectives.getDepthSamplingSettings().get(i).getHardwareFiltering(); + this.linearFiltered[i] = !shadowDirectives.getDepthSamplingSettings().get(i).getNearest(); } this.resolution = resolution; @@ -75,8 +70,6 @@ public ShadowRenderTargets(int resolution, PackShadowDirectives shadowDirectives fullClearRequired = true; this.depthSourceFb = createFramebufferWritingToMain(new int[] {0}); - this.mainRenderBuffer = createFramebufferWritingToMain(drawBuffers); - this.mainRenderBuffer.addDepthAttachment(this.mainDepth.getTextureId()); this.noTranslucentsDestFb = createFramebufferWritingToMain(new int[] {0}); this.noTranslucentsDestFb.addDepthAttachment(this.noTranslucents.getTextureId()); @@ -99,7 +92,9 @@ public void destroy() { } for (RenderTarget target : targets) { - target.destroy(); + if (target != null) { + target.destroy(); + } } mainDepth.destroy(); @@ -114,6 +109,50 @@ public RenderTarget get(int index) { return targets[index]; } + /** + * Gets the render target assigned to an index, and creates it if it does not exist. + * This is a expensive opetation nad may block other tasks! Use it sparingly, and use {@code get()} if possible. + * @param index The index of the render target to get + * @return The existing or a new render target, if no existing one exists + */ + public RenderTarget getOrCreate(int index) { + if (targets[index] != null) { + return targets[index]; + } + + create(index); + return targets[index]; + } + + private void create(int index) { + if (index > size) { + throw new IllegalStateException("Tried to access buffer higher than allowed limit of " + size + "! If you're trying to use shadowcolor2-7, you need to activate it's feature flag!"); + } + + + PackShadowDirectives.SamplingSettings settings = shadowDirectives.getColorSamplingSettings().computeIfAbsent(index, i -> new PackShadowDirectives.SamplingSettings()); + targets[index] = RenderTarget.builder().setDimensions(resolution, resolution) + .setInternalFormat(settings.getFormat()) + .setPixelFormat(settings.getFormat().getPixelFormat()).build(); + formats[index] = settings.getFormat(); + if (settings.getClear()) { + buffersToBeCleared.add(index); + } + + if (settings.getClear()) { + buffersToBeCleared.add(index); + } + + fullClearRequired = true; + pipeline.onShadowBufferChange(); + } + + public void createIfEmpty(int index) { + if (targets[index] == null) { + create(index); + } + } + public int getResolution() { return resolution; } @@ -185,10 +224,6 @@ private GlFramebuffer createEmptyFramebuffer() { return framebuffer; } - public GlFramebuffer getMainRenderBuffer() { - return mainRenderBuffer; - } - public GlFramebuffer createShadowFramebuffer(ImmutableSet stageWritesToAlt, int[] drawBuffers) { if (drawBuffers.length == 0) { return createEmptyFramebuffer(); @@ -239,12 +274,15 @@ public GlFramebuffer createColorFramebuffer(ImmutableSet stageWritesToM actualDrawBuffers[i] = i; if (drawBuffers[i] >= getRenderTargetCount()) { - // TODO: This causes resource leaks, also we should really verify this in the shaderpack parser... - throw new IllegalStateException("Render target with index " + drawBuffers[i] + " is not supported, only " - + getRenderTargetCount() + " render targets are supported."); + // If a shader is using an invalid drawbuffer, they're most likely relying on the Optifine behavior of ignoring DRAWBUFFERS in the shadow pass. + // We need to fix this for them, since apparantly this is a common issue. + // Iris.logger.warn("Invalid framebuffer was attempted to be created! Forcing a framebuffer with DRAWBUFFERS 01 for shadow."); + ownedFramebuffers.remove(framebuffer); + framebuffer.destroy(); + return createColorFramebuffer(stageWritesToMain, new int[] { 0, 1 }); } - RenderTarget target = this.get(drawBuffers[i]); + RenderTarget target = this.getOrCreate(drawBuffers[i]); int textureId = stageWritesToMain.contains(drawBuffers[i]) ? target.getMainTexture() : target.getAltTexture(); @@ -270,6 +308,10 @@ public boolean isHardwareFiltered(int i) { return hardwareFiltered[i]; } + public boolean isLinearFiltered(int i) { + return linearFiltered[i]; + } + public int getNumColorTextures() { return targets.length; } @@ -292,4 +334,5 @@ public ImmutableSet snapshot() { public IntList getBuffersToBeCleared() { return buffersToBeCleared; } + } diff --git a/src/main/java/net/coderbot/iris/shadows/frustum/BoxCuller.java b/src/main/java/net/coderbot/iris/shadows/frustum/BoxCuller.java index 494de192ec..de60ea453d 100644 --- a/src/main/java/net/coderbot/iris/shadows/frustum/BoxCuller.java +++ b/src/main/java/net/coderbot/iris/shadows/frustum/BoxCuller.java @@ -45,4 +45,9 @@ public boolean isCulled(float minX, float minY, float minZ, float maxX, float ma return false; } + + @Override + public String toString() { + return "Box Culling active; max distance " + maxDistance; + } } diff --git a/src/main/java/net/coderbot/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java b/src/main/java/net/coderbot/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java index f3e49eb973..8197aa2b33 100644 --- a/src/main/java/net/coderbot/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java +++ b/src/main/java/net/coderbot/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java @@ -1,7 +1,7 @@ package net.coderbot.iris.shadows.frustum.advanced; -import net.coderbot.iris.vendored.joml.Math; import net.coderbot.iris.shadows.frustum.BoxCuller; +import net.coderbot.iris.vendored.joml.Math; import net.coderbot.iris.vendored.joml.Matrix4f; import net.coderbot.iris.vendored.joml.Vector3f; import net.coderbot.iris.vendored.joml.Vector4f; @@ -68,7 +68,7 @@ public class AdvancedShadowCullingFrustum extends Frustum { private double z; private final Vector3f shadowLightVectorFromOrigin; - private final BoxCuller boxCuller; + protected final BoxCuller boxCuller; public AdvancedShadowCullingFrustum(Matrix4f playerView, Matrix4f playerProjection, Vector3f shadowLightVectorFromOrigin, BoxCuller boxCuller) { @@ -302,7 +302,7 @@ public boolean canDetermineInvisible(double minX, double minY, double minZ, doub return false; } - private int isVisible(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { + protected int isVisible(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { float f = (float)(minX - this.x); float g = (float)(minY - this.y); float h = (float)(minZ - this.z); @@ -323,7 +323,7 @@ private int isVisible(double minX, double minY, double minZ, double maxX, double * @param maxZ Maximum Z value of the AABB. * @return 0 if nothing is visible, 1 if everything is visible, 2 if only some corners are visible. */ - private int checkCornerVisibility(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { + protected int checkCornerVisibility(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { float outsideBoundX; float outsideBoundY; float outsideBoundZ; diff --git a/src/main/java/net/coderbot/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java b/src/main/java/net/coderbot/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java new file mode 100644 index 0000000000..a997ad1bc8 --- /dev/null +++ b/src/main/java/net/coderbot/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java @@ -0,0 +1,50 @@ +package net.coderbot.iris.shadows.frustum.advanced; + +import net.coderbot.iris.Iris; +import net.coderbot.iris.shadows.frustum.BoxCuller; +import net.coderbot.iris.vendored.joml.Matrix4f; +import net.coderbot.iris.vendored.joml.Vector3f; +import net.minecraft.world.phys.AABB; + +public class ReversedAdvancedShadowCullingFrustum extends AdvancedShadowCullingFrustum { + private final BoxCuller distanceCuller; + + public ReversedAdvancedShadowCullingFrustum(Matrix4f playerView, Matrix4f playerProjection, Vector3f shadowLightVectorFromOrigin, BoxCuller voxelCuller, BoxCuller distanceCuller) { + super(playerView, playerProjection, shadowLightVectorFromOrigin, voxelCuller); + this.distanceCuller = distanceCuller; + } + + @Override + public void prepare(double cameraX, double cameraY, double cameraZ) { + if (this.distanceCuller != null) { + this.distanceCuller.setPosition(cameraX, cameraY, cameraZ); + } + super.prepare(cameraX, cameraY, cameraZ); + } + + @Override + public boolean isVisible(AABB aabb) { + if (distanceCuller != null && distanceCuller.isCulled(aabb)) { + return false; + } + + if (boxCuller != null && !boxCuller.isCulled(aabb)) { + return true; + } + + return this.isVisible(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ) != 0; + } + + @Override + public int fastAabbTest(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { + if (distanceCuller != null && distanceCuller.isCulled(minX, minY, minZ, maxX, maxY, maxZ)) { + return 0; + } + + if (boxCuller != null && !boxCuller.isCulled(minX, minY, minZ, maxX, maxY, maxZ)) { + return 2; + } + + return isVisible(minX, minY, minZ, maxX, maxY, maxZ); + } +} diff --git a/src/main/java/net/coderbot/iris/uniforms/BiomeParameters.java b/src/main/java/net/coderbot/iris/uniforms/BiomeParameters.java index 0c8fe18d55..74346007e1 100644 --- a/src/main/java/net/coderbot/iris/uniforms/BiomeParameters.java +++ b/src/main/java/net/coderbot/iris/uniforms/BiomeParameters.java @@ -1,79 +1,51 @@ package net.coderbot.iris.uniforms; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import net.coderbot.iris.gl.uniform.FloatSupplier; import net.coderbot.iris.gl.uniform.UniformHolder; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; -import net.minecraft.data.BuiltinRegistries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.biome.Biome; -import java.util.Locale; import java.util.function.IntSupplier; import java.util.function.ToIntFunction; -import static net.coderbot.iris.gl.uniform.UniformUpdateFrequency.ONCE; import static net.coderbot.iris.gl.uniform.UniformUpdateFrequency.PER_TICK; public class BiomeParameters { - private static final Minecraft client = Minecraft.getInstance(); - - public static void addBiomeUniforms(UniformHolder uniforms) { - - uniforms - .uniform1i(PER_TICK, "biome", playerI(player -> - BuiltinRegistries.BIOME.getId(player.level.getBiome(player.blockPosition()).value()))) - .uniform1i(PER_TICK, "biome_category", playerI(player -> - Biome.getBiomeCategory(player.level.getBiome(player.blockPosition())).ordinal())) - .uniform1i(PER_TICK, "biome_precipitation", playerI(player -> { - Biome.Precipitation precipitation = player.level.getBiome(player.blockPosition()).value().getPrecipitation(); - switch (precipitation){ - case NONE: return 0; - case RAIN: return 1; - case SNOW: return 2; - } - throw new IllegalStateException("Unknown precipitation type:" + precipitation); - })) - .uniform1f(PER_TICK, "rainfall", playerF(player -> - player.level.getBiome(player.blockPosition()).value().getDownfall())) - .uniform1f(PER_TICK, "temperature", playerF(player -> - player.level.getBiome(player.blockPosition()).value().getBaseTemperature())) - - - .uniform1i(ONCE, "PPT_NONE", () -> 0) - .uniform1i(ONCE, "PPT_RAIN", () -> 1) - .uniform1i(ONCE, "PPT_SNOW", () -> 2); - - - - - addBiomes(uniforms); - addCategories(uniforms); + private static final Object2IntMap> biomeMap = new Object2IntOpenHashMap<>(); + public static Object2IntMap> getBiomeMap() { + return biomeMap; } - public static void addBiomes(UniformHolder uniforms) { - for (Biome biome : BuiltinRegistries.BIOME) { - ResourceLocation id = BuiltinRegistries.BIOME.getKey(biome); - if (id == null || !id.getNamespace().equals("minecraft")) { - continue; // TODO: What should we do with non-standard biomes? - } - int rawId = BuiltinRegistries.BIOME.getId(biome); - uniforms.uniform1i(ONCE, "BIOME_" + id.getPath().toUpperCase(Locale.ROOT), () -> rawId); - } - } - - public static void addCategories(UniformHolder uniforms) { - Biome.BiomeCategory[] categories = Biome.BiomeCategory.values(); - for (int i = 0; i < categories.length; i++) { - int finalI = i; - uniforms.uniform1i(ONCE, "CAT_" + categories[i].getName().toUpperCase(Locale.ROOT), () -> finalI); - } + public static void addBiomeUniforms(UniformHolder uniforms) { + uniforms + .uniform1i(PER_TICK, "biome", playerI(player -> + biomeMap.getInt(player.level.getBiome(player.blockPosition()).unwrapKey().orElse(null)))) + .uniform1i(PER_TICK, "biome_category", playerI(player -> { + return Biome.getBiomeCategory(player.level.getBiome(player.blockPosition())).ordinal(); + })) + .uniform1i(PER_TICK, "biome_precipitation", playerI(player -> { + Biome.Precipitation precipitation = player.level.getBiome(player.blockPosition()).value().getPrecipitation(); + switch (precipitation){ + case NONE: return 0; + case RAIN: return 1; + case SNOW: return 2; + } + throw new IllegalStateException("Unknown precipitation type:" + precipitation); + })) + .uniform1f(PER_TICK, "rainfall", playerF(player -> + (player.level.getBiome(player.blockPosition()).value()).getDownfall())) + .uniform1f(PER_TICK, "temperature", playerF(player -> + player.level.getBiome(player.blockPosition()).value().getBaseTemperature())); } static IntSupplier playerI(ToIntFunction function) { return () -> { - LocalPlayer player = client.player; + LocalPlayer player = Minecraft.getInstance().player; if (player == null) { return 0; // TODO: I'm not sure what I'm supposed to do here? } else { @@ -84,7 +56,7 @@ static IntSupplier playerI(ToIntFunction function) { static FloatSupplier playerF(ToFloatFunction function) { return () -> { - LocalPlayer player = client.player; + LocalPlayer player = Minecraft.getInstance().player; if (player == null) { return 0.0f; // TODO: I'm not sure what I'm supposed to do here? } else { diff --git a/src/main/java/net/coderbot/iris/uniforms/CapturedRenderingState.java b/src/main/java/net/coderbot/iris/uniforms/CapturedRenderingState.java index bf5c4e52b3..76ae27f730 100644 --- a/src/main/java/net/coderbot/iris/uniforms/CapturedRenderingState.java +++ b/src/main/java/net/coderbot/iris/uniforms/CapturedRenderingState.java @@ -1,7 +1,6 @@ package net.coderbot.iris.uniforms; import com.mojang.math.Matrix4f; -import net.coderbot.iris.gl.state.ValueUpdateNotifier; import net.coderbot.iris.vendored.joml.Vector3d; import net.minecraft.client.Minecraft; @@ -16,10 +15,9 @@ public class CapturedRenderingState { private float fogDensity; private float tickDelta; private int currentRenderedBlockEntity; - private Runnable blockEntityIdListener = null; private int currentRenderedEntity = -1; - private Runnable entityIdListener = null; + private int currentRenderedItem = -1; private float currentAlphaTest; @@ -72,10 +70,6 @@ public float getTickDelta() { public void setCurrentBlockEntity(int entity) { this.currentRenderedBlockEntity = entity; - - if (this.blockEntityIdListener != null) { - this.blockEntityIdListener.run(); - } } public int getCurrentRenderedBlockEntity() { @@ -84,22 +78,18 @@ public int getCurrentRenderedBlockEntity() { public void setCurrentEntity(int entity) { this.currentRenderedEntity = entity; - - if (this.entityIdListener != null) { - this.entityIdListener.run(); - } } - public ValueUpdateNotifier getEntityIdNotifier() { - return listener -> this.entityIdListener = listener; + public int getCurrentRenderedEntity() { + return currentRenderedEntity; } - public ValueUpdateNotifier getBlockEntityIdNotifier() { - return listener -> this.blockEntityIdListener = listener; + public void setCurrentRenderedItem(int item) { + this.currentRenderedItem = item; } - public int getCurrentRenderedEntity() { - return currentRenderedEntity; + public int getCurrentRenderedItem() { + return currentRenderedItem; } public float getCurrentAlphaTest() { diff --git a/src/main/java/net/coderbot/iris/uniforms/CommonUniforms.java b/src/main/java/net/coderbot/iris/uniforms/CommonUniforms.java index 8216e38a78..8ee135ff34 100644 --- a/src/main/java/net/coderbot/iris/uniforms/CommonUniforms.java +++ b/src/main/java/net/coderbot/iris/uniforms/CommonUniforms.java @@ -18,34 +18,22 @@ import net.coderbot.iris.uniforms.transforms.SmoothedFloat; import net.coderbot.iris.uniforms.transforms.SmoothedVec2f; import net.coderbot.iris.vendored.joml.Math; -import net.coderbot.iris.vendored.joml.Vector2f; -import net.coderbot.iris.vendored.joml.Vector2i; -import net.coderbot.iris.vendored.joml.Vector3d; -import net.coderbot.iris.vendored.joml.Vector4f; -import net.coderbot.iris.vendored.joml.Vector4i; -import net.irisshaders.iris.api.v0.item.IrisItemLightProvider; +import net.coderbot.iris.vendored.joml.*; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.texture.AbstractTexture; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.core.BlockPos; -import net.minecraft.world.InteractionHand; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.material.FogType; import net.minecraft.world.phys.Vec3; -import java.util.Objects; -import java.util.function.IntSupplier; - -import static net.coderbot.iris.gl.uniform.UniformUpdateFrequency.ONCE; -import static net.coderbot.iris.gl.uniform.UniformUpdateFrequency.PER_FRAME; -import static net.coderbot.iris.gl.uniform.UniformUpdateFrequency.PER_TICK; +import static net.coderbot.iris.gl.uniform.UniformUpdateFrequency.*; public final class CommonUniforms { private static final Minecraft client = Minecraft.getInstance(); @@ -63,6 +51,9 @@ public static void addDynamicUniforms(DynamicUniformHolder uniforms, FogMode fog FogUniforms.addFogUniforms(uniforms, fogMode); IrisInternalUniforms.addFogUniforms(uniforms, fogMode); + // This is a fallback for when entityId via attributes cannot be used. (lightning) + uniforms.uniform1i("entityId", CapturedRenderingState.INSTANCE::getCurrentRenderedEntity, StateUpdateNotifiers.fallbackEntityNotifier); + // TODO: OptiFine doesn't think that atlasSize is a "dynamic" uniform, // but we do. How will custom uniforms depending on atlasSize work? // @@ -89,12 +80,6 @@ public static void addDynamicUniforms(DynamicUniformHolder uniforms, FogMode fog }, StateUpdateNotifiers.bindTextureNotifier); - uniforms.uniform1i("entityId", CapturedRenderingState.INSTANCE::getCurrentRenderedEntity, - CapturedRenderingState.INSTANCE.getEntityIdNotifier()); - - uniforms.uniform1i("blockEntityId", CapturedRenderingState.INSTANCE::getCurrentRenderedBlockEntity, - CapturedRenderingState.INSTANCE.getBlockEntityIdNotifier()); - uniforms.uniform4i("blendFunc", () -> { GlStateManager.BlendState blend = GlStateManagerAccessor.getBLEND(); @@ -121,6 +106,7 @@ public static void addNonDynamicUniforms(UniformHolder uniforms, IdMap idMap, Pa BiomeParameters.addBiomeUniforms(uniforms); new CelestialUniforms(directives.getSunPathRotation()).addCelestialUniforms(uniforms); IrisExclusiveUniforms.addIrisExclusiveUniforms(uniforms); + IrisTimeUniforms.addTimeUniforms(uniforms); MatrixUniforms.addMatrixUniforms(uniforms, directives); IdMapUniforms.addIdMapUniforms(updateNotifier, uniforms, idMap, directives.isOldHandLight()); CommonUniforms.generalCommonUniforms(uniforms, updateNotifier, directives); @@ -141,12 +127,15 @@ public static void generalCommonUniforms(UniformHolder uniforms, FrameUpdateNoti .uniform1b(PER_FRAME, "is_hurt", CommonUniforms::isHurt) .uniform1b(PER_FRAME, "is_invisible", CommonUniforms::isInvisible) .uniform1b(PER_FRAME, "is_burning", CommonUniforms::isBurning) + .uniform1b(PER_FRAME, "is_on_ground", CommonUniforms::isOnGround) // TODO: Do we need to clamp this to avoid fullbright breaking shaders? Or should shaders be able to detect // that the player is trying to turn on fullbright? .uniform1f(PER_FRAME, "screenBrightness", () -> client.options.gamma) // just a dummy value for shaders where entityColor isn't supplied through a vertex attribute (and thus is // not available) - suppresses warnings. See AttributeShaderTransformer for the actual entityColor code. .uniform4f(ONCE, "entityColor", () -> new Vector4f(0, 0, 0, 0)) + .uniform1i(ONCE, "blockEntityId", () -> -1) + .uniform1i(ONCE, "currentRenderedItemId", () -> -1) .uniform1f(ONCE, "pi", () -> Math.PI) .uniform1f(PER_TICK, "playerMood", CommonUniforms::getPlayerMood) .uniform2i(PER_FRAME, "eyeBrightness", CommonUniforms::getEyeBrightness) @@ -159,6 +148,10 @@ public static void generalCommonUniforms(UniformHolder uniforms, FrameUpdateNoti .uniform3d(PER_FRAME, "skyColor", CommonUniforms::getSkyColor); } + private static boolean isOnGround() { + return client.player != null && client.player.isOnGround(); + } + private static boolean isHurt() { if (client.player != null) { return client.player.hurtTime > 0; // Do not use isHurt, that's not what we want! diff --git a/src/main/java/net/coderbot/iris/uniforms/ExternallyManagedUniforms.java b/src/main/java/net/coderbot/iris/uniforms/ExternallyManagedUniforms.java index e5d1b0ff2a..525514984a 100644 --- a/src/main/java/net/coderbot/iris/uniforms/ExternallyManagedUniforms.java +++ b/src/main/java/net/coderbot/iris/uniforms/ExternallyManagedUniforms.java @@ -11,7 +11,7 @@ private ExternallyManagedUniforms() { public static void addExternallyManagedUniforms(UniformHolder uniformHolder) { addMat4(uniformHolder, "iris_ModelViewMatrix"); addMat4(uniformHolder, "u_ModelViewProjectionMatrix"); - addMat4(uniformHolder, "iris_NormalMatrix"); + addMat3(uniformHolder, "iris_NormalMatrix"); // Exclusive to pre-1.19 addFloat(uniformHolder, "darknessFactor"); addFloat(uniformHolder, "darknessLightFactor"); @@ -33,8 +33,9 @@ public static void addExternallyManagedUniforms117(UniformHolder uniformHolder) addVec4(uniformHolder, "iris_FogColor"); addMat4(uniformHolder, "iris_ProjectionMatrix"); addMat4(uniformHolder, "iris_ModelViewMatrix"); - addMat4(uniformHolder, "iris_NormalMatrix"); + addMat3(uniformHolder, "iris_NormalMatrix"); addFloat(uniformHolder, "iris_TextureScale"); + addFloat(uniformHolder, "iris_GlintAlpha"); addFloat(uniformHolder, "iris_ModelScale"); addFloat(uniformHolder, "iris_ModelOffset"); addVec3(uniformHolder, "iris_CameraTranslation"); @@ -55,6 +56,11 @@ public static void addExternallyManagedUniforms117(UniformHolder uniformHolder) uniformHolder.externallyManagedUniform("iris_FogColor", UniformType.VEC4); } + private static void addMat3(UniformHolder uniformHolder, String name) { + uniformHolder.externallyManagedUniform(name, UniformType.MAT3); + } + + private static void addMat4(UniformHolder uniformHolder, String name) { uniformHolder.externallyManagedUniform(name, UniformType.MAT4); } diff --git a/src/main/java/net/coderbot/iris/uniforms/IdMapUniforms.java b/src/main/java/net/coderbot/iris/uniforms/IdMapUniforms.java index d547f9e839..b91902e911 100644 --- a/src/main/java/net/coderbot/iris/uniforms/IdMapUniforms.java +++ b/src/main/java/net/coderbot/iris/uniforms/IdMapUniforms.java @@ -37,11 +37,9 @@ public static void addIdMapUniforms(FrameUpdateNotifier notifier, UniformHolder .uniform1i(UniformUpdateFrequency.PER_FRAME, "heldItemId", mainHandSupplier::getIntID) .uniform1i(UniformUpdateFrequency.PER_FRAME, "heldItemId2", offHandSupplier::getIntID) .uniform1i(PER_FRAME, "heldBlockLightValue", mainHandSupplier::getLightValue) - .uniform1i(PER_FRAME, "heldBlockLightValue2", offHandSupplier::getLightValue); - // TODO: Figure out API. - //.uniformVanilla3f(PER_FRAME, "heldBlockLightColor", mainHandSupplier::getLightColor) - //.uniformVanilla3f(PER_FRAME, "heldBlockLightColor2", offHandSupplier::getLightColor); - + .uniform1i(PER_FRAME, "heldBlockLightValue2", offHandSupplier::getLightValue) + .uniformVanilla3f(PER_FRAME, "heldBlockLightColor", mainHandSupplier::getLightColor) + .uniformVanilla3f(PER_FRAME, "heldBlockLightColor2", offHandSupplier::getLightColor); } /** diff --git a/src/main/java/net/coderbot/iris/uniforms/IrisExclusiveUniforms.java b/src/main/java/net/coderbot/iris/uniforms/IrisExclusiveUniforms.java index 40b490844b..1037ae4fb5 100644 --- a/src/main/java/net/coderbot/iris/uniforms/IrisExclusiveUniforms.java +++ b/src/main/java/net/coderbot/iris/uniforms/IrisExclusiveUniforms.java @@ -1,7 +1,9 @@ package net.coderbot.iris.uniforms; +import net.coderbot.iris.JomlConversions; import net.coderbot.iris.gl.uniform.UniformHolder; import net.coderbot.iris.gl.uniform.UniformUpdateFrequency; +import net.coderbot.iris.gui.option.IrisVideoSettings; import net.coderbot.iris.mixin.DimensionTypeAccessor; import net.coderbot.iris.vendored.joml.Math; import net.coderbot.iris.vendored.joml.Vector3d; @@ -9,7 +11,10 @@ import net.coderbot.iris.vendored.joml.Vector4f; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.LightningBolt; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.GameType; import net.minecraft.world.phys.Vec3; @@ -20,17 +25,30 @@ public class IrisExclusiveUniforms { public static void addIrisExclusiveUniforms(UniformHolder uniforms) { WorldInfoUniforms.addWorldInfoUniforms(uniforms); + uniforms.uniform1i(UniformUpdateFrequency.PER_TICK, "currentColorSpace", () -> IrisVideoSettings.colorSpace.ordinal()); + //All Iris-exclusive uniforms (uniforms which do not exist in either OptiFine or ShadersMod) should be registered here. uniforms.uniform1f(UniformUpdateFrequency.PER_FRAME, "thunderStrength", IrisExclusiveUniforms::getThunderStrength); uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "currentPlayerHealth", IrisExclusiveUniforms::getCurrentHealth); uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "maxPlayerHealth", IrisExclusiveUniforms::getMaxHealth); uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "currentPlayerHunger", IrisExclusiveUniforms::getCurrentHunger); uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "maxPlayerHunger", () -> 20); + uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "currentPlayerArmor", IrisExclusiveUniforms::getCurrentArmor); + uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "maxPlayerArmor", () -> 50); uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "currentPlayerAir", IrisExclusiveUniforms::getCurrentAir); uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "maxPlayerAir", IrisExclusiveUniforms::getMaxAir); uniforms.uniform1b(UniformUpdateFrequency.PER_FRAME, "firstPersonCamera", IrisExclusiveUniforms::isFirstPersonCamera); uniforms.uniform1b(UniformUpdateFrequency.PER_TICK, "isSpectator", IrisExclusiveUniforms::isSpectator); uniforms.uniform3d(UniformUpdateFrequency.PER_FRAME, "eyePosition", IrisExclusiveUniforms::getEyePosition); + uniforms.uniform3d(UniformUpdateFrequency.PER_FRAME, "relativeEyePosition", () -> { + return CameraUniforms.getUnshiftedCameraPosition().sub(getEyePosition()); + }); + uniforms.uniform3d(UniformUpdateFrequency.PER_FRAME, "playerLookVector", () -> { + return JomlConversions.fromVec3(Minecraft.getInstance().getCameraEntity().getLookAngle()); + }); + uniforms.uniform3d(UniformUpdateFrequency.PER_FRAME, "playerBodyVector", () -> { + return JomlConversions.fromVec3(Minecraft.getInstance().getCameraEntity().getForward()); + }); Vector4f zero = new Vector4f(0, 0, 0, 0); uniforms.uniform4f(UniformUpdateFrequency.PER_TICK, "lightningBoltPosition", () -> { if (Minecraft.getInstance().level != null) { @@ -75,6 +93,14 @@ private static float getCurrentAir() { return (float) Minecraft.getInstance().player.getAirSupply() / (float) Minecraft.getInstance().player.getMaxAirSupply(); } + private static float getCurrentArmor() { + if (Minecraft.getInstance().player == null || !Minecraft.getInstance().gameMode.getPlayerMode().isSurvival()) { + return -1; + } + + return (float) (Minecraft.getInstance().player.getArmorValue() / 50.0f); + } + private static float getMaxAir() { if (Minecraft.getInstance().player == null || !Minecraft.getInstance().gameMode.getPlayerMode().isSurvival()) { return -1; @@ -91,6 +117,8 @@ private static float getMaxHealth() { return Minecraft.getInstance().player.getMaxHealth(); } + + private static boolean isFirstPersonCamera() { // If camera type is not explicitly third-person, assume it's first-person. switch (Minecraft.getInstance().options.getCameraType()) { @@ -107,17 +135,39 @@ private static boolean isSpectator() { private static Vector3d getEyePosition() { Objects.requireNonNull(Minecraft.getInstance().getCameraEntity()); - return new Vector3d(Minecraft.getInstance().getCameraEntity().getX(), Minecraft.getInstance().getCameraEntity().getEyeY(), Minecraft.getInstance().getCameraEntity().getZ()); + Vec3 pos = Minecraft.getInstance().getCameraEntity().getEyePosition(CapturedRenderingState.INSTANCE.getTickDelta()); + return new Vector3d(pos.x, pos.y, pos.z); } public static class WorldInfoUniforms { public static void addWorldInfoUniforms(UniformHolder uniforms) { ClientLevel level = Minecraft.getInstance().level; // TODO: Use level.dimensionType() coordinates for 1.18! - uniforms.uniform1i(UniformUpdateFrequency.PER_FRAME, "bedrockLevel", () -> 0); + uniforms.uniform1i(UniformUpdateFrequency.PER_FRAME, "bedrockLevel", () -> { + if (level != null) { + return level.dimensionType().minY(); + } else { + return 0; + } + }); + uniforms.uniform1f(UniformUpdateFrequency.PER_FRAME, "cloudHeight", () -> { + if (level != null) { + return level.effects().getCloudHeight(); + } else { + return 192.0; + } + }); + uniforms.uniform1i(UniformUpdateFrequency.PER_FRAME, "heightLimit", () -> { if (level != null) { - return level.getMaxBuildHeight(); + return level.dimensionType().height(); + } else { + return 256; + } + }); + uniforms.uniform1i(UniformUpdateFrequency.PER_FRAME, "logicalHeightLimit", () -> { + if (level != null) { + return level.dimensionType().logicalHeight(); } else { return 256; } diff --git a/src/main/java/net/coderbot/iris/uniforms/IrisTimeUniforms.java b/src/main/java/net/coderbot/iris/uniforms/IrisTimeUniforms.java new file mode 100644 index 0000000000..a47f2d17fb --- /dev/null +++ b/src/main/java/net/coderbot/iris/uniforms/IrisTimeUniforms.java @@ -0,0 +1,35 @@ +package net.coderbot.iris.uniforms; + +import net.coderbot.iris.Iris; +import net.coderbot.iris.gl.uniform.UniformHolder; +import net.coderbot.iris.gl.uniform.UniformUpdateFrequency; +import net.coderbot.iris.vendored.joml.Vector2i; +import net.coderbot.iris.vendored.joml.Vector3i; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalField; +import java.util.GregorianCalendar; + +public class IrisTimeUniforms { + private static LocalDateTime dateTime; + + public static void updateTime() { + dateTime = LocalDateTime.now(); + } + + public static void addTimeUniforms(UniformHolder uniforms) { + Vector3i date = new Vector3i(); + Vector3i time = new Vector3i(); + Vector2i yearTime = new Vector2i(); + uniforms.uniform3i(UniformUpdateFrequency.PER_TICK, "currentDate", () -> date.set(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth())); + uniforms.uniform3i(UniformUpdateFrequency.PER_TICK, "currentTime", () -> time.set(dateTime.getHour(), dateTime.getMinute(), dateTime.getSecond())); + uniforms.uniform2i(UniformUpdateFrequency.PER_TICK, "currentYearTime", () -> yearTime.set( + ((dateTime.getDayOfYear() - 1) * 86400) + (dateTime.getHour() * 3600) + (dateTime.getMinute() * 60) + dateTime.getSecond(), + (dateTime.toLocalDate().lengthOfYear() * 86400) - (((dateTime.getDayOfYear() - 1) * 86400) + (dateTime.getHour() * 3600) + (dateTime.getMinute() * 60) + dateTime.getSecond()) + )); + } + + static { + } +} diff --git a/src/main/java/net/coderbot/iris/uniforms/builtin/BuiltinReplacementUniforms.java b/src/main/java/net/coderbot/iris/uniforms/builtin/BuiltinReplacementUniforms.java index 62b3963227..0811cabed4 100644 --- a/src/main/java/net/coderbot/iris/uniforms/builtin/BuiltinReplacementUniforms.java +++ b/src/main/java/net/coderbot/iris/uniforms/builtin/BuiltinReplacementUniforms.java @@ -1,23 +1,22 @@ package net.coderbot.iris.uniforms.builtin; -import com.mojang.math.Matrix4f; -import net.coderbot.iris.Iris; import net.coderbot.iris.gl.uniform.UniformHolder; import net.coderbot.iris.gl.uniform.UniformUpdateFrequency; +import net.coderbot.iris.vendored.joml.Matrix4f; public class BuiltinReplacementUniforms { private static final Matrix4f lightmapTextureMatrix; static { // This mimics the transformations done in LightTexture to the GL_TEXTURE matrix. - lightmapTextureMatrix = new Matrix4f(); - lightmapTextureMatrix.setIdentity(); - lightmapTextureMatrix.multiply(0.00390625f); - lightmapTextureMatrix.multiply(Matrix4f.createTranslateMatrix(8.0f, 8.0f, 8.0f)); + lightmapTextureMatrix = new Matrix4f(0.00390625f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.00390625f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.00390625f, 0.0f, + 0.03125f, 0.03125f, 0.03125f, 1.0f); } public static void addBuiltinReplacementUniforms(UniformHolder uniforms) { - uniforms.uniformMatrix(UniformUpdateFrequency.ONCE, "iris_LightmapTextureMatrix", () -> { + uniforms.uniformJomlMatrix(UniformUpdateFrequency.ONCE, "iris_LightmapTextureMatrix", () -> { // Iris.logger.warn("A shader appears to require the lightmap texture matrix even after transformations have occurred"); // Iris.logger.warn("Iris handles this correctly but it indicates that the shader is doing weird things with lightmap coordinates"); diff --git a/src/main/java/net/coderbot/iris/uniforms/custom/CustomUniformFixedInputUniformsHolder.java b/src/main/java/net/coderbot/iris/uniforms/custom/CustomUniformFixedInputUniformsHolder.java index f1a3ac9590..1a895a94ff 100644 --- a/src/main/java/net/coderbot/iris/uniforms/custom/CustomUniformFixedInputUniformsHolder.java +++ b/src/main/java/net/coderbot/iris/uniforms/custom/CustomUniformFixedInputUniformsHolder.java @@ -10,8 +10,6 @@ import net.coderbot.iris.gl.uniform.UniformUpdateFrequency; import net.coderbot.iris.uniforms.custom.cached.*; import net.coderbot.iris.vendored.joml.*; -import net.minecraft.world.phys.Vec2; -import net.minecraft.world.phys.Vec3; import org.lwjgl.BufferUtils; import java.nio.FloatBuffer; @@ -107,6 +105,11 @@ public Builder uniform3f(UniformUpdateFrequency updateFrequency, String name, Su return this.put(name, new Float3VectorCachedUniform(name, updateFrequency, value)); } + @Override + public Builder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier value) { + return this.put(name, new Int3VectorCachedUniform(name, updateFrequency, value)); + } + @Override public UniformHolder uniformVanilla3f(UniformUpdateFrequency updateFrequency, String name, Supplier value) { return this.put(name, new Float3VanillaVectorCachedUniform(name, updateFrequency, value)); diff --git a/src/main/java/net/coderbot/iris/uniforms/custom/CustomUniforms.java b/src/main/java/net/coderbot/iris/uniforms/custom/CustomUniforms.java index f0feb91279..c898f352a5 100644 --- a/src/main/java/net/coderbot/iris/uniforms/custom/CustomUniforms.java +++ b/src/main/java/net/coderbot/iris/uniforms/custom/CustomUniforms.java @@ -306,7 +306,7 @@ public void addVariable(String type, String name, String expression, boolean isU ExpressionElement ast = Parser.parse(expression, IrisOptions.options); variables.put(name, new Variable(parsedType, name, ast, isUniform)); } catch (Exception e) { - Iris.logger.warn("Failed to parse custom variable/uniform", e); + Iris.logger.warn("Failed to parse custom variable/uniform " + name + " with expression " + expression, e); } } diff --git a/src/main/java/net/coderbot/iris/uniforms/custom/cached/Int3VectorCachedUniform.java b/src/main/java/net/coderbot/iris/uniforms/custom/cached/Int3VectorCachedUniform.java new file mode 100644 index 0000000000..803570143a --- /dev/null +++ b/src/main/java/net/coderbot/iris/uniforms/custom/cached/Int3VectorCachedUniform.java @@ -0,0 +1,31 @@ +package net.coderbot.iris.uniforms.custom.cached; + +import net.coderbot.iris.gl.uniform.UniformUpdateFrequency; +import net.coderbot.iris.parsing.VectorType; +import net.coderbot.iris.vendored.joml.Vector3f; +import net.coderbot.iris.vendored.joml.Vector3i; +import org.lwjgl.opengl.GL21; + +import java.util.function.Supplier; + +public class Int3VectorCachedUniform extends VectorCachedUniform { + + public Int3VectorCachedUniform(String name, UniformUpdateFrequency updateFrequency, Supplier supplier) { + super(name, updateFrequency, new Vector3i(), supplier); + } + + @Override + protected void setFrom(Vector3i other) { + this.cached.set(other); + } + + @Override + public void push(int location) { + GL21.glUniform3i(location, this.cached.x, this.cached.y, this.cached.z); + } + + @Override + public VectorType getType() { + return VectorType.I_VEC3; + } +} diff --git a/src/main/java/net/coderbot/iris/vertices/ImmediateState.java b/src/main/java/net/coderbot/iris/vertices/ImmediateState.java index 2762c6bda0..7e13ce2970 100644 --- a/src/main/java/net/coderbot/iris/vertices/ImmediateState.java +++ b/src/main/java/net/coderbot/iris/vertices/ImmediateState.java @@ -1,9 +1,10 @@ package net.coderbot.iris.vertices; /** - * Some annoying global state needed for the extended vertex format disabling optimization. + * Some annoying global state needed for rendering. */ public class ImmediateState { public static boolean isRenderingLevel = false; + public static boolean usingTessellation = false; public static boolean renderWithExtendedVertexFormat = true; } diff --git a/src/main/java/net/coderbot/iris/vertices/IrisTextVertexSinkImpl.java b/src/main/java/net/coderbot/iris/vertices/IrisTextVertexSinkImpl.java index d6c9dad2c2..4c50876850 100644 --- a/src/main/java/net/coderbot/iris/vertices/IrisTextVertexSinkImpl.java +++ b/src/main/java/net/coderbot/iris/vertices/IrisTextVertexSinkImpl.java @@ -1,19 +1,21 @@ package net.coderbot.iris.vertices; import com.mojang.blaze3d.vertex.VertexFormat; +import net.coderbot.iris.uniforms.CapturedRenderingState; import net.coderbot.iris.vendored.joml.Vector3f; import net.irisshaders.iris.api.v0.IrisTextVertexSink; +import net.minecraft.client.renderer.texture.OverlayTexture; import org.lwjgl.system.MemoryUtil; import java.nio.ByteBuffer; import java.util.function.IntFunction; public class IrisTextVertexSinkImpl implements IrisTextVertexSink { - static VertexFormat format = IrisVertexFormats.TERRAIN; + static VertexFormat format = IrisVertexFormats.ENTITY; private final ByteBuffer buffer; private final TextQuadView quad = new TextQuadView(); private final Vector3f saveNormal = new Vector3f(); - private static final int STRIDE = IrisVertexFormats.TERRAIN.getVertexSize(); + private static final int STRIDE = IrisVertexFormats.ENTITY.getVertexSize(); private int vertexCount; private long elementOffset; private float uSum; @@ -33,7 +35,14 @@ public VertexFormat getUnderlyingVertexFormat() { public ByteBuffer getUnderlyingByteBuffer() { return buffer; } - + private static final int OFFSET_POSITION = 0; + private static final int OFFSET_COLOR = 12; + private static final int OFFSET_TEXTURE = 16; + private static final int OFFSET_MID_TEXTURE = 42; + private static final int OFFSET_OVERLAY = 24; + private static final int OFFSET_LIGHT = 28; + private static final int OFFSET_NORMAL = 32; + private static final int OFFSET_TANGENT = 50; @Override public void quad(float minX, float minY, float maxX, float maxY, float z, int color, float minU, float minV, float maxU, float maxV, int light) { vertex(minX, minY, z, color, minU, minV, light); @@ -47,36 +56,41 @@ private void vertex(float x, float y, float z, int color, float u, float v, int uSum += u; vSum += v; - long i = elementOffset; + long ptr = elementOffset; + + MemoryUtil.memPutFloat(ptr + OFFSET_POSITION + 0, x); + MemoryUtil.memPutFloat(ptr + OFFSET_POSITION + 4, y); + MemoryUtil.memPutFloat(ptr + OFFSET_POSITION + 8, z); + + MemoryUtil.memPutInt(ptr + OFFSET_COLOR, color); + + MemoryUtil.memPutFloat(ptr + OFFSET_TEXTURE + 0, u); + MemoryUtil.memPutFloat(ptr + OFFSET_TEXTURE + 4, v); + + MemoryUtil.memPutInt(ptr + OFFSET_LIGHT, light); - MemoryUtil.memPutFloat(i, x); - MemoryUtil.memPutFloat(i + 4, y); - MemoryUtil.memPutFloat(i + 8, z); - MemoryUtil.memPutInt(i + 12, color); - MemoryUtil.memPutFloat(i + 16, u); - MemoryUtil.memPutFloat(i + 20, v); - MemoryUtil.memPutInt(i + 24, light); + MemoryUtil.memPutInt(ptr + OFFSET_OVERLAY, OverlayTexture.NO_OVERLAY); if (vertexCount == 4) { // TODO: compute this at the head of quad() vertexCount = 0; uSum *= 0.25; vSum *= 0.25; - quad.setup(elementOffset, IrisVertexFormats.TERRAIN.getVertexSize()); + quad.setup(elementOffset, IrisVertexFormats.ENTITY.getVertexSize()); NormalHelper.computeFaceNormal(saveNormal, quad); float normalX = saveNormal.x; float normalY = saveNormal.y; float normalZ = saveNormal.z; - int normal = NormalHelper.packNormal(saveNormal, 0.0F); + int normal = NormI8.pack(normalX, normalY, normalZ, 0.0F); int tangent = NormalHelper.computeTangent(normalX, normalY, normalZ, quad); for (long vertex = 0; vertex < 4; vertex++) { - MemoryUtil.memPutFloat(i + 36 - STRIDE * vertex, uSum); - MemoryUtil.memPutFloat(i + 40 - STRIDE * vertex, vSum); - MemoryUtil.memPutInt(i + 28 - STRIDE * vertex, normal); - MemoryUtil.memPutInt(i + 44 - STRIDE * vertex, tangent); + MemoryUtil.memPutFloat(ptr + OFFSET_MID_TEXTURE - STRIDE * vertex, uSum); + MemoryUtil.memPutFloat(ptr + (OFFSET_MID_TEXTURE + 4) - STRIDE * vertex, vSum); + MemoryUtil.memPutInt(ptr + OFFSET_NORMAL - STRIDE * vertex, normal); + MemoryUtil.memPutInt(ptr + OFFSET_TANGENT - STRIDE * vertex, tangent); } uSum = 0; diff --git a/src/main/java/net/coderbot/iris/vertices/IrisVertexFormats.java b/src/main/java/net/coderbot/iris/vertices/IrisVertexFormats.java index b378d3d650..44ef5287de 100644 --- a/src/main/java/net/coderbot/iris/vertices/IrisVertexFormats.java +++ b/src/main/java/net/coderbot/iris/vertices/IrisVertexFormats.java @@ -4,21 +4,26 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormatElement; +import net.coderbot.iris.Iris; public class IrisVertexFormats { public static final VertexFormatElement ENTITY_ELEMENT; + public static final VertexFormatElement ENTITY_ID_ELEMENT; public static final VertexFormatElement MID_TEXTURE_ELEMENT; public static final VertexFormatElement TANGENT_ELEMENT; public static final VertexFormatElement MID_BLOCK_ELEMENT; + public static final VertexFormatElement PADDING_SHORT; public static final VertexFormat TERRAIN; public static final VertexFormat ENTITY; static { ENTITY_ELEMENT = new VertexFormatElement(11, VertexFormatElement.Type.SHORT, VertexFormatElement.Usage.GENERIC, 2); + ENTITY_ID_ELEMENT = new VertexFormatElement(11, VertexFormatElement.Type.USHORT, VertexFormatElement.Usage.UV, 3); MID_TEXTURE_ELEMENT = new VertexFormatElement(12, VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.GENERIC, 2); TANGENT_ELEMENT = new VertexFormatElement(13, VertexFormatElement.Type.BYTE, VertexFormatElement.Usage.GENERIC, 4); MID_BLOCK_ELEMENT = new VertexFormatElement(14, VertexFormatElement.Type.BYTE, VertexFormatElement.Usage.GENERIC, 3); + PADDING_SHORT = new VertexFormatElement(1, VertexFormatElement.Type.SHORT, VertexFormatElement.Usage.PADDING, 1); ImmutableMap.Builder terrainElements = ImmutableMap.builder(); ImmutableMap.Builder entityElements = ImmutableMap.builder(); @@ -42,10 +47,21 @@ public class IrisVertexFormats { entityElements.put("UV2", DefaultVertexFormat.ELEMENT_UV2); // 32 entityElements.put("Normal", DefaultVertexFormat.ELEMENT_NORMAL); // 35 entityElements.put("Padding", DefaultVertexFormat.ELEMENT_PADDING); // 36 - entityElements.put("mc_midTexCoord", MID_TEXTURE_ELEMENT); // 44 - entityElements.put("at_tangent", TANGENT_ELEMENT); // 48 + entityElements.put("iris_Entity", ENTITY_ID_ELEMENT); // 40 + entityElements.put("mc_midTexCoord", MID_TEXTURE_ELEMENT); // 48 + entityElements.put("at_tangent", TANGENT_ELEMENT); // 52 + entityElements.put("Padding2", PADDING_SHORT); // 52 TERRAIN = new VertexFormat(terrainElements.build()); ENTITY = new VertexFormat(entityElements.build()); } + + private static void debug(VertexFormat format) { + Iris.logger.info("Vertex format: " + format); + int byteIndex = 0; + for (VertexFormatElement element : format.getElements()) { + Iris.logger.info(element + " @ " + byteIndex + " is " + element.getType() + " " + element.getUsage()); + byteIndex += element.getByteSize(); + } + } } diff --git a/src/main/java/net/coderbot/iris/vertices/NormI8.java b/src/main/java/net/coderbot/iris/vertices/NormI8.java new file mode 100644 index 0000000000..e365a019fe --- /dev/null +++ b/src/main/java/net/coderbot/iris/vertices/NormI8.java @@ -0,0 +1,87 @@ +package net.coderbot.iris.vertices; + +import net.minecraft.util.Mth; +import repack.joml.Vector3f; + +/** + * Provides some utilities for working with packed normal vectors. Each normal component provides 8 bits of + * precision in the range of [-1.0,1.0]. + * Copied from Sodium, licensed under the LGPLv3. Modified to support a W component. + * + * | 32 | 24 | 16 | 8 | + * | 0000 0000 | 0110 1100 | 0110 1100 | 0110 1100 | + * | W | X | Y | Z | + */ +public class NormI8 { + private static final int X_COMPONENT_OFFSET = 0; + private static final int Y_COMPONENT_OFFSET = 8; + private static final int Z_COMPONENT_OFFSET = 16; + private static final int W_COMPONENT_OFFSET = 24; + + /** + * The maximum value of a normal's vector component. + */ + private static final float COMPONENT_RANGE = 127.0f; + + /** + * Constant value which can be multiplied with a floating-point vector component to get the normalized value. The + * multiplication is slightly faster than a floating point division, and this code is a hot path which justifies it. + */ + private static final float NORM = 1.0f / COMPONENT_RANGE; + + public static int pack(Vector3f normal) { + return pack(normal.x(), normal.y(), normal.z(), 0); + } + + /** + * Packs the specified vector components into a 32-bit integer in XYZ ordering with the 8 bits of padding at the + * end. + * @param x The x component of the normal's vector + * @param y The y component of the normal's vector + * @param z The z component of the normal's vector + */ + public static int pack(float x, float y, float z, float w) { + return ((int) (x * 127) & 0xFF) | (((int) (y * 127) & 0xFF) << 8) | (((int) (z * 127) & 0xFF) << 16) | (((int) (w * 127) & 0xFF) << 24); + } + + /** + * Encodes a float in the range of -1.0..1.0 to a normalized unsigned integer in the range of 0..255 which can then + * be passed to graphics memory. + */ + private static int encode(float comp) { + // TODO: is the clamp necessary here? our inputs should always be normalized vector components + return ((int) (Mth.clamp(comp, -1.0F, 1.0F) * COMPONENT_RANGE) & 255); + } + + /** + * Unpacks the x-component of the packed normal, denormalizing it to a float in the range of -1.0..1.0. + * @param norm The packed normal + */ + public static float unpackX(int norm) { + return ((byte) ((norm >> X_COMPONENT_OFFSET) & 0xFF)) * NORM; + } + + /** + * Unpacks the y-component of the packed normal, denormalizing it to a float in the range of -1.0..1.0. + * @param norm The packed normal + */ + public static float unpackY(int norm) { + return ((byte) ((norm >> Y_COMPONENT_OFFSET) & 0xFF)) * NORM; + } + + /** + * Unpacks the z-component of the packed normal, denormalizing it to a float in the range of -1.0..1.0. + * @param norm The packed normal + */ + public static float unpackZ(int norm) { + return ((byte) ((norm >> Z_COMPONENT_OFFSET) & 0xFF)) * NORM; + } + + /** + * Unpacks the w-component of the packed normal, denormalizing it to a float in the range of -1.0..1.0. + * @param norm The packed normal + */ + public static float unpackW(int norm) { + return ((byte) ((norm >> W_COMPONENT_OFFSET) & 0xFF)) * NORM; + } +} diff --git a/src/main/java/net/coderbot/iris/vertices/NormalHelper.java b/src/main/java/net/coderbot/iris/vertices/NormalHelper.java index 875bb35dac..c01f0e7be2 100644 --- a/src/main/java/net/coderbot/iris/vertices/NormalHelper.java +++ b/src/main/java/net/coderbot/iris/vertices/NormalHelper.java @@ -23,20 +23,6 @@ public abstract class NormalHelper { private NormalHelper() { } - /** - * Stores a normal plus an extra value as a quartet of signed bytes. - * This is the same normal format that vanilla item rendering expects. - * The extra value is for use by shaders. - */ - public static int packNormal(float x, float y, float z, float w) { - x = Mth.clamp(x, -1, 1); - y = Mth.clamp(y, -1, 1); - z = Mth.clamp(z, -1, 1); - w = Mth.clamp(w, -1, 1); - - return ((int) (x * 127) & 0xFF) | (((int) (y * 127) & 0xFF) << 8) | (((int) (z * 127) & 0xFF) << 16) | (((int) (w * 127) & 0xFF) << 24); - } - public static int invertPackedNormal(int packed) { int ix = -(packed & 255); int iy = -((packed >> 8) & 255); @@ -49,22 +35,6 @@ public static int invertPackedNormal(int packed) { return (packed & 0xFF000000) | (iz << 16) | (iy << 8) | ix; } - /** - * Version of {@link #packNormal(float, float, float, float)} that accepts a vector type. - */ - public static int packNormal(Vector3f normal, float w) { - return packNormal(normal.x, normal.y, normal.z, w); - } - - /** - * Retrieves values packed by {@link #packNormal(float, float, float, float)}. - * - *

Components are x, y, z, w - zero based. - */ - public static float getPackedNormalComponent(int packedNormal, int component) { - return ((byte) (packedNormal >> (8 * component))) / 127f; - } - /** * Computes the face normal of the given quad and saves it in the provided non-null vector. * @@ -164,6 +134,116 @@ public static void computeFaceNormalTri(@NotNull Vector3f saveTo, TriView t) { saveTo.set(normX, normY, normZ); } + public static int computeTangentSmooth(float normalX, float normalY, float normalZ, TriView t) { + // Capture all of the relevant vertex positions + float x0 = t.x(0); + float y0 = t.y(0); + float z0 = t.z(0); + + float x1 = t.x(1); + float y1 = t.y(1); + float z1 = t.z(1); + + float x2 = t.x(2); + float y2 = t.y(2); + float z2 = t.z(2); + + // Project all vertices onto normal plane (for smooth normal support). Optionally skip this step for flat shading. + // Procedure: + // project v onto normal + // offset v by the projection to get the point on the plane + // project x0, y0, z0 onto normal + float d0 = x0 * normalX + y0 * normalY + z0 * normalZ; + float d1 = x1 * normalX + y1 * normalY + z1 * normalZ; + float d2 = x2 * normalX + y2 * normalY + z2 * normalZ; + + // offset x, y, z by the projection to get the projected point on the normal plane + x0 -= d0 * normalX; + y0 -= d0 * normalY; + z0 -= d0 * normalZ; + + x1 -= d1 * normalX; + y1 -= d1 * normalY; + z1 -= d1 * normalZ; + + x2 -= d2 * normalX; + y2 -= d2 * normalY; + z2 -= d2 * normalZ; + + + float edge1x = x1 - x0; + float edge1y = y1 - y0; + float edge1z = z1 - z0; + + float edge2x = x2 - x0; + float edge2y = y2 - y0; + float edge2z = z2 - z0; + + float u0 = t.u(0); + float v0 = t.v(0); + + float u1 = t.u(1); + float v1 = t.v(1); + + float u2 = t.u(2); + float v2 = t.v(2); + + float deltaU1 = u1 - u0; + float deltaV1 = v1 - v0; + float deltaU2 = u2 - u0; + float deltaV2 = v2 - v0; + + float fdenom = deltaU1 * deltaV2 - deltaU2 * deltaV1; + float f; + + if (fdenom == 0.0) { + f = 1.0f; + } else { + f = 1.0f / fdenom; + } + + float tangentx = f * (deltaV2 * edge1x - deltaV1 * edge2x); + float tangenty = f * (deltaV2 * edge1y - deltaV1 * edge2y); + float tangentz = f * (deltaV2 * edge1z - deltaV1 * edge2z); + float tcoeff = rsqrt(tangentx * tangentx + tangenty * tangenty + tangentz * tangentz); + tangentx *= tcoeff; + tangenty *= tcoeff; + tangentz *= tcoeff; + + float bitangentx = f * (-deltaU2 * edge1x + deltaU1 * edge2x); + float bitangenty = f * (-deltaU2 * edge1y + deltaU1 * edge2y); + float bitangentz = f * (-deltaU2 * edge1z + deltaU1 * edge2z); + float bitcoeff = rsqrt(bitangentx * bitangentx + bitangenty * bitangenty + bitangentz * bitangentz); + bitangentx *= bitcoeff; + bitangenty *= bitcoeff; + bitangentz *= bitcoeff; + + // predicted bitangent = tangent × normal + // Compute the determinant of the following matrix to get the cross product + // i j k + // tx ty tz + // nx ny nz + + // Be very careful when writing out complex multi-step calculations + // such as vector cross products! The calculation for pbitangentz + // used to be broken because it multiplied values in the wrong order. + + float pbitangentx = tangenty * normalZ - tangentz * normalY; + float pbitangenty = tangentz * normalX - tangentx * normalZ; + float pbitangentz = tangentx * normalY - tangenty * normalX; + + float dot = (bitangentx * pbitangentx) + (bitangenty * pbitangenty) + (bitangentz * pbitangentz); + float tangentW; + + if (dot < 0) { + tangentW = -1.0F; + } else { + tangentW = 1.0F; + } + + return NormI8.pack(tangentx, tangenty, tangentz, tangentW); + } + public static int computeTangent(float normalX, float normalY, float normalZ, TriView t) { // Capture all of the relevant vertex positions float x0 = t.x(0); @@ -248,7 +328,7 @@ public static int computeTangent(float normalX, float normalY, float normalZ, Tr tangentW = 1.0F; } - return packNormal(tangentx, tangenty, tangentz, tangentW); + return NormI8.pack(tangentx, tangenty, tangentz, tangentW); } private static float rsqrt(float value) { diff --git a/src/main/java/net/irisshaders/iris/api/v0/IrisApi.java b/src/main/java/net/irisshaders/iris/api/v0/IrisApi.java index ceba45ece6..4d294265b7 100644 --- a/src/main/java/net/irisshaders/iris/api/v0/IrisApi.java +++ b/src/main/java/net/irisshaders/iris/api/v0/IrisApi.java @@ -25,7 +25,7 @@ static IrisApi getInstance() { * if they wish to check whether given API calls are available on * the currently installed Iris version. * - * @return The current minor revision. Currently, revision 1. + * @return The current minor revision. Currently, revision 2. */ int getMinorApiRevision(); @@ -105,4 +105,12 @@ static IrisApi getInstance() { * @since API 0.1 */ IrisTextVertexSink createTextVertexSink(int maxQuadCount, IntFunction bufferProvider); + + /** + * Gets the sun path rotation used by the current shader pack. + * + * @return The sun path rotation as specified by the shader pack, or 0 if no shader pack is in use. + * @since API v0.2 + */ + float getSunPathRotation(); } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index a39b930849..5625433d87 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -1,3 +1,4 @@ +public com.mojang.blaze3d.platform.GlStateManager$BooleanState public com.mojang.blaze3d.platform.GlStateManager$BlendState public com.mojang.blaze3d.platform.GlStateManager$TextureState public com.mojang.blaze3d.platform.GlStateManager$ColorMask @@ -16,4 +17,4 @@ public-f net.minecraft.client.renderer.ShaderInstance f_173320_ # CHUNK_OFFSET public-f net.minecraft.client.renderer.ShaderInstance f_173312_ # COLOR_MODULATOR public net.minecraft.client.renderer.ShaderInstance f_173331_ # uniforms public-f net.minecraft.client.renderer.LevelRenderer f_109464_ # renderBuffers -public com.mojang.blaze3d.platform.NativeImage f_84964_ # pixels \ No newline at end of file +public com.mojang.blaze3d.platform.NativeImage f_84964_ # pixels diff --git a/src/main/resources/assets/iris/lang/cs_cz.json b/src/main/resources/assets/iris/lang/cs_cz.json index 234f1bdbbb..512cd2f574 100644 --- a/src/main/resources/assets/iris/lang/cs_cz.json +++ b/src/main/resources/assets/iris/lang/cs_cz.json @@ -8,9 +8,9 @@ "iris.shaders.reloaded.failure": "NepodaÅ™ilo se znovu naÄíst shadery! Důvod: %s", "iris.shaders.toggled.failure": "NepodaÅ™ilo se pÅ™epnout shadery! Důvod: %s", "iris.sodium.failure.title": "NepodaÅ™ilo se naÄíst Oculus!", - "iris.sodium.failure.download": "Stáhnout Rubidium", - "iris.sodium.failure.reason.notFound": "Pro dobrý výkon vyžaduje Oculus modifikaci Rubidium, která ale není nainstalovaná. StáhnÄ›te si prosím Rubidium, vložte jej do vaší složky mods a restartujte hru.", - "iris.sodium.failure.reason.incompatible": "Pro dobrý výkon vyžaduje Oculus modifikaci Rubidium, ale byla nalezena její nekompatibilní verze. StáhnÄ›te si prosím správnou verzi Sodia, vložte jej do vaší složky mods, odeberte nesprávnou verzi a restartujte hru.", + "iris.sodium.failure.download": "Stáhnout Embeddium", + "iris.sodium.failure.reason.notFound": "Pro dobrý výkon vyžaduje Oculus modifikaci Embeddium, která ale není nainstalovaná. StáhnÄ›te si prosím Embeddium, vložte jej do vaší složky mods a restartujte hru.", + "iris.sodium.failure.reason.incompatible": "Pro dobrý výkon vyžaduje Oculus modifikaci Embeddium, ale byla nalezena její nekompatibilní verze. StáhnÄ›te si prosím správnou verzi Sodia, vložte jej do vaší složky mods, odeberte nesprávnou verzi a restartujte hru.", "options.iris.apply": "Použít", "options.iris.refresh": "Obnovit", diff --git a/src/main/resources/assets/iris/lang/de_ch.json b/src/main/resources/assets/iris/lang/de_ch.json index a000cbbc62..dde6b03a9c 100644 --- a/src/main/resources/assets/iris/lang/de_ch.json +++ b/src/main/resources/assets/iris/lang/de_ch.json @@ -4,7 +4,7 @@ "iris.keybind.reload": "Shaders neu lade", "iris.keybind.shaderPackSelection": "Shaderpack uswähle", "iris.keybind.toggleShaders": "Shaders i/uschalte", - "iris.keybinds": "Iris", + "iris.keybinds": "Oculus", "iris.shaders.reloaded.failure": "Shader neu lade hed ned funktioniert! Grund: %s", "iris.shaders.toggled.failure": "Shader i/uschalte hed ned funktioniert! Grund: %s", diff --git a/src/main/resources/assets/iris/lang/de_de.json b/src/main/resources/assets/iris/lang/de_de.json index 2a35d1aa97..b780c2172d 100644 --- a/src/main/resources/assets/iris/lang/de_de.json +++ b/src/main/resources/assets/iris/lang/de_de.json @@ -2,41 +2,41 @@ "iris.shaders.reloaded": "Shader neu geladen!", "iris.shaders.disabled": "Shader deaktiviert!", "iris.shaders.toggled": "Shader umgeschaltet auf: %s!", - + "iris.shaders.debug.enabled": "Debugging wurde aktiviert, die Debug-Protokollierung wird ausführlicher sein!", "iris.shaders.debug.disabled": "Debugging wurde deaktiviert.", "iris.shaders.debug.failure": "Debugging kann nicht aktiviert werden, da dieser Computer keine Debug-Funktionen unterstützt.", "iris.shaders.debug.restart": "Es liegt kein Debug-Kontext vor, starte bitte neu, um Debugging zu aktivieren.", - + "iris.keybind.reload": "Shader neu laden", "iris.keybind.shaderPackSelection": "Shader-Auswahlbildschirm", "iris.keybind.toggleShaders": "Shader umschalten", "iris.keybinds": "Oculus", - + "iris.shaders.reloaded.failure": "Shader konnte nicht neu geladen werden! Grund: %s", "iris.shaders.toggled.failure": "Shader konnte nicht umgeschaltet werden! Grund: %s", - + "iris.sodium.failure.title": "Oculus konnte nicht geladen werden!", - "iris.sodium.failure.download": "Rubidium herunterladen", - "iris.sodium.failure.reason.notFound": "Oculus erfordert Rubidium für optimale Leistung, aber Rubidium ist nicht installiert. Bitte lade Rubidium herunter, füge es deinem Mods-Ordner hinzu und starte das Spiel neu.", - "iris.sodium.failure.reason.incompatible": "Oculus erfordert Rubidium für optimale Leistung, aber es wurde eine inkompatible Version gefunden. Bitte lade die passende Version von Rubidium herunter, füge sie deinem Mods-Ordner hinzu, entferne die falsche Version und starte das Spiel neu.", - + "iris.sodium.failure.download": "Sodium herunterladen", + "iris.sodium.failure.reason.notFound": "Oculus erfordert Sodium für optimale Leistung, aber Sodium ist nicht installiert. Bitte lade Sodium herunter, füge es deinem Mods-Ordner hinzu und starte das Spiel neu.", + "iris.sodium.failure.reason.incompatible": "Oculus erfordert Sodium für optimale Leistung, aber es wurde eine inkompatible Version gefunden. Bitte lade die passende Version von Sodium herunter, füge sie deinem Mods-Ordner hinzu, entferne die falsche Version und starte das Spiel neu.", + "iris.nec.failure.title": "[%s] Not Enough Crashes erkannt!", - "iris.nec.failure.description": "Not Enough Crashes kann das Spiel bei der Behandlung von Abstürzen stark beeinträchtigen und liefert keine genauen Ergebnisse.\nGute Alternativen sind MixinTrace und Crafty Crashes, die die Ursache eines Absturzes zuverlässiger identifizieren können und das Spiel nicht in einen fehlerhaften Zustand versetzen.", - + "iris.nec.failure.description": "Not Enough Crashes kann das Spiel bei der Behandlung von Abstürzen stark beeinträchtigen und liefert keine genauen Ergebnisse.\nGute Alternativen sind MixinTrace, die die Ursache eines Absturzes zuverlässiger identifizieren können und das Spiel nicht in einen fehlerhaften Zustand versetzen.", + "iris.unsupported.irisorpc": "Oculus oder diesem Computer", "iris.unsupported.iris": "Oculus", "iris.unsupported.pc": "diesem Computer", "iris.unsupported.pack": "Shaderpaket inkompatibel!", "iris.unsupported.pack.description": "Dieses Shaderpaket enthält Funktionen, die von %s nicht unterstützt werden%s Bitte versuche ein anderes Paket.", - + "options.iris.apply": "Anwenden", "options.iris.refresh": "Aktualisieren", "options.iris.openShaderPackFolder": "Shader-Ordner öffnen ...", "options.iris.shaderPackSettings": "Shader-Einstellungen ...", "options.iris.shaderPackList": "Shader-Liste ...", "options.iris.refreshShaderPacks": "Shader/Liste aktualisieren", - + "options.iris.shaderPackSelection": "Shaderpakete ...", "options.iris.shaderPackSelection.title": "Shaderpakete", "options.iris.shaderPackSelection.addedPack": "Shaderpaket \"%s\" hinzugefügt", @@ -45,36 +45,36 @@ "options.iris.shaderPackSelection.failedAddSingle": "\"%s\" ist kein zulässiges Shaderpaket", "options.iris.shaderPackSelection.copyError": "Konnte Shaderpaket \"%s\" nicht hinzufügen", "options.iris.shaderPackSelection.copyErrorAlreadyExists": "\"%s\" befindet sich bereits im Shader-Ordner!", - + "options.iris.shaderPackOptions.tooManyFiles": "Es können nicht mehrere Shader-Einstellungsdateien importiert werden!", "options.iris.shaderPackOptions.failedImport": "Shader-Einstellungsdatei \"%s\" konnte nicht importiert werden", "options.iris.shaderPackOptions.importedSettings": "Shader-Einstellungen aus \"%s\" importiert", - + "options.iris.shaders.disabled": "Shader: Deaktiviert", "options.iris.shaders.enabled": "Shader: Aktiviert", "options.iris.shaders.nonePresent": "Shader: Keine vorhanden", - + "options.iris.back": "Zurück", "options.iris.reset": "Zurücksetzen", "options.iris.reset.tooltip": "ALLE Einstellungen zurücksetzen und anwenden?", "options.iris.reset.tooltip.holdShift": "Zum Zurücksetzen UMSCHALTEN/SHIFT gedrückt halten und klicken", - + "options.iris.importSettings.tooltip": "Einstellungen aus Datei importieren", "options.iris.exportSettings.tooltip": "Angewandte Einstellungen in eine Datei exportieren", "options.iris.mustDisableFullscreen": "Bitte deaktiviere zuerst den Vollbildmodus!", "options.iris.setToDefault": "Diese Einstellung auf den Standardwert zurücksetzen?", - + "options.iris.profile": "Profil", "options.iris.profile.custom": "Benutzerdefiniert", - + "options.iris.shadowDistance": "Max. Schattendistanz", "options.iris.shadowDistance.enabled": "Erlaubt es dir, die maximale Distanz für Schatten zu ändern. Gelände und Objekte, die weiter entfernt sind als die eingestellte Distanz, werden keine Schatten werfen. Das Senken der Distanz kann die Leistung erheblich verbessern.", "options.iris.shadowDistance.disabled": "Dein aktuelles Shaderpaket hat bereits eine Distanz für Schatten gesetzt; du kannst sie nicht ändern.", "options.iris.shadowDistance.sodium_tooltip": "Die Distanz für Schatten bestimmt, wie weit das Gelände entfernt sein darf, um keinen Schatten mehr zu werfen. Bei geringeren Distanzen werden weniger Schatten berechnet, was die Bildrate verbessert. Diese Option kann nicht geändert werden bei Paketen, die explizit eine Distanz für Schatten vorgeben. Die tatsächliche Distanz für Schatten wird von der Einstellung \"Sichtweite\" begrenzt.", - + "options.iris.gui.hide": "GUI ausblenden", "options.iris.gui.show": "GUI anzeigen", - + "pack.iris.select.title": "Auswählen", "pack.iris.configure.title": "Konfigurieren", "pack.iris.list.label": "+ Um Shader hinzuzufügen, ziehe sie in dieses Fenster hinein", diff --git a/src/main/resources/assets/iris/lang/en_pt.json b/src/main/resources/assets/iris/lang/en_pt.json index adf301d888..df2e2ccac7 100644 --- a/src/main/resources/assets/iris/lang/en_pt.json +++ b/src/main/resources/assets/iris/lang/en_pt.json @@ -8,7 +8,7 @@ "iris.shaders.reloaded.failure": "Failed to clean ye Glass eyes! Reason: %s", "iris.shaders.toggled.failure": "Failed to place ye Glass eyes back in! Reason: %s", "iris.sodium.failure.title": "Oculus failed to load!", - "iris.sodium.failure.reason": "Yee 'ave Rubidium in yer mods folder, however Oculus includes it. Please close the game 'n remove Rubidium from yer mods Coffer.", + "iris.sodium.failure.reason": "Yee 'ave Embeddium in yer mods folder, however Oculus includes it. Please close the game 'n remove Embeddium from yer mods Coffer.", "options.iris.apply": "Apply", "options.iris.refresh": "Refresh", @@ -30,7 +30,7 @@ "pack.iris.select.title": "Select", "pack.iris.list.label": "+ Drop yer Glass eye files in this ole window t' add yer Glass eyes", - "iris.sodium.failure.download": "Download Rubidium", - "iris.sodium.failure.reason.notFound": "Oculus needs e' Rubidium for smooth sailin', but Rubidium ain't found. Find the Rubidium, add it to t'mods, and open the game.", - "iris.sodium.failure.reason.incompatible": "Oculus needs e' Rubidium for smooth sailin', but the one here ain't it. Find t'correct Rubidium, add it to t'mods, throw overboard t'old one, and open the game." + "iris.sodium.failure.download": "Download Embeddium", + "iris.sodium.failure.reason.notFound": "Oculus needs e' Embeddium for smooth sailin', but Embeddium ain't found. Find the Embeddium, add it to t'mods, and open the game.", + "iris.sodium.failure.reason.incompatible": "Oculus needs e' Embeddium for smooth sailin', but the one here ain't it. Find t'correct Embeddium, add it to t'mods, throw overboard t'old one, and open the game." } diff --git a/src/main/resources/assets/iris/lang/en_ud.json b/src/main/resources/assets/iris/lang/en_ud.json index c6d2c3b8fe..91a95e11f3 100644 --- a/src/main/resources/assets/iris/lang/en_ud.json +++ b/src/main/resources/assets/iris/lang/en_ud.json @@ -13,7 +13,7 @@ "iris.shaders.reloaded.failure": "%s :uosÉÇá´š ¡sɹÇpÉÉ¥s pÉoןÇɹ oʇ pÇןᴉÉℲ", "iris.shaders.toggled.failure": "%s :uosÉÇá´š ¡sɹÇpÉÉ¥s Çןƃƃoʇ oʇ pÇןᴉÉℲ", "iris.sodium.failure.title": "¡pÉoן oʇ pÇןᴉÉÉŸ snlnÉ”o", - "iris.sodium.failure.download": "Download Rubidium", + "iris.sodium.failure.download": "Download Embeddium", "iris.sodium.failure.reason.notFound": "Ë™ÇɯÉƃ Çɥʇ ɥɔunÉן-Çɹ puÉ Â´É¹ÇpןoÉŸ spoɯ ɹnoÊŽ uá´‰ ʇᴉ ÇÉ”Éןd ´ɯnıpıqnɹ pÉoןuÊop ÇsÉÇןԀ Ë™pÇןןÉʇsuá´‰ ʇou sá´‰ ɯnıpıqnɹ ʇnq ´ÇÉ”uÉɯɹoɟɹÇd pooƃ ɹoÉŸ ɯnıpıqnɹ sÇɹᴉnbÇɹ snlnÉ”o", "iris.sodium.failure.reason.incompatible": "Ë™ÇɯÉƃ Çɥʇ ɥɔunÉן-Çɹ puÉ Â´uoá´‰sɹÇÊŒ ʇɔÇɹɹoÉ”uá´‰ Çɥʇ ÇÊŒoɯÇɹ ´ɹÇpןoÉŸ spoɯ ɹnoÊŽ uá´‰ ʇᴉ ÇÉ”Éןd ´ɯnıpıqnɹ ÉŸo uoá´‰sɹÇÊŒ ʇɔÇɹɹoÉ” Çɥʇ pÉoןuÊop ÇsÉÇןԀ Ë™punoÉŸ sÉÊ uoá´‰sɹÇÊŒ ÇןqᴉʇÉdɯoÉ”uá´‰ uÉ Ê‡nq ´ÇÉ”uÉɯɹoɟɹÇd pooƃ ɹoÉŸ ɯnıpıqnɹ sÇɹᴉnbÇɹ snlnÉ”o", diff --git a/src/main/resources/assets/iris/lang/en_us.json b/src/main/resources/assets/iris/lang/en_us.json index 30da582dd7..7cb4631398 100644 --- a/src/main/resources/assets/iris/lang/en_us.json +++ b/src/main/resources/assets/iris/lang/en_us.json @@ -5,24 +5,27 @@ "iris.shaders.debug.enabled": "Debugging has been enabled, debug logging will be more verbose!", "iris.shaders.debug.disabled": "Debugging has been disabled.", "iris.shaders.debug.failure": "Cannot enable debugging, your computer does not support debug features.", - "iris.shaders.debug.restart": "You do not have a debug context, please restart to enable OpenGL client debugging.", + "iris.shaders.debug.restart": "You do not have a debug context, please restart to enable debugging.", + "iris.shaders.ssbofailure": "The shader requested a specific feature (SSBO) that is not supported by your GPU, it may not work correctly.", "iris.keybind.reload": "Reload Shaders", "iris.keybind.shaderPackSelection": "Shaderpack Selection Screen", + "iris.keybind.wireframe": "Wireframe (SP only)", "iris.keybind.toggleShaders": "Toggle Shaders", "iris.keybinds": "Oculus", "iris.shaders.reloaded.failure": "Failed to reload shaders! Reason: %s", "iris.shaders.toggled.failure": "Failed to toggle shaders! Reason: %s", "iris.sodium.failure.title": "Oculus failed to load!", - "iris.sodium.failure.download": "Download Rubidium", - "iris.sodium.failure.reason.notFound": "Oculus requires Rubidium for good performance, but Rubidium is not installed. Please download Rubidium, place it in your mods folder, and re-launch the game.", - "iris.sodium.failure.reason.incompatible": "Oculus requires Rubidium for good performance, but an incompatible version was found. Please download the correct version of Rubidium, place it in your mods folder, remove the incorrect version, and re-launch the game.", + "iris.sodium.failure.download": "Download Sodium", + "iris.sodium.failure.reason.notFound": "Oculus requires Sodium for good performance, but Sodium is not installed. Please download Sodium, place it in your mods folder, and re-launch the game.", + "iris.sodium.failure.reason.incompatible": "Oculus requires Sodium for good performance, but an incompatible version was found. Please download the correct version of Sodium, place it in your mods folder, remove the incorrect version, and re-launch the game.", "iris.nec.failure.title": "[%s] Not Enough Crashes detected!", - "iris.nec.failure.description": "Not Enough Crashes can severely break the game while handling crashes, and does not provide accurate results.\nGood alternatives are MixinTrace and Crafty Crashes, which can identify the cause of a crash more reliably and does not put the game in an invalid state.", + "iris.nec.failure.description": "Not Enough Crashes can severely break the game while handling crashes, and does not provide accurate results.\nA good alternative is MixinTrace, which can identify the cause of a crash more reliably and does not put the game in an invalid state.", "iris.unsupported.irisorpc": "Oculus or your PC", "iris.unsupported.iris": "Oculus", "iris.unsupported.pc": "your PC", "iris.unsupported.pack": "Shaderpack incompatible!", "iris.unsupported.pack.description": "The shaderpack you are trying to load contains features unsupported by %s. Please try another pack. List %s", + "iris.unsupported.pack.macos": "\nmacOS is known to have issues with many shader packs.", "options.iris.apply": "Apply", "options.iris.refresh": "Refresh", "options.iris.openShaderPackFolder": "Open Shader Pack Folder...", @@ -57,6 +60,8 @@ "options.iris.shadowDistance.enabled": "Allows you to change the maximum distance for shadows. Terrain and entities beyond this distance will not cast shadows. Lowering the shadow distance can significantly increase performance.", "options.iris.shadowDistance.disabled": "Your current shader pack has already set a render distance for shadows; you cannot change it.", "options.iris.shadowDistance.sodium_tooltip": "The shadow render distance controls how far away terrain can potentially be rendered in the shadow pass. Lower distances mean that less terrain will be rendered, improving frame rates. This option cannot be changed on packs which explicitly specify a shadow render distance. The actual shadow render distance is capped by the View Distance setting.", + "options.iris.colorSpace": "Color Space", + "options.iris.colorSpace.sodium_tooltip": "The color space to transform the screen to. Works on top of shader packs. Use SRGB if unsure.", "options.iris.gui.hide": "Hide GUI", "options.iris.gui.show": "Show GUI", diff --git a/src/main/resources/assets/iris/lang/es_ar.json b/src/main/resources/assets/iris/lang/es_ar.json new file mode 100644 index 0000000000..1259b7ac63 --- /dev/null +++ b/src/main/resources/assets/iris/lang/es_ar.json @@ -0,0 +1,68 @@ +{ + "iris.shaders.reloaded": "¡Shaders Recargados!", + "iris.shaders.disabled": "¡Shaders desactivados!", + "iris.shaders.toggled": "¡Shaders cambiados a %s!", + "iris.shaders.debug.enabled": "¡Se habilitó la depuración, el registro de depuración va a ser más detallado!", + "iris.shaders.debug.disabled": "La depuración se desactivó.", + "iris.shaders.debug.failure": "No se puede habilitar la depuración, tu computadora no admite funciones de depuración.", + "iris.shaders.debug.restart": "No tenés un contexto de depuración, por favor reiniciá para habilitar la depuración.", + "iris.keybind.reload": "Recargar Shaders", + "iris.keybind.shaderPackSelection": "Pantalla de Selección de Shaders", + "iris.keybind.toggleShaders": "Cambiar Shaders", + "iris.keybinds": "Oculus", + "iris.shaders.reloaded.failure": "¡Error al recargar los shaders! Razón: %s", + "iris.shaders.toggled.failure": "¡Error al activar los shaders! Razón: %s", + "iris.sodium.failure.title": "¡Oculus no se pudo cargar!", + "iris.sodium.failure.download": "Descargá Sodium", + "iris.sodium.failure.reason.notFound": "Oculus requiere de Sodium para un buen rendimiento, pero Sodium no está instalado. Por favor, descargá Sodium, colocalo en tu carpeta de mods y volvé a iniciar el juego.", + "iris.sodium.failure.reason.incompatible": "Oculus requiere de Sodium para un buen rendimiento, pero se encontró una versión incompatible. Por favor, descargá la versión correcta de Sodium, colocala en tu carpeta de mods, eliminá la versión incorrecta y volvé a iniciar el juego.", + "iris.nec.failure.title": "¡[%s] Not Enough Crashes detectado!", + "iris.nec.failure.description": "No es recomendable usar Not Enough Crashes porque puede romper el juego severamente al manejar los errores y no brindar resultados precisos.\nBuenas alternativas son MixinTrace y Crafty Crashes, que pueden identificar la causa de un error de manera más confiable y no dejan al juego en un estado inválido.", + "iris.unsupported.irisorpc": "Oculus o tu PC", + "iris.unsupported.iris": "Oculus", + "iris.unsupported.pc": "tu PC", + "iris.unsupported.pack": "¡Shader incompatible!", + "iris.unsupported.pack.description": "El shaderpack que estás intentando cargar contiene características no soportadas por %s. Por favor, probá con otro pack. Lista %s", + "options.iris.apply": "Aplicar", + "options.iris.refresh": "Recargar", + "options.iris.openShaderPackFolder": "Abrir carpeta de Shader Packs...", + "options.iris.shaderPackSettings": "Configuración del Shader Pack...", + "options.iris.shaderPackList": "Lista de Shader Packs...", + "options.iris.refreshShaderPacks": "Refresh Shader Packs", + "options.iris.shaderPackSelection": "Shader Packs...", + "options.iris.shaderPackSelection.title": "Shader Packs", + "options.iris.shaderPackSelection.addedPack": "Se agregó el Shader Pack \"%s\"", + "options.iris.shaderPackSelection.addedPacks": "Se agregaron %s Shader Packs", + "options.iris.shaderPackSelection.failedAdd": "Los archivos no eran Shader Packs válidos", + "options.iris.shaderPackSelection.failedAddSingle": "\"%s\" no es un Shader Pack válido", + "options.iris.shaderPackSelection.copyError": "No se pudo agregar el Shader Pack \"%s\"", + "options.iris.shaderPackSelection.copyErrorAlreadyExists": "¡\"%s\" ya está en tu carpeta de Shader Packs!", + "options.iris.shaderPackOptions.tooManyFiles": "¡No se pueden importar varios archivos de configuración de Shaders!", + "options.iris.shaderPackOptions.failedImport": "Error al importar el archivo de configuración de Shaders \"%s\"", + "options.iris.shaderPackOptions.importedSettings": "Se importaron las configuraciones del Shader desde \"%s\"", + "options.iris.shaders.disabled": "Shaders: Desactivados", + "options.iris.shaders.enabled": "Shaders: Activados", + "options.iris.shaders.nonePresent": "Shaders: No hay Packs", + "options.iris.back": "Volver", + "options.iris.reset": "Reinciar", + "options.iris.reset.tooltip": "¿Restablecer TODAS las opciones y aplicar?", + "options.iris.reset.tooltip.holdShift": "Mantené presionado SHIFT y hacé clic para restablecer", + "options.iris.importSettings.tooltip": "Importar configuración desde un archivo", + "options.iris.exportSettings.tooltip": "Exportar la configuración aplicada a un archivo", + "options.iris.mustDisableFullscreen": "¡Por favor, desactivá la pantalla completa primero!", + "options.iris.setToDefault": "¿Establecer la opción al valor por defecto?", + "options.iris.profile": "Perfil", + "options.iris.profile.custom": "Personalizado", + "options.iris.shadowDistance": "Distancia máxima de sombras", + "options.iris.shadowDistance.enabled": "Permite cambiar la distancia máxima para las sombras. El terreno y las entidades más allá de esta distancia no proyectarán sombras. Reducir la distancia de las sombras puede mejorar significativamente el rendimiento.", + "options.iris.shadowDistance.disabled": "Tu paquete de shaders actual ya estableció una distancia de renderizado para las sombras; no podés cambiarla.", + "options.iris.gui.hide": "Esconder GUI", + "options.iris.gui.show": "Mostrar GUI", + + "pack.iris.select.title": "Seleccionar", + "pack.iris.configure.title": "Configurar", + "pack.iris.list.label": "+ Arrastrá y soltá Shader Packs para agregar", + + "label.iris.true": "Activado", + "label.iris.false": "Desactivado" +} diff --git a/src/main/resources/assets/iris/lang/es_es.json b/src/main/resources/assets/iris/lang/es_es.json index ac92b8f5a4..08fe03dc19 100644 --- a/src/main/resources/assets/iris/lang/es_es.json +++ b/src/main/resources/assets/iris/lang/es_es.json @@ -14,9 +14,9 @@ "iris.shaders.toggled.failure": "¡Error al activar shaders! Razón: %s", "iris.sodium.failure.title": "¡Oculus no pudo iniciarse!", - "iris.sodium.failure.download": "Descarga Rubidium", - "iris.sodium.failure.reason.notFound": "Oculus necesita Rubidium para obtener un buen rendimiento, pero no está instalado. Por favor descarga Rubidium, ponlo en tu carpeta de mods, y arranca el juego de nuevo.", - "iris.sodium.failure.reason.incompatible": "Oculus necesita Rubidium para obtener un buen rendimiento, pero se encontró una versión incompatible. Por favor descarga la versión correcta de Rubidium, ponla en tu carpeta de mods, quita la versión incorrecta, y arranca el juego de nuevo.", + "iris.sodium.failure.download": "Descarga Embeddium", + "iris.sodium.failure.reason.notFound": "Oculus necesita Embeddium para obtener un buen rendimiento, pero no está instalado. Por favor descarga Embeddium, ponlo en tu carpeta de mods, y arranca el juego de nuevo.", + "iris.sodium.failure.reason.incompatible": "Oculus necesita Embeddium para obtener un buen rendimiento, pero se encontró una versión incompatible. Por favor descarga la versión correcta de Embeddium, ponla en tu carpeta de mods, quita la versión incorrecta, y arranca el juego de nuevo.", "iris.unsupported.irisorpc": "Oculus o tu PC", "iris.unsupported.iris": "Oculus", "iris.unsupported.pc": "tu PC", diff --git a/src/main/resources/assets/iris/lang/et_ee.json b/src/main/resources/assets/iris/lang/et_ee.json index 9efb93d814..52dfee2ec2 100644 --- a/src/main/resources/assets/iris/lang/et_ee.json +++ b/src/main/resources/assets/iris/lang/et_ee.json @@ -6,17 +6,25 @@ "iris.shaders.debug.disabled": "Silumine on nüüd keelatud.", "iris.shaders.debug.failure": "Silumist ei saa lubada, sinu arvuti ei toeta silumisfunktsioone.", "iris.shaders.debug.restart": "Sul puudub silumiskontekst, silumiseks palun taaskäivita.", + "iris.shaders.ssbofailure": "Varjutaja taotles konkreetset funktsiooni (SSBO), mis ei ole sinu videokaardi poolt toetatud, see ei pruugi korrektselt töötada.", "iris.keybind.reload": "Laadi varjutajad uuesti", "iris.keybind.shaderPackSelection": "Varjutajapaki valikukuva", "iris.keybind.toggleShaders": "Lülita varjutajad sisse/välja", "iris.keybinds": "Oculus", "iris.shaders.reloaded.failure": "Varjutajate taaslaadimine ebaõnnestus! Põhjus: %s", "iris.shaders.toggled.failure": "Varjutajate lülitamine ebaõnnestus! Põhjus: %s", - "iris.sodium.failure.title": "Irise laadimine ebaõnnestus!", - "iris.sodium.failure.download": "Laadi Rubidium alla", - "iris.sodium.failure.reason.notFound": "Oculus vajab hea jõudluse saavutamiseks Rubidiumi, ent Rubidium ei ole paigaldatud. Palun laadi Rubidium alla, aseta see oma mods kausta ning taaskäivita mäng.", - "iris.sodium.failure.reason.incompatible": "Oculus vajab hea jõudluse saavutamiseks Rubidiumi, ent leiti ühildumatu Rubidiumi versioon. Palun laadi sobiv Rubidiumi versioon alla, aseta see oma mods kausta, kustuta sobimatu versioon ning taaskäivita mäng.", - + "iris.sodium.failure.title": "Oculuse laadimine ebaõnnestus!", + "iris.sodium.failure.download": "Laadi Sodium alla", + "iris.sodium.failure.reason.notFound": "Oculus vajab hea jõudluse saavutamiseks Sodiumi, ent Sodium ei ole paigaldatud. Palun laadi Sodium alla, aseta see oma mods kausta ning taaskäivita mäng.", + "iris.sodium.failure.reason.incompatible": "Oculus vajab hea jõudluse saavutamiseks Sodiumi, ent leiti ühildumatu versioon. Palun laadi sobiv Sodiumi versioon alla, aseta see oma mods kausta, kustuta sobimatu versioon ning taaskäivita mäng.", + "iris.nec.failure.title": "[%s] Tuvastati Not Enough Crashes!", + "iris.nec.failure.description": "Not Enough Crashes võib krahhide käsitlemisel mängu tõsiselt lõhkuda ning ei anna täpseid tulemusi.\nHead alternatiivid on MixinTrace, mis suudavad krahhi põhjuse usaldusväärsemalt tuvastada ja ei aseta mängu vigasesse olekusse.", + "iris.unsupported.irisorpc": "Oculus või sinu arvuti", + "iris.unsupported.iris": "Oculus", + "iris.unsupported.pc": "sinu arvuti", + "iris.unsupported.pack": "Varjutajapakk ühildumatu!", + "iris.unsupported.pack.description": "Varjutajapakk, mida proovid laadida, sisaldab funktsioone, mida %s ei toeta. Palun proovi teist pakki. Loetelu %s", + "iris.unsupported.pack.macos": "\nmacOSil on teadaolevalt probleeme paljude varjutajapakkidega.", "options.iris.apply": "Rakenda", "options.iris.refresh": "Värskenda", "options.iris.openShaderPackFolder": "Ava varjutajapakkide kaust...", @@ -43,13 +51,17 @@ "options.iris.reset.tooltip.holdShift": "Lähtestamiseks hoia Shifti ja klõpsa", "options.iris.importSettings.tooltip": "Impordi seadistused failist", "options.iris.exportSettings.tooltip": "Ekspordi rakendatud seadistused faili", + "options.iris.mustDisableFullscreen": "Palun keela enne täisekraanirežiim!", "options.iris.setToDefault": "Seadistad valiku vaikeväärtusele?", "options.iris.profile": "Profiil", "options.iris.profile.custom": "Kohandatud", "options.iris.shadowDistance": "Maks. varjukaugus", "options.iris.shadowDistance.enabled": "Võimaldab muuta varjude maksimaalset kaugust. Sellest kaugem maastik ning olemid ei heida varjusid. Varjukauguse vähendamine võib jõudlust märkimisväärselt suurendada.", "options.iris.shadowDistance.disabled": "Sinu praegune varjutajapakk on varjude nähtavuskauguse juba seadnud, sa ei saa seda muuta.", - + "options.iris.shadowDistance.sodium_tooltip": "Varjude nähtavuskaugus määrab, kui kaugel olevat maastikku saab varjutuskäigul renderdada. Väiksemad kaugused tähendavad vähema maastiku renderdamist, mis parandab kaadrisagedust. Seda valikut ei saa muuta pakkide puhul, mis määravad varjude nähtavuskauguse ise. Tegelik varjude nähtavuskaugus on piiratud nähtavuskauguse valikuga.", + "options.iris.gui.hide": "Peida liides", + "options.iris.gui.show": "Kuva liides", + "pack.iris.select.title": "Vali", "pack.iris.configure.title": "Seadista", "pack.iris.list.label": "+ Varjutajapakkide lisamiseks sikuta need siia", diff --git a/src/main/resources/assets/iris/lang/fa_ir.json b/src/main/resources/assets/iris/lang/fa_ir.json index 8111786f1b..dd4f5e5806 100644 --- a/src/main/resources/assets/iris/lang/fa_ir.json +++ b/src/main/resources/assets/iris/lang/fa_ir.json @@ -4,7 +4,7 @@ "iris.keybinds": "Oculus", "iris.shaders.reloaded.failure": "خطا در بارگیری مجدد shader ها ØŒ علت : %s", "iris.sodium.failure.title": "Oculus اشکال در بارگذاری", - "iris.sodium.failure.reason": "شما Rubidium پرونده اجرایی را در پوشه mods بازی خود دارید، اما Oculus پرونده اجرایی Rubidium را به همراه دارد،‌ لطÙا بازی را ببندید Ùˆ پرونده اجرایی Rubidium را از پوشه mods بازی حذ٠کنید.", + "iris.sodium.failure.reason": "شما Embeddium پرونده اجرایی را در پوشه mods بازی خود دارید، اما Oculus پرونده اجرایی Embeddium را به همراه دارد،‌ لطÙا بازی را ببندید Ùˆ پرونده اجرایی Embeddium را از پوشه mods بازی حذ٠کنید.", "options.iris.shadowDistance": "حداکثر Ùاصله سایه ها", "options.iris.shadowDistance.enabled": "به شما قابلیت تغییر میزان حداکثر Ùاصله سایه ها را می‌دهد. موجودات خارج از این Ùاصله هیچ سایه ای نمی‌اندازند. Ú©Ù… کردن این گزینه می‌تواند تاثیر زیادی در عملکرد بهتر بازی داشته باشد.", "options.iris.shadowDistance.disabled": "Shaderpack انتخابی شما میزان حداکثر Ùاصله سایه ها را تایین کرده است Ùˆ شما نمی توانید آن را تغییر دهد.", diff --git a/src/main/resources/assets/iris/lang/fi_fi.json b/src/main/resources/assets/iris/lang/fi_fi.json index c3200343fc..ac20dea808 100644 --- a/src/main/resources/assets/iris/lang/fi_fi.json +++ b/src/main/resources/assets/iris/lang/fi_fi.json @@ -13,10 +13,10 @@ "iris.shaders.reloaded.failure": "Shaderien lataus epäonnistui! Syy: %s", "iris.shaders.toggled.failure": "Shaderien käyttöönotto epäonnistui! Syy: %s", "iris.sodium.failure.title": "Iriksen lataus epäonnistui!", - "iris.sodium.failure.download": "Lataa Rubidium", - "iris.sodium.failure.reason.notFound": "Oculus vaatii Rubidiumin hyvän suorituskyvyn takaamiseksi, mutta Rubidiumia ei ole asennettu. Lataa Rubidium, laita se modit-kansioosi, ja käynnistä pelisi uudelleen.", - "iris.sodium.failure.reason.incompatible": "Oculus vaatii Rubidiumin hyvän suorituskyvyn takaamiseksi, mutta Rubidium versiosi on yhteensopimaton. Lataa yhteensopiva Rubidium versio, laita se modit-kansioosi ja poista yhteensopimaton versio, käynnistä sitten pelisi uudelleen.", - + "iris.sodium.failure.download": "Lataa Embeddium", + "iris.sodium.failure.reason.notFound": "Oculus vaatii Embeddiumin hyvän suorituskyvyn takaamiseksi, mutta Embeddiumia ei ole asennettu. Lataa Embeddium, laita se modit-kansioosi, ja käynnistä pelisi uudelleen.", + "iris.sodium.failure.reason.incompatible": "Oculus vaatii Embeddiumin hyvän suorituskyvyn takaamiseksi, mutta Embeddium versiosi on yhteensopimaton. Lataa yhteensopiva Embeddium versio, laita se modit-kansioosi ja poista yhteensopimaton versio, käynnistä sitten pelisi uudelleen.", + "options.iris.apply": "Ota käyttöön", "options.iris.refresh": "Lataa uudelleen", "options.iris.openShaderPackFolder": "Avaa shader-pakettikansio...", @@ -48,7 +48,7 @@ "options.iris.profile.custom": "Mukautettu", "options.iris.shadowDistance": "Varjojen enimmäisetäisyys", "options.iris.shadowDistance.enabled": "Sallii varjojen enimmäisetäisyydeen määrittämisen. Maasto ja kohteet asetetun etäisyyden jälkeen eivät enää tuota varjoja. Varjoetäisyyden alentaminen saattaa nostaa pelin kuvataajuutta huomattavasti.", - "options.iris.shadowDistance.disabled": "Käyttöön ottamasi shader-paketti määrittää varjoetäisyyden jo; et voi muuttaa sitä.", + "options.iris.shadowDistance.disabled": "Käyttöön ottamasi shader-paketti määrittää varjoetäisyyden jo; et voi muuttaa sitä.", "pack.iris.select.title": "Valitse", "pack.iris.configure.title": "Mukauta", diff --git a/src/main/resources/assets/iris/lang/hu_hu.json b/src/main/resources/assets/iris/lang/hu_hu.json index 9af883d860..d68dbf747b 100644 --- a/src/main/resources/assets/iris/lang/hu_hu.json +++ b/src/main/resources/assets/iris/lang/hu_hu.json @@ -13,11 +13,11 @@ "iris.shaders.reloaded.failure": "Nem sikerült a shader-ek újratöltése! A hiba oka: %s", "iris.shaders.toggled.failure": "Nem sikerült a shader-eket bekapcsolni! A hiba oka: %s", "iris.sodium.failure.title": "Az Oculus nem tudott betöltÅ‘dni!", - "iris.sodium.failure.download": "Töltsd le a Rubidium modot", - "iris.sodium.failure.reason.notFound": "Az Oculus-nak szüksége van a Rubidium modra a megfelelÅ‘ teljesítményhez, de a Rubidium mod nincs telepítve.\nKérlek töltsd le a Rubidium modot, helyezd a mods mappába, és indítsd újra a játékot.", - "iris.sodium.failure.reason.incompatible": "Az Oculus-nak szüksége van a Rubidium modra a megfelelÅ‘ teljesítményhez, de a Rubidium modnak nem a megfelelÅ‘ verziója van feltelepítve.\nKérlek töltsd le a helyes verziót, majd helyezd a mods mappába és törölj minden más verziót, végük indítsd újra a játékot.", + "iris.sodium.failure.download": "Töltsd le a Sodium modot", + "iris.sodium.failure.reason.notFound": "Az Oculus-nak szüksége van a Sodium modra a megfelelÅ‘ teljesítményhez, de a Sodium mod nincs telepítve.\nKérlek töltsd le a Sodium modot, helyezd a mods mappába, és indítsd újra a játékot.", + "iris.sodium.failure.reason.incompatible": "Az Oculus-nak szüksége van a Sodium modra a megfelelÅ‘ teljesítményhez, de a Sodium modnak nem a megfelelÅ‘ verziója van feltelepítve.\nKérlek töltsd le a helyes verziót, majd helyezd a mods mappába és törölj minden más verziót, végük indítsd újra a játékot.", "iris.nec.failure.title": "[%s] Not Enough Crashes észlelve!", - "iris.nec.failure.description": "A Not Enough Crashes súlyosan rongálhatja a játékot, ezentúé nem ad pontos részleteket a hibákról.\nJó alternatívák a MixinTrace és a Crafty Crashes, ezek megbízhatóan tudják elemezni a hiba forrását.", + "iris.nec.failure.description": "A Not Enough Crashes súlyosan rongálhatja a játékot, ezentúé nem ad pontos részleteket a hibákról.\nJó alternatívák a MixinTrace, ezek megbízhatóan tudják elemezni a hiba forrását.", "iris.unsupported.irisorpc": "Oculus vagy a PC-d", "iris.unsupported.iris": "Oculus", "iris.unsupported.pc": "a PC-d", diff --git a/src/main/resources/assets/iris/lang/it_it.json b/src/main/resources/assets/iris/lang/it_it.json index 5b3847b34b..0556f325dc 100644 --- a/src/main/resources/assets/iris/lang/it_it.json +++ b/src/main/resources/assets/iris/lang/it_it.json @@ -13,11 +13,11 @@ "iris.shaders.reloaded.failure": "Impossibile ricaricare le shaders! Motivo: %s", "iris.shaders.toggled.failure": "Impossibile attivare le shaders! Motico: %s", "iris.sodium.failure.title": "Oculus non è riuscito a caricarsi!", - "iris.sodium.failure.download": "Scarica Rubidium", - "iris.sodium.failure.reason.notFound": "Oculus ha bisogno di Rubidium per una buona performance, ma Rubidium non è installato. Per favore scarica Rubidium, mettilo nella cartella delle mod e riavvia il gioco.", - "iris.sodium.failure.reason.incompatible": "Oculus ha bisogno di Rubidium per una buona performance, ma una versione incompatibile è stata trovata. Per favore scarica la corretta verisone di Rubidium, mettilo nella cartella delle mod, elimina la vecchia versione e riavvia il gioco.", + "iris.sodium.failure.download": "Scarica Sodium", + "iris.sodium.failure.reason.notFound": "Oculus ha bisogno di Sodium per una buona performance, ma Sodium non è installato. Per favore scarica Sodium, mettilo nella cartella delle mod e riavvia il gioco.", + "iris.sodium.failure.reason.incompatible": "Oculus ha bisogno di Sodium per una buona performance, ma una versione incompatibile è stata trovata. Per favore scarica la corretta verisone di Sodium, mettilo nella cartella delle mod, elimina la vecchia versione e riavvia il gioco.", "iris.nec.failure.title": "[%s] Not Enough Crashes Trovato!", - "iris.nec.failure.description": "Not Enough Crashes può rompere il gioco durante i crash e non dà risultati accurati. Buone alternative sono MixinTrace e Crafty Crashes, che possono identificare la causa di un crash meglio e non mettono il gioco in uno stato invalido.", + "iris.nec.failure.description": "Not Enough Crashes può rompere il gioco durante i crash e non dà risultati accurati. Buone alternative sono MixinTrace, che possono identificare la causa di un crash meglio e non mettono il gioco in uno stato invalido.", "iris.unsupported.irisorpc": "Oculus o il tuo PC", "iris.unsupported.iris": "Oculus", "iris.unsupported.pc": "il tuo PC", diff --git a/src/main/resources/assets/iris/lang/ja_jp.json b/src/main/resources/assets/iris/lang/ja_jp.json index 52d0b9b27f..fb6c3fca6b 100644 --- a/src/main/resources/assets/iris/lang/ja_jp.json +++ b/src/main/resources/assets/iris/lang/ja_jp.json @@ -13,9 +13,9 @@ "iris.shaders.reloaded.failure": "シェーダーã®å†èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸï¼ ç†ç”±: %s", "iris.shaders.toggled.failure": "シェーダーã®åˆ‡ã‚Šæ›¿ãˆã«å¤±æ•—ã—ã¾ã—ãŸï¼ ç†ç”±: %s", "iris.sodium.failure.title": "Oculusã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸï¼", - "iris.sodium.failure.download": "Rubidiumをダウンロード", - "iris.sodium.failure.reason.notFound": "パフォーマンスå‘上ã®ãŸã‚ã€Oculusを使用ã™ã‚‹ã«ã¯RubidiumãŒå¿…è¦ã§ã™ã€‚ Rubidiumをダウンロードã—ã€modsフォルダーã«å°Žå…¥ã—ã¦ã‹ã‚‰ã€ã‚²ãƒ¼ãƒ ã‚’å†èµ·å‹•ã—ã¦ãã ã•ã„。", - "iris.sodium.failure.reason.incompatible": "互æ›æ€§ã®ãªã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®RubidiumãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸã€‚ 対応ã—ã¦ã„ã‚‹ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®Rubidiumをダウンロードã—ã€modsフォルダーã«å°Žå…¥ã—ã¦ã‹ã‚‰ã€ã‚²ãƒ¼ãƒ ã‚’å†èµ·å‹•ã—ã¦ãã ã•ã„。", + "iris.sodium.failure.download": "Embeddiumをダウンロード", + "iris.sodium.failure.reason.notFound": "パフォーマンスå‘上ã®ãŸã‚ã€Oculusを使用ã™ã‚‹ã«ã¯EmbeddiumãŒå¿…è¦ã§ã™ã€‚ Embeddiumをダウンロードã—ã€modsフォルダーã«å°Žå…¥ã—ã¦ã‹ã‚‰ã€ã‚²ãƒ¼ãƒ ã‚’å†èµ·å‹•ã—ã¦ãã ã•ã„。", + "iris.sodium.failure.reason.incompatible": "互æ›æ€§ã®ãªã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®EmbeddiumãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸã€‚ 対応ã—ã¦ã„ã‚‹ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®Embeddiumをダウンロードã—ã€modsフォルダーã«å°Žå…¥ã—ã¦ã‹ã‚‰ã€ã‚²ãƒ¼ãƒ ã‚’å†èµ·å‹•ã—ã¦ãã ã•ã„。", "iris.unsupported.irisorpc": "Oculusã¾ãŸã¯ãŠä½¿ã„ã®ã‚³ãƒ³ãƒ”ューター", "iris.unsupported.iris": "Oculus", "iris.unsupported.pc": "ãŠä½¿ã„ã®ã‚³ãƒ³ãƒ”ューター", diff --git a/src/main/resources/assets/iris/lang/ko_kr.json b/src/main/resources/assets/iris/lang/ko_kr.json index 22b4d4ef21..351e68a478 100644 --- a/src/main/resources/assets/iris/lang/ko_kr.json +++ b/src/main/resources/assets/iris/lang/ko_kr.json @@ -6,6 +6,7 @@ "iris.shaders.debug.disabled": "디버그 모드가 비활성화ë˜ì—ˆìŠµë‹ˆë‹¤.", "iris.shaders.debug.failure": "ì´ ì»´í“¨í„°ëŠ” 디버그 ê¸°ëŠ¥ì„ ì§€ì›í•˜ì§€ 않습니다.", "iris.shaders.debug.restart": "디버그 콘í…스트가 없습니다. 다시 시작하여 디버그 모드를 활성화하십시오.", + "iris.shaders.ssbofailure": "ì´ GPU는 ì…°ì´ë”ê°€ 요구하는 기능(SSBO)ì„ ì§€ì›í•˜ì§€ 않습니다. ì…°ì´ë”ê°€ ì •ìƒì ìœ¼ë¡œ ë™ìž‘하지 ì•Šì„ ê²ƒìž…ë‹ˆë‹¤.", "iris.keybind.reload": "ì…°ì´ë” 새로고침", "iris.keybind.shaderPackSelection": "ì…°ì´ë” 팩 ì„ íƒ ì°½", "iris.keybind.toggleShaders": "ì…°ì´ë” 전환", @@ -13,16 +14,17 @@ "iris.shaders.reloaded.failure": "ì…°ì´ë”를 새로고침하지 못하였습니다: %s", "iris.shaders.toggled.failure": "ì…°ì´ë”를 전환하지 못하였습니다: %s", "iris.sodium.failure.title": "Oculus를 불러오지 못하였습니다.", - "iris.sodium.failure.download": "Rubidium 다운로드", - "iris.sodium.failure.reason.notFound": "Oculus를 최ìƒì˜ 성능으로 쓰기 위한 Rubidiumì´ ì„¤ì¹˜ë˜ì–´ 있지 않습니다. Rubidiumì„ ë‚´ë ¤ë°›ì•„ mods í´ë”ì— ë„£ì–´ ê²Œìž„ì„ ë‹¤ì‹œ 실행하십시오.", - "iris.sodium.failure.reason.incompatible": "Oculus를 최ìƒì˜ 성능으로 쓰기 위한 Rubidiumì˜ ë²„ì „ì´ í˜¸í™˜ë˜ì§€ 않습니다. Oculus와 맞는 ë²„ì „ì˜ Rubidiumì„ ë‚´ë ¤ë°›ì•„ mods í´ë”ì— ë„£ê³ , 호환ë˜ì§€ 않는 ë²„ì „ì˜ Rubidiumì„ ì œê±°í•œ ë’¤ ê²Œìž„ì„ ë‹¤ì‹œ 실행하십시오.", + "iris.sodium.failure.download": "Sodium 다운로드", + "iris.sodium.failure.reason.notFound": "Oculus를 최ìƒì˜ 성능으로 쓰기 위한 Sodiumì´ ì„¤ì¹˜ë˜ì–´ 있지 않습니다. Sodiumì„ ë‚´ë ¤ë°›ì•„ mods í´ë”ì— ë„£ì–´ ê²Œìž„ì„ ë‹¤ì‹œ 실행하십시오.", + "iris.sodium.failure.reason.incompatible": "Oculus를 최ìƒì˜ 성능으로 쓰기 위한 Sodiumì˜ ë²„ì „ì´ í˜¸í™˜ë˜ì§€ 않습니다. Oculus와 맞는 ë²„ì „ì˜ Sodiumì„ ë‚´ë ¤ë°›ì•„ mods í´ë”ì— ë„£ê³ , 호환ë˜ì§€ 않는 ë²„ì „ì˜ Sodiumì„ ì œê±°í•œ ë’¤ ê²Œìž„ì„ ë‹¤ì‹œ 실행하십시오.", "iris.nec.failure.title": "[%s] Not Enough Crashes 모드가 ê°ì§€ë˜ì—ˆìŠµë‹ˆë‹¤.", - "iris.nec.failure.description": "Not Enough Crashes는 충ëŒì´ ì²˜ë¦¬ë  ë•Œ ê²Œìž„ì„ ì˜ˆê¸°ì¹˜ 못하게 중단시킬 수 있으며 정확한 ì¶©ëŒ ê²°ê³¼ë¥¼ 표시하지 않습니다.\nì´ì— 대한 ì¢‹ì€ ëŒ€ì²´ìž¬ë¡œì„œ, MixinTrace와 Crafty Crashes는 ì¶©ëŒ ì›ì¸ì„ 보다 안정ì ìœ¼ë¡œ ì‹ë³„하며 ê²Œìž„ì„ ì¤‘ë‹¨í•˜ì§€ 않습니다.", + "iris.nec.failure.description": "Not Enough Crashes는 충ëŒì´ ì²˜ë¦¬ë  ë•Œ ê²Œìž„ì„ ì˜ˆê¸°ì¹˜ 못하게 중단할 수 있으며 정확한 ì¶©ëŒ ê²°ê³¼ë¥¼ 표시하지 않습니다.\nì´ì— 대한 ì¢‹ì€ ëŒ€ì²´ìž¬ë¡œì„œ, MixinTrace는 ì¶©ëŒ ì›ì¸ì„ 보다 안정ì ìœ¼ë¡œ ì‹ë³„하며 ê²Œìž„ì„ ì¤‘ë‹¨í•˜ì§€ 않습니다.", "iris.unsupported.irisorpc": "Oculus ë˜ëŠ” 사용ìžì˜ PC", "iris.unsupported.iris": "Oculus", "iris.unsupported.pc": "사용ìžì˜ PC", "iris.unsupported.pack": "ì…°ì´ë” íŒ©ì´ í˜¸í™˜ë˜ì§€ 않습니다.", "iris.unsupported.pack.description": "불러오려는 ì…°ì´ë” íŒ©ì´ %sì— ì˜í•´ 지ì›ë˜ì§€ 않는 ê¸°ëŠ¥ì„ í¬í•¨í•˜ê³  있습니다. 다른 팩으로 다시 ì‹œë„하십시오. ëª©ë¡ %s", + "iris.unsupported.pack.macos": "\nmacOS는 ëŒ€ë¶€ë¶„ì˜ ì…°ì´ë” 팩과 문제를 ì¼ìœ¼í‚µë‹ˆë‹¤.", "options.iris.apply": "ì ìš©", "options.iris.refresh": "새로고침", "options.iris.openShaderPackFolder": "ì…°ì´ë” 팩 í´ë” 열기", @@ -47,15 +49,16 @@ "options.iris.reset": "초기화", "options.iris.reset.tooltip": "모든 ì˜µì…˜ì´ ì´ˆê¸°í™”ë©ë‹ˆë‹¤. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?", "options.iris.reset.tooltip.holdShift": "[Shift] 키를 누르고 í´ë¦­í•˜ì—¬ 초기화", - "options.iris.importSettings.tooltip": "파ì¼ì—ì„œ 설정 가져오기", + "options.iris.importSettings.tooltip": "ì„¤ì •ì„ íŒŒì¼ì—ì„œ 가져오기", "options.iris.exportSettings.tooltip": "ì„¤ì •ì„ íŒŒì¼ë¡œ 내보내기", "options.iris.mustDisableFullscreen": "ì „ì²´ 화면 모드를 해제하십시오.", "options.iris.setToDefault": "ì˜µì…˜ì„ ê¸°ë³¸ê°’ìœ¼ë¡œ ë˜ëŒë¦¬ì‹œê² ìŠµë‹ˆê¹Œ?", "options.iris.profile": "프로필", "options.iris.profile.custom": "ì‚¬ìš©ìž ì§€ì •", - "options.iris.shadowDistance": "최대 ê·¸ë¦¼ìž ë²”ìœ„", - "options.iris.shadowDistance.enabled": "최대 ê·¸ë¦¼ìž í‘œì‹œ 범위를 ì¡°ì •í•  수 있습니다. ì´ ê±°ë¦¬ë³´ë‹¤ 멀리 있는 개체와 ì§€í˜•ì€ ê·¸ë¦¼ìžë¥¼ 표시하지 않습니다. ê·¸ë¦¼ìž ê±°ë¦¬ë¥¼ 줄ì´ë©´ 성능 í–¥ìƒì— ë„ì›€ì´ ë  ìˆ˜ 있습니다.", - "options.iris.shadowDistance.disabled": "현재 사용하고 있는 ì…°ì´ë” íŒ©ì€ ì´ë¯¸ ê·¸ë¦¼ìž í‘œì‹œ 범위가 설정ë˜ì–´ 있어 바꿀 수 없습니다.", + "options.iris.shadowDistance": "ê·¸ë¦¼ìž ë Œë”ë§ ê±°ë¦¬", + "options.iris.shadowDistance.enabled": "그림ìžê°€ 표시ë˜ëŠ” 최대 거리를 ì¡°ì •í•  수 있습니다. ì´ ê±°ë¦¬ë³´ë‹¤ 멀리 있는 개체와 ì§€í˜•ì€ ê·¸ë¦¼ìžë¥¼ 표시하지 않습니다. ê·¸ë¦¼ìž ê±°ë¦¬ë¥¼ 줄ì´ë©´ ì„±ëŠ¥ì„ í–¥ìƒì‹œí‚¬ 수 있습니다.", + "options.iris.shadowDistance.disabled": "현재 사용하고 있는 ì…°ì´ë” íŒ©ì€ ì´ë¯¸ ê·¸ë¦¼ìž ë Œë”ë§ ê±°ë¦¬ê°€ 설정ë˜ì–´ 있어 바꿀 수 없습니다.", + "options.iris.shadowDistance.sodium_tooltip": "ê·¸ë¦¼ìž ë Œë”ë§ ê±°ë¦¬ëŠ” 잠재ì ìœ¼ë¡œ ì„€ë„ íŒ¨ìŠ¤ì—ì„œ ì§€í˜•ì„ ë Œë”ë§í•  수 있는 거리를 제어합니다. ì´ë¥¼ 낮게 설정하면 ì§€í˜•ì´ ëœ ë Œë”ë§ë˜ì§€ë§Œ 프레임레ì´íŠ¸ë¥¼ í–¥ìƒì‹œí‚¬ 수 있습니다. ê·¸ë¦¼ìž ë Œë”ë§ ê±°ë¦¬ë¥¼ 명시ì ìœ¼ë¡œ 지정하는 ì…°ì´ë” íŒ©ì„ ì‚¬ìš©í•˜ë©´ ì´ ì„¤ì •ì„ ë°”ê¿€ 수 없습니다. 실제로 그림ìžê°€ 표시ë˜ëŠ” 범위는 ë Œë”ë§ ê±°ë¦¬ 설정으로 제한ë©ë‹ˆë‹¤.", "options.iris.gui.hide": "GUI 숨기기", "options.iris.gui.show": "GUI ë³´ì´ê¸°", diff --git a/src/main/resources/assets/iris/lang/nl_nl.json b/src/main/resources/assets/iris/lang/nl_nl.json index d0116de09d..cd7e85d118 100644 --- a/src/main/resources/assets/iris/lang/nl_nl.json +++ b/src/main/resources/assets/iris/lang/nl_nl.json @@ -1,11 +1,37 @@ { "iris.shaders.reloaded": "Shaders herladen!", + "iris.shaders.disabled": "Shaders uitgeschakeld!", + "iris.shaders.toggled": "Shaders naar %s geschakeld!", + "iris.shaders.debug.enabled": "Foutopsporing is ingeschakeld, de foutopsporings log zal uitgebreider zijn!", + "iris.shaders.debug.disabled": "Foutopsporing is uitgeschakeld.", + "iris.shaders.debug.failure": "Foutopsporing kon niet worden ingeschakeld, uw computer ondersteunt geen foutopsporingsfuncties.", + "iris.shaders.debug.restart": "Uw heeft geen foutopsporings-context, start opnieuw op om OpenGL foutopsporing in te schakelen.", + "iris.load.failure.shader": "Het shader-pack kon niet worden geladen! Rapporteer de fout aan de shader-ontwikkelaar.", + "iris.load.failure.generic": "Oculus heeft een probleem ondervonden bij het laden van de shaders; meld dit alstublieft aan de Oculus-ontwikkelaars.", + "iris.shaders.ssbofailure": "De shader heeft om een specifieke functie (SSBO) gevraagd die niet door uw GPU wordt ondersteund, deze werkt mogelijk niet.", "iris.keybind.reload": "Herlaad Shaders", + "iris.keybind.shaderPackSelection": "Shader-pack Selectie Scherm", + "iris.keybind.toggleShaders": "Shaders In- Of Uitschakelen", + "iris.keybinds": "Oculus", "iris.shaders.reloaded.failure": "Shaders herladen is mislukt! Reden: %s", - + "iris.shaders.toggled.failure": "Het is niet gelukt om shaders in of uit te schakelen! Reden: %s", + "iris.sodium.failure.title": "Oculus kon niet laden!", + "iris.sodium.failure.download": "Sodium Downloaden", + "iris.sodium.failure.reason.notFound": "Oculus heeft Sodium nodig voor goede prestaties, maar Sodium is niet geïnstalleerd. Download Sodium, plaats het in je mods-map, en herstart het spel.", + "iris.sodium.failure.reason.incompatible": "Oculus heeft Sodium nodig voor goede prestaties, maar er is een incompatibele versie gevonden. Download de juiste versie van Sodium, plaats het in je mods-map, verwijder de incorrecte versie, en herstart het spel.", + "iris.nec.failure.title": "[%s] Not Enough Crashes is gedetecteerd!", + "iris.nec.failure.description": "Not Enough Crashes kan het spel ernstig beschadigen tijdens het verwerken van crashes, en levert geen nauwkeurige resultaten op.\nEen goed alternatief is MixinTrace, wat de oorzaak van een crash betrouwbaarder kan identificeren en het spel niet in een ongeldige staat brengt.", + "iris.unsupported.irisorpc": "Oculus of uw computer", + "iris.unsupported.iris": "Oculus", + "iris.unsupported.pc": "uw computer", + "iris.unsupported.pack": "Shader-pack is incompatibel!", + "iris.unsupported.pack.description": "Het shader-pack dat je probeert te laden bevat functies die niet ondersteund worden door %s. Probeer een ander pack. Lijst %s", + "iris.unsupported.pack.macos": "\nHet is bekend dat macOS problemen heeft met veel shader-pakketten.", "options.iris.apply": "Toepassen", "options.iris.refresh": "Verversen", "options.iris.openShaderPackFolder": "Open de Shader Pack map...", + "options.iris.shaderPackSettings": "Shader Pack Instellingen...", + "options.iris.shaderPackList": "Shader Pack Lijst...", "options.iris.refreshShaderPacks": "Ververs Shader Pack", "options.iris.shaderPackSelection": "Shader Packs...", "options.iris.shaderPackSelection.title": "Shader Packs", @@ -15,9 +41,35 @@ "options.iris.shaderPackSelection.failedAddSingle": "\"%s\" is geen geldige Shader Pack", "options.iris.shaderPackSelection.copyError": "Kon Shader Pack \"%s\" niet toevoegen", "options.iris.shaderPackSelection.copyErrorAlreadyExists": "\"%s\" staat al in uw Shader Packs map!", + "options.iris.shaderPackOptions.tooManyFiles": "Kan niet meerdere Shader-instellingenbestanden importeren!", + "options.iris.shaderPackOptions.failedImport": "Importeren van Shader-instellingenbestand \"%s\" mislukt", + "options.iris.shaderPackOptions.importedSettings": "Shader-instellingen geïmporteerd van \"%s\"", "options.iris.shaders.disabled": "Shaders: Uitgeschakeld", "options.iris.shaders.enabled": "Shaders: Ingeschakeld", + "options.iris.shaders.nonePresent": "Shaders: Geen Pakketten Aanwezig", + "options.iris.back": "Terug", + "options.iris.reset": "Reset", + "options.iris.reset.tooltip": "Reset ALLE opties en pas toe?", + "options.iris.reset.tooltip.holdShift": "Houd SHIFT ingedrukt en klik om te resetten", + "options.iris.importSettings.tooltip": "Importeer instellingen van een bestand", + "options.iris.exportSettings.tooltip": "Exporteer instellingen naar een bestand", + "options.iris.mustDisableFullscreen": "Schakel eerst volledig-scherm uit!", + "options.iris.setToDefault": "Optie instellen op standaardwaarde?", + "options.iris.profile": "Profiel", + "options.iris.profile.custom": "Aangepast", + "options.iris.shadowDistance": "Maximale Schaduwafstand", + "options.iris.shadowDistance.enabled": "Hiermee kunt u de maximale afstand voor schaduwen wijzigen. Terrein en entiteiten buiten deze afstand zullen geen schaduwen werpen. Het verkleinen van de Schaduwafstand kan de prestaties aanzienlijk verbeteren.", + "options.iris.shadowDistance.disabled": "Uw huidig shader-pack heeft al een weergaveafstand voor schaduwen ingesteld; je kunt het niet veranderen.", + "options.iris.shadowDistance.sodium_tooltip": "De schaduwweergaveafstand bepaalt hoe ver terrein mogelijk kan worden weergeven in de schaduw fase. Kleinere afstanden betekent dat minder terrein wordt weergeven, waardoor de framesnelheden verbeteren. Deze optie kan niet worden gewijzigd op pakketten die expliciet een schaduwweergaveafstand specificeren. De werkelijke schaduwweergaveafstand wordt beperkt door de weergaveafstand.", + "options.iris.colorSpace": "Kleur Ruimte", + "options.iris.colorSpace.sodium_tooltip": "De kleurruimte waarnaar het scherm moet worden getransformeerd. Werkt bovenop shader-packs. Gebruik SRGB als u het niet zeker weet.", + "options.iris.gui.hide": "Verberg GUI", + "options.iris.gui.show": "Toon GUI", "pack.iris.select.title": "Selecteren", - "pack.iris.list.label": "+ Voeg Shader Packs toe door te slepen en neer te zetten" + "pack.iris.configure.title": "Configureer", + "pack.iris.list.label": "+ Voeg Shader Packs toe door te slepen en neer te zetten", + + "label.iris.true": "Aan", + "label.iris.false": "Uit" } diff --git a/src/main/resources/assets/iris/lang/pl_pl.json b/src/main/resources/assets/iris/lang/pl_pl.json index bf2a27970e..3af0143019 100644 --- a/src/main/resources/assets/iris/lang/pl_pl.json +++ b/src/main/resources/assets/iris/lang/pl_pl.json @@ -13,23 +13,29 @@ "iris.shaders.reloaded.failure": "Nie udaÅ‚o siÄ™ przeÅ‚adować Shaderów! Powód: %s", "iris.shaders.toggled.failure": "Nie udaÅ‚o siÄ™ przeÅ‚Ä…czyć Shaderów! Powód: %s", "iris.sodium.failure.title": "Oculus: Nie udaÅ‚o siÄ™ zaÅ‚adować!", - "iris.sodium.failure.download": "Pobierz Rubidium", - "iris.sodium.failure.reason.notFound": "Oculus wymaga Rubidium dla poprawnego dziaÅ‚ania, a Rubidium nie jest zainstalowane. Pobierz wÅ‚aÅ›ciwÄ… wersjÄ™ Rubidium, umieść jÄ… w folderze mods i ponownie uruchom grÄ™.", - "iris.sodium.failure.reason.incompatible": "Oculus wymaga Rubidium dla poprawnego dziaÅ‚ania. Znaleziono niekompatybilnÄ… wersjÄ™ Rubidium. Pobierz wÅ‚aÅ›ciwÄ… wersjÄ™ Rubidium, umieść jÄ… w folderze mods oraz usuÅ„ niekompatybilnÄ… wersjÄ™ i ponownie uruchom grÄ™.", - + "iris.sodium.failure.download": "Pobierz Sodium", + "iris.sodium.failure.reason.notFound": "Oculus wymaga Sodium dla poprawnego dziaÅ‚ania, a Sodium nie jest zainstalowane. Pobierz wÅ‚aÅ›ciwÄ… wersjÄ™ Sodium, umieść jÄ… w folderze mods i ponownie uruchom grÄ™.", + "iris.sodium.failure.reason.incompatible": "Oculus wymaga Sodium dla poprawnego dziaÅ‚ania. Znaleziono niekompatybilnÄ… wersjÄ™ Sodium. Pobierz wÅ‚aÅ›ciwÄ… wersjÄ™ Sodium, umieść jÄ… w folderze mods oraz usuÅ„ niekompatybilnÄ… wersjÄ™ i ponownie uruchom grÄ™.", + "iris.nec.failure.title": "[%s] Wykryto Not Enough Crashes!", + "iris.nec.failure.description": "Not Enough Crashes może poważnie uszkodzić grÄ™ podczas obsÅ‚ugi awarii i nie zapewnia dokÅ‚adnych wyników.\nDobrymi alternatywami sÄ… MixinTrace, które sÄ… w stanie bardziej niezawodnie okreÅ›lić przyczynÄ™ awarii i nie wprowadzajÄ… gry w bÅ‚Ä™dny stan.", + "iris.unsupported.irisorpc": "Oculus lub Twój PC", + "iris.unsupported.iris": "Oculus", + "iris.unsupported.pc": "Twój PC", + "iris.unsupported.pack": "Niekompatybilny pakiet Shaderów!", + "iris.unsupported.pack.description": "Pakiet Shaderów, który próbujesz zaÅ‚adować zawiera funkcje nieobsÅ‚ugiwane przez %s. ProszÄ™ spróbować z innym Shaderem. Lista %s", "options.iris.apply": "Zastosuj", "options.iris.refresh": "OdÅ›wież", - "options.iris.openShaderPackFolder": "Otwórz folder z Shaderami...", - "options.iris.shaderPackSettings": "Ustawienia Shader Packa...", + "options.iris.openShaderPackFolder": "Otwórz folder z pakietem Shaderów...", + "options.iris.shaderPackSettings": "Ustawienia pakietu Shader...", "options.iris.shaderPackList": "Lista Shaderów...", "options.iris.refreshShaderPacks": "OdÅ›wież listÄ™ z Shaderami", - "options.iris.shaderPackSelection": "Shader Packi...", - "options.iris.shaderPackSelection.title": "Shader Packi", - "options.iris.shaderPackSelection.addedPack": "Dodano Shader Packa \"%s\"", - "options.iris.shaderPackSelection.addedPacks": "Dodano %s Shader Packi", - "options.iris.shaderPackSelection.failedAdd": "Pliki nie sÄ… poprawnymi Shader Packami", - "options.iris.shaderPackSelection.failedAddSingle": "\"%s\" nie jest poprawnym Shader Packiem", - "options.iris.shaderPackSelection.copyError": "Nie można dodać Shader Packa \"%s\"", + "options.iris.shaderPackSelection": "Pakiety Shaderów...", + "options.iris.shaderPackSelection.title": "Pakiety Shaderów", + "options.iris.shaderPackSelection.addedPack": "Dodano pakiet Shaderów \"%s\"", + "options.iris.shaderPackSelection.addedPacks": "Dodano %s pakietów Shaderów", + "options.iris.shaderPackSelection.failedAdd": "Pliki nie sÄ… poprawnymi pakietami Shaderów", + "options.iris.shaderPackSelection.failedAddSingle": "\"%s\" nie jest poprawnym pakietem Shaderów", + "options.iris.shaderPackSelection.copyError": "Nie można dodać pakietu Shader \"%s\"", "options.iris.shaderPackSelection.copyErrorAlreadyExists": "\"%s\" jest już w folderze z Shaderami!", "options.iris.shaderPackOptions.tooManyFiles": "Nie można zaimportować wielu plików z ustawieniami shaderów!", "options.iris.shaderPackOptions.failedImport": "Nie udaÅ‚o siÄ™ zaimportować pliku z ustawieniami shaderów \"%s\"", @@ -49,11 +55,14 @@ "options.iris.profile.custom": "WÅ‚asny", "options.iris.shadowDistance": "Maksymalna odlegÅ‚ość cieni", "options.iris.shadowDistance.enabled": "Umożliwia zmianÄ™ maksymalnej odlegÅ‚oÅ›ci wyÅ›wietlania cieni. Teren i obiekty znajdujÄ…ce siÄ™ poza tÄ… odlegÅ‚oÅ›ciÄ… nie bÄ™dÄ… rzucać cieni. Zmniejszenie odlegÅ‚oÅ›ci cieni może znacznie zwiÄ™kszyć wydajność.", - "options.iris.shadowDistance.disabled": "Twój aktualny shader pack ma już ustawionÄ… odlegÅ‚ość renderowania cieni; nie możesz jej zmienić.", + "options.iris.shadowDistance.disabled": "Twój aktualny pakiet Shaderów ma już ustawionÄ… odlegÅ‚ość renderowania cieni; nie możesz jej zmienić.", + "options.iris.shadowDistance.sodium_tooltip": "OdlegÅ‚ość renderowania cieni okreÅ›la, jak daleko mogÄ… być potencjalnie renderowane cienie. Mniejsza odlegÅ‚ość oznacza, że mniejsza liczba cieni bÄ™dzie renderowane, co poprawia liczbÄ™ klatek na sekundÄ™. Opcja ta nie może być zmieniona w Shaderach, które jawnie okreÅ›lajÄ… odlegÅ‚ość renderowania cieni. Rzeczywista odlegÅ‚ość renderowania cieni jest ograniczona przez ustawienie OdlegÅ‚ość widzenia.", + "options.iris.gui.hide": "Ukryj GUI", + "options.iris.gui.show": "Pokaż GUI", "pack.iris.select.title": "Wybierz", "pack.iris.configure.title": "Konfiguracja", - "pack.iris.list.label": "+ PrzeciÄ…gnij i upuść Shader Packi, aby dodać", + "pack.iris.list.label": "+ PrzeciÄ…gnij i upuść pakiety Shaderów, aby dodać", "label.iris.true": "WÅ‚Ä…czone", "label.iris.false": "WyÅ‚Ä…czone" diff --git a/src/main/resources/assets/iris/lang/pt_br.json b/src/main/resources/assets/iris/lang/pt_br.json index 21228b563e..97b9839aec 100644 --- a/src/main/resources/assets/iris/lang/pt_br.json +++ b/src/main/resources/assets/iris/lang/pt_br.json @@ -13,11 +13,11 @@ "iris.shaders.reloaded.failure": "Falha ao recarregar sombreadores! Motivo: %s", "iris.shaders.toggled.failure": "Falha ao alternar sombreadores! Motivo: %s", "iris.sodium.failure.title": "Oculus falhou!", - "iris.sodium.failure.download": "Baixar Rubidium", - "iris.sodium.failure.reason.notFound": "O Oculus requer o Rubidium para um bom desempenho, mas o Rubidium não está instalado. Instale-o, coloque-o na pasta de mods e inicie o jogo.", - "iris.sodium.failure.reason.incompatible": "O Oculus requer o Rubidium para um bom desempenho, mas uma versão incompatível dele foi encontrada. Instale a versão correta, coloque-a na pasta de mods, remova a versão incorreta e inicie o jogo.", + "iris.sodium.failure.download": "Baixar Sodium", + "iris.sodium.failure.reason.notFound": "O Oculus requer o Sodium para um bom desempenho, mas o Sodium não está instalado. Instale-o, coloque-o na pasta de mods e inicie o jogo.", + "iris.sodium.failure.reason.incompatible": "O Oculus requer o Sodium para um bom desempenho, mas uma versão incompatível dele foi encontrada. Instale a versão correta, coloque-a na pasta de mods, remova a versão incorreta e inicie o jogo.", "iris.nec.failure.title": "[%s] Not Enough Crashes detectado!", - "iris.nec.failure.description": "O Not Enough Crashes pode quebrar gravemente como o jogo lida com os interrompimentos e não fornece resultados precisos.\nBoas alternativas são MixinTrace e Crafty Crashes, que pode identificar a causa de uma falha de forma mais confiável e não coloca o jogo em um estado inválido.", + "iris.nec.failure.description": "O Not Enough Crashes pode quebrar gravemente como o jogo lida com os interrompimentos e não fornece resultados precisos.\nBoas alternativas são MixinTrace, que pode identificar a causa de uma falha de forma mais confiável e não coloca o jogo em um estado inválido.", "iris.unsupported.irisorpc": "Oculus ou seu computador", "iris.unsupported.iris": "Oculus", "iris.unsupported.pc": "seu computador", @@ -65,4 +65,4 @@ "label.iris.true": "Sim", "label.iris.false": "Não" -} \ No newline at end of file +} diff --git a/src/main/resources/assets/iris/lang/ru_ru.json b/src/main/resources/assets/iris/lang/ru_ru.json index 396919d3b5..ea9e6b095a 100644 --- a/src/main/resources/assets/iris/lang/ru_ru.json +++ b/src/main/resources/assets/iris/lang/ru_ru.json @@ -1,11 +1,12 @@ { "iris.shaders.reloaded": "Шейдеры перезагружены.", "iris.shaders.disabled": "Шейдеры выключены.", - "iris.shaders.toggled": "Включён набор шейдеров %s.", + "iris.shaders.toggled": "Включён набор шейдеров «%s».", "iris.shaders.debug.enabled": "Отладка включена, ведение журнала будет более подробным.", "iris.shaders.debug.disabled": "Отладка отключена.", "iris.shaders.debug.failure": "Ðевозможно включить отладку, ваш компьютер не поддерживает необходимые функции.", "iris.shaders.debug.restart": "ОтÑутÑтвует отладочный контекÑÑ‚. ПерезапуÑтите игру, чтобы включить отладку.", + "iris.shaders.ssbofailure": "Ð—Ð°Ð¿Ñ€Ð°ÑˆÐ¸Ð²Ð°ÐµÐ¼Ð°Ñ ÑˆÐµÐ¹Ð´ÐµÑ€Ð¾Ð¼ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ (SSBO) не поддерживаетÑÑ Ð²Ð°ÑˆÐ¸Ð¼ ГП, шейдер может работать неправильно.", "iris.keybind.reload": "Перезагрузить шейдеры", "iris.keybind.shaderPackSelection": "СпиÑок наборов шейдеров", "iris.keybind.toggleShaders": "Переключить шейдеры", @@ -13,16 +14,17 @@ "iris.shaders.reloaded.failure": "Ðе удалоÑÑŒ перезагрузить шейдеры. Причина: %s", "iris.shaders.toggled.failure": "Ðе удалоÑÑŒ переключить шейдеры. Причина: %s", "iris.sodium.failure.title": "Ðе удалоÑÑŒ загрузить Oculus.", - "iris.sodium.failure.download": "Загрузить Rubidium", - "iris.sodium.failure.reason.notFound": "Oculus требует Rubidium Ð´Ð»Ñ Ð»ÑƒÑ‡ÑˆÐµÐ¹ производительноÑти, но Rubidium не уÑтановлен. ПожалуйÑта, загрузите Rubidium, добавьте его в папку Ñ Ð¼Ð¾Ð´Ð°Ð¼Ð¸ и перезапуÑтите игру.", - "iris.sodium.failure.reason.incompatible": "Oculus требует Rubidium Ð´Ð»Ñ Ð»ÑƒÑ‡ÑˆÐµÐ¹ производительноÑти, но ваша верÑÐ¸Ñ Rubidium неÑовмеÑтима. ПожалуйÑта, загрузите и добавьте в папку Ñ Ð¼Ð¾Ð´Ð°Ð¼Ð¸ подходÑщую верÑию Rubidium, удалите Ñтарую верÑию и перезапуÑтите игру.", + "iris.sodium.failure.download": "Загрузить Sodium", + "iris.sodium.failure.reason.notFound": "Oculus требует Sodium Ð´Ð»Ñ Ð»ÑƒÑ‡ÑˆÐµÐ¹ производительноÑти, но Sodium не уÑтановлен. ПожалуйÑта, загрузите Sodium, добавьте его в папку Ñ Ð¼Ð¾Ð´Ð°Ð¼Ð¸ и перезапуÑтите игру.", + "iris.sodium.failure.reason.incompatible": "Oculus требует Sodium Ð´Ð»Ñ Ð»ÑƒÑ‡ÑˆÐµÐ¹ производительноÑти, но ваша верÑÐ¸Ñ Sodium неÑовмеÑтима. ПожалуйÑта, загрузите и добавьте в папку Ñ Ð¼Ð¾Ð´Ð°Ð¼Ð¸ подходÑщую верÑию Sodium, удалите Ñтарую верÑию и перезапуÑтите игру.", "iris.nec.failure.title": "[%s] обнаружен Not Enough Crashes!", - "iris.nec.failure.description": "Not Enough Crashes может Ñерьёзно Ñломать игру при обработке Ñбоев, при Ñтом не Ð´Ð°Ð²Ð°Ñ Ñ‚Ð¾Ñ‡Ð½Ñ‹Ñ… результатов.\nÐ’ качеÑтве альтернатив еÑÑ‚ÑŒ MixinTrace и Crafty Crashes, которые более надёжно определÑÑŽÑ‚ причину ÑÐ±Ð¾Ñ Ð¸ не доводÑÑ‚ игру до неÑтабильного ÑоÑтоÑниÑ.", + "iris.nec.failure.description": "Not Enough Crashes может Ñерьёзно Ñломать игру при обработке Ñбоев, при Ñтом не Ð´Ð°Ð²Ð°Ñ Ñ‚Ð¾Ñ‡Ð½Ñ‹Ñ… результатов.\nÐ’ качеÑтве альтернатив еÑÑ‚ÑŒ MixinTrace, которые более надёжно определÑÑŽÑ‚ причину ÑÐ±Ð¾Ñ Ð¸ не доводÑÑ‚ игру до неÑтабильного ÑоÑтоÑниÑ.", "iris.unsupported.irisorpc": "не поддерживает Oculus или ваше уÑтройÑтво", "iris.unsupported.iris": "Oculus не поддерживает", "iris.unsupported.pc": "ваше уÑтройÑтво не поддерживает", "iris.unsupported.pack": "ÐеÑовмеÑтимый набор шейдеров!", "iris.unsupported.pack.description": "Этот набор шейдеров Ñодержит функции, которые %s. Попробуйте другой набор. ÐеÑовмеÑтимо: %s", + "iris.unsupported.pack.macos": "\nmacOS извеÑтен Ñвоими проблемами Ñо многими наборами шейдеров.", "options.iris.apply": "Применить", "options.iris.refresh": "Обновить", "options.iris.openShaderPackFolder": "Папка Ñ Ð½Ð°Ð±Ð¾Ñ€Ð°Ð¼Ð¸", @@ -31,15 +33,15 @@ "options.iris.refreshShaderPacks": "Обновить ÑпиÑок шейдеров", "options.iris.shaderPackSelection": "Ðаборы шейдеров...", "options.iris.shaderPackSelection.title": "Ðаборы шейдеров", - "options.iris.shaderPackSelection.addedPack": "Добавлен набор шейдеров \"%s\"", + "options.iris.shaderPackSelection.addedPack": "Добавлен набор шейдеров «%s»", "options.iris.shaderPackSelection.addedPacks": "Добавлено %s наборов шейдеров", "options.iris.shaderPackSelection.failedAdd": "Файлы не ÑвлÑÑŽÑ‚ÑÑ Ð´Ð¾Ð¿ÑƒÑтимыми наборами шейдеров", - "options.iris.shaderPackSelection.failedAddSingle": "\"%s\" не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым набором шейдеров", - "options.iris.shaderPackSelection.copyError": "Ðе удалоÑÑŒ добавить набор шейдеров \"%s\"", - "options.iris.shaderPackSelection.copyErrorAlreadyExists": "\"%s\" уже находитÑÑ Ð² вашей папке Ñ Ð½Ð°Ð±Ð¾Ñ€Ð°Ð¼Ð¸ шейдеров.", + "options.iris.shaderPackSelection.failedAddSingle": "«%s» не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым набором шейдеров", + "options.iris.shaderPackSelection.copyError": "Ðе удалоÑÑŒ добавить набор шейдеров «%s»", + "options.iris.shaderPackSelection.copyErrorAlreadyExists": "«%s» уже находитÑÑ Ð² вашей папке Ñ Ð½Ð°Ð±Ð¾Ñ€Ð°Ð¼Ð¸ шейдеров.", "options.iris.shaderPackOptions.tooManyFiles": "Ðевозможно загрузить неÑколько файлов Ñ Ð½Ð°Ñтройками.", - "options.iris.shaderPackOptions.failedImport": "Ðе удалоÑÑŒ загрузить наÑтройки из \"%s\"", - "options.iris.shaderPackOptions.importedSettings": "Загружены наÑтройки шейдеров из \"%s\"", + "options.iris.shaderPackOptions.failedImport": "Ðе удалоÑÑŒ загрузить наÑтройки из «%s»", + "options.iris.shaderPackOptions.importedSettings": "Загружены наÑтройки шейдеров из «%s»", "options.iris.shaders.disabled": "Шейдеры: Выключены", "options.iris.shaders.enabled": "Шейдеры: Включены", "options.iris.shaders.nonePresent": "Шейдеры: наборов не обнаружено", diff --git a/src/main/resources/assets/iris/lang/sk_sk.json b/src/main/resources/assets/iris/lang/sk_sk.json index 31260be597..49c5c7a750 100644 --- a/src/main/resources/assets/iris/lang/sk_sk.json +++ b/src/main/resources/assets/iris/lang/sk_sk.json @@ -12,9 +12,9 @@ "iris.shaders.reloaded.failure": "Nepodarilo sa obnoviÅ¥ tieňovaÄe! Dôvod: %s", "iris.shaders.toggled.failure": "Nepodarilo sa prepnúť tieňovaÄe! Dôvod: %s", "iris.sodium.failure.title": "Oculus sa nepodarilo naÄítaÅ¥!", - "iris.sodium.failure.download": "StiahnuÅ¥ Rubidium", - "iris.sodium.failure.reason.notFound": "Oculus potrebuje Rubidium pre dobrý výkon, ale Rubidium nie je nainÅ¡talovaný. Prosím, stiahnite si Rubidium, dajte ho do prieÄinka módov a reÅ¡tartujte hru.", - "iris.sodium.failure.reason.incompatible": "Oculus potrebuje Rubidium pre dobrý výkon, ale máte zlú verziu Rubidium. Prosím, stiahnite si správnu verziu Rubidium, dajte ho do prieÄinka módov, odstráňte zlú verziu a reÅ¡tartujte hru.", + "iris.sodium.failure.download": "StiahnuÅ¥ Embeddium", + "iris.sodium.failure.reason.notFound": "Oculus potrebuje Embeddium pre dobrý výkon, ale Embeddium nie je nainÅ¡talovaný. Prosím, stiahnite si Embeddium, dajte ho do prieÄinka módov a reÅ¡tartujte hru.", + "iris.sodium.failure.reason.incompatible": "Oculus potrebuje Embeddium pre dobrý výkon, ale máte zlú verziu Embeddium. Prosím, stiahnite si správnu verziu Embeddium, dajte ho do prieÄinka módov, odstráňte zlú verziu a reÅ¡tartujte hru.", "options.iris.apply": "AplikovaÅ¥", "options.iris.refresh": "ObnoviÅ¥", diff --git a/src/main/resources/assets/iris/lang/th_th.json b/src/main/resources/assets/iris/lang/th_th.json index 8086440061..1fdb0a0199 100644 --- a/src/main/resources/assets/iris/lang/th_th.json +++ b/src/main/resources/assets/iris/lang/th_th.json @@ -8,9 +8,9 @@ "iris.shaders.reloaded.failure": "เà¸à¸´à¸”ข้อผิดพลาดในà¸à¸²à¸£à¹‚หลดà¹à¸ªà¸‡à¹€à¸‡à¸²à¹ƒà¸«à¸¡à¹ˆ! สาเหตุ: %s", "iris.shaders.toggled.failure": "เà¸à¸´à¸”ข้อผิดพลาดในà¸à¸²à¸£à¹€à¸›à¸´à¸”/ปิดà¹à¸ªà¸‡à¹€à¸‡à¸²! สาเหตุ: %s", "iris.sodium.failure.title": "Oculus เà¸à¸´à¸”ข้อผิดพลาดขณะที่à¸à¸³à¸¥à¸±à¸‡à¹‚หลด!", - "iris.sodium.failure.download": "ดาวน์โหลด Rubidium", - "iris.sodium.failure.reason.notFound": "Oculus ต้องใช้ Rubidium เพื่อประสิทธิภาพที่ดีขึ้น à¹à¸•à¹ˆ Rubidium ยังไม่ได้รับà¸à¸²à¸£à¸•à¸´à¸”ตั้ง โปรดดาวน์โหลด Rubidium à¹à¸¥à¹‰à¸§à¸§à¸²à¸‡à¹„ว้ในโฟลเดอร์ mods เสร็จà¹à¸¥à¹‰à¸§à¹ƒà¸«à¹‰à¹€à¸›à¸´à¸”เà¸à¸¡à¹ƒà¸«à¸¡à¹ˆà¸­à¸µà¸à¸„รั้ง", - "iris.sodium.failure.reason.incompatible": "Oculus ต้องใช้ Rubidium เพื่อประสิทธิภาพที่ดีขึ้น à¹à¸•à¹ˆà¸žà¸šà¹€à¸§à¸­à¸£à¹Œà¸Šà¸±à¹ˆà¸™à¸‚อง Rubidium ที่ไม่สามารถใช้ร่วมà¸à¸±à¸š Oculus ได้ โปรดดาวน์โหลด Rubidium เวอร์ชั่นที่สามารถใช้à¸à¸±à¸š Oculus ได้ à¹à¸¥à¹‰à¸§à¸§à¸²à¸‡à¹„ว้ในโฟลเดอร์ mods ลบตัวเวอร์ชั่นที่ใช้ร่วมà¸à¸±à¸™à¹„ม่ได้ออภเสร็จà¹à¸¥à¹‰à¸§à¹ƒà¸«à¹‰à¹€à¸›à¸´à¸”เà¸à¸¡à¹ƒà¸«à¸¡à¹ˆà¸­à¸µà¸à¸„รั้ง", + "iris.sodium.failure.download": "ดาวน์โหลด Embeddium", + "iris.sodium.failure.reason.notFound": "Oculus ต้องใช้ Embeddium เพื่อประสิทธิภาพที่ดีขึ้น à¹à¸•à¹ˆ Embeddium ยังไม่ได้รับà¸à¸²à¸£à¸•à¸´à¸”ตั้ง โปรดดาวน์โหลด Embeddium à¹à¸¥à¹‰à¸§à¸§à¸²à¸‡à¹„ว้ในโฟลเดอร์ mods เสร็จà¹à¸¥à¹‰à¸§à¹ƒà¸«à¹‰à¹€à¸›à¸´à¸”เà¸à¸¡à¹ƒà¸«à¸¡à¹ˆà¸­à¸µà¸à¸„รั้ง", + "iris.sodium.failure.reason.incompatible": "Oculus ต้องใช้ Embeddium เพื่อประสิทธิภาพที่ดีขึ้น à¹à¸•à¹ˆà¸žà¸šà¹€à¸§à¸­à¸£à¹Œà¸Šà¸±à¹ˆà¸™à¸‚อง Embeddium ที่ไม่สามารถใช้ร่วมà¸à¸±à¸š Oculus ได้ โปรดดาวน์โหลด Embeddium เวอร์ชั่นที่สามารถใช้à¸à¸±à¸š Oculus ได้ à¹à¸¥à¹‰à¸§à¸§à¸²à¸‡à¹„ว้ในโฟลเดอร์ mods ลบตัวเวอร์ชั่นที่ใช้ร่วมà¸à¸±à¸™à¹„ม่ได้ออภเสร็จà¹à¸¥à¹‰à¸§à¹ƒà¸«à¹‰à¹€à¸›à¸´à¸”เà¸à¸¡à¹ƒà¸«à¸¡à¹ˆà¸­à¸µà¸à¸„รั้ง", "options.iris.apply": "ปรับใช้", "options.iris.refresh": "รีเฟรช", @@ -46,7 +46,7 @@ "options.iris.shadowDistance.disabled": "à¹à¸ªà¸‡à¹€à¸‡à¸²à¸‚องคุณใช้อยู่ได้รับà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าระยะà¸à¸²à¸£à¹€à¸£à¸™à¹€à¸”อร์เงามาเรียบร้อยà¹à¸¥à¹‰à¸§ คุณไม่สามารถเปลี่ยนได้", "options.iris.shadowDistance.sodium_tooltip": "ระยะà¸à¸²à¸£à¹€à¸£à¸™à¹€à¸”อร์เงา จะควบคุมว่าภูมิประเทศจะสามารถเรนเดอร์เป็นเงาได้ไà¸à¸¥à¸¡à¸²à¸à¸™à¹‰à¸­à¸¢à¹à¸„่ไหน โดยค่าต่ำ ๆ หมายความว่าภูมิประเทศจะถูà¸à¹€à¸£à¸™à¹€à¸”อร์ได้น้อย ช่วยเพิ่มอัตราเฟรมได้ ตัวเลือà¸à¸™à¸µà¹‰à¸ˆà¸°à¹„ม่สามารถเปลี่ยนบนà¹à¸žà¹‡à¸„ที่ได้à¸à¸³à¸«à¸™à¸”ระยะà¸à¸²à¸£à¹€à¸£à¸™à¹€à¸”อร์à¹à¸ªà¸‡à¹€à¸‡à¸²à¸¡à¸²à¹à¸¥à¹‰à¸§à¸­à¸¢à¹ˆà¸²à¸‡à¸Šà¸±à¸”เจน ระยะà¸à¸²à¸£à¹€à¸£à¸™à¹€à¸”อร์à¹à¸ªà¸‡à¹€à¸‡à¸²à¸—ี่à¹à¸—้จริงจะถูà¸à¸ˆà¸³à¸à¸±à¸”โดยตัวเลือà¸à¸£à¸°à¸¢à¸°à¸à¸²à¸£à¸¡à¸­à¸‡à¹€à¸«à¹‡à¸™", - "pack.iris.select.title": "โปรดเลือà¸", + "pack.iris.select.title": "โปรดเลือà¸", "pack.iris.configure.title": "ปรับà¹à¸•à¹ˆà¸‡à¸„่า", "pack.iris.list.label": "+ ลาà¸à¹„ฟล์à¹à¸ªà¸‡à¹€à¸‡à¸²à¸¡à¸²à¸—ี่นี่เพื่อเพิ่มà¹à¸ªà¸‡à¹€à¸‡à¸²", diff --git a/src/main/resources/assets/iris/lang/tr_tr.json b/src/main/resources/assets/iris/lang/tr_tr.json index 5cd2b11403..6109409aec 100644 --- a/src/main/resources/assets/iris/lang/tr_tr.json +++ b/src/main/resources/assets/iris/lang/tr_tr.json @@ -8,9 +8,9 @@ "iris.shaders.reloaded.failure": "Shaderları yenileme baÅŸarısız! Sebep: %s", "iris.shaders.toggled.failure": "Shaderları açma/kapama baÅŸarısız! Sebep: %s", "iris.sodium.failure.title": "Oculus yüklenilemedi!", - "iris.sodium.failure.download": "Rubidium'u Ä°ndir", - "iris.sodium.failure.reason.notFound": "Ä°yi performans için Oculus'e Rubidium gerek, ancak kurulu deÄŸil. Lütfen Rubidium'u indir ve modlar klasörüne yerleÅŸtirip oyunu yeniden baÅŸlat.", - "iris.sodium.failure.reason.incompatible": "Ä°yi performans için Oculus'e Rubidium gerek, ancak uyumsuz bir sürüm bulundu. Lütfen Rubidium'un uygun sürümünü indir, modlar klasörüne yerleÅŸtir, uyumsuz sürümü kaldır ve oyunu yeniden baÅŸlat.", + "iris.sodium.failure.download": "Embeddium'u Ä°ndir", + "iris.sodium.failure.reason.notFound": "Ä°yi performans için Oculus'e Embeddium gerek, ancak kurulu deÄŸil. Lütfen Embeddium'u indir ve modlar klasörüne yerleÅŸtirip oyunu yeniden baÅŸlat.", + "iris.sodium.failure.reason.incompatible": "Ä°yi performans için Oculus'e Embeddium gerek, ancak uyumsuz bir sürüm bulundu. Lütfen Embeddium'un uygun sürümünü indir, modlar klasörüne yerleÅŸtir, uyumsuz sürümü kaldır ve oyunu yeniden baÅŸlat.", "options.iris.apply": "Uygula", "options.iris.refresh": "Yenile", diff --git a/src/main/resources/assets/iris/lang/uk_ua.json b/src/main/resources/assets/iris/lang/uk_ua.json index 562a8258e2..69e8806078 100644 --- a/src/main/resources/assets/iris/lang/uk_ua.json +++ b/src/main/resources/assets/iris/lang/uk_ua.json @@ -13,11 +13,11 @@ "iris.shaders.reloaded.failure": "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ шейдери! Причина: %s", "iris.shaders.toggled.failure": "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¼ÐºÐ½ÑƒÑ‚Ð¸ шейдери! Причина: %s", "iris.sodium.failure.title": "Oculus не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸!", - "iris.sodium.failure.download": "Завантажити Rubidium", - "iris.sodium.failure.reason.notFound": "Ð”Ð»Ñ Ð³Ð°Ñ€Ð½Ð¾Ñ— роботи Oculus потрібен Rubidium, але Rubidium не вÑтановлено. Будь лаÑка, завантажте Rubidium, поміÑÑ‚Ñ–Ñ‚ÑŒ його в папку mods Ñ– повторно запуÑÑ‚Ñ–Ñ‚ÑŒ гру.", - "iris.sodium.failure.reason.incompatible": "Ð”Ð»Ñ Ð³Ð°Ñ€Ð½Ð¾Ñ— роботи Oculus потрібен Rubidium, але була знайдена неÑуміÑна верÑÑ–Ñ. Будь лаÑка, завантажте правильну верÑÑ–ÑŽ Rubidium, поміÑÑ‚Ñ–Ñ‚ÑŒ Ñ—Ñ— в папку mods, видаліть неправильну верÑÑ–ÑŽ та перезапуÑÑ‚Ñ–Ñ‚ÑŒ гру.", + "iris.sodium.failure.download": "Завантажити Sodium", + "iris.sodium.failure.reason.notFound": "Ð”Ð»Ñ Ð³Ð°Ñ€Ð½Ð¾Ñ— роботи Oculus потрібен Sodium, але Sodium не вÑтановлено. Будь лаÑка, завантажте Sodium, поміÑÑ‚Ñ–Ñ‚ÑŒ його в папку mods Ñ– повторно запуÑÑ‚Ñ–Ñ‚ÑŒ гру.", + "iris.sodium.failure.reason.incompatible": "Ð”Ð»Ñ Ð³Ð°Ñ€Ð½Ð¾Ñ— роботи Oculus потрібен Sodium, але була знайдена неÑуміÑна верÑÑ–Ñ. Будь лаÑка, завантажте правильну верÑÑ–ÑŽ Sodium, поміÑÑ‚Ñ–Ñ‚ÑŒ Ñ—Ñ— в папку mods, видаліть неправильну верÑÑ–ÑŽ та перезапуÑÑ‚Ñ–Ñ‚ÑŒ гру.", "iris.nec.failure.title": "[%s] Not Enough Crashes виÑвлено!", - "iris.nec.failure.description": "Not Enough Crashes може Ñерйозно поламати гру під Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ збоїв, та не дає точних результатів.\nХорошими альтернативами Ñ” MixinTrace Ñ– Crafty Crashes, Ñкі можуть надійніше визначити причину збою та не переводÑÑ‚ÑŒ гру в недійÑний Ñтан.", + "iris.nec.failure.description": "Not Enough Crashes може Ñерйозно поламати гру під Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ збоїв, та не дає точних результатів.\nХорошими альтернативами Ñ” MixinTrace, Ñкі можуть надійніше визначити причину збою та не переводÑÑ‚ÑŒ гру в недійÑний Ñтан.", "iris.unsupported.irisorpc": "Oculus або твій ПК", "iris.unsupported.iris": "Oculus", "iris.unsupported.pc": "твій ПК", diff --git a/src/main/resources/assets/iris/lang/zh_cn.json b/src/main/resources/assets/iris/lang/zh_cn.json index aa106d9d15..c162cd8e35 100644 --- a/src/main/resources/assets/iris/lang/zh_cn.json +++ b/src/main/resources/assets/iris/lang/zh_cn.json @@ -5,7 +5,8 @@ "iris.shaders.debug.enabled": "调试已å¯ç”¨ï¼Œæ—¥å¿—将更加详细ï¼", "iris.shaders.debug.disabled": "调试已ç¦ç”¨ã€‚", "iris.shaders.debug.failure": "无法å¯ç”¨è°ƒè¯•ï¼Œä½ çš„电脑ä¸æ”¯æŒè°ƒè¯•åŠŸèƒ½ã€‚", - "iris.shaders.debug.restart": "请é‡å¯ä»¥å¯ç”¨è°ƒè¯•ã€‚", + "iris.shaders.debug.restart": "没有调试环境,请é‡å¯ä»¥å¯ç”¨è°ƒè¯•ã€‚", + "iris.shaders.ssbofailure": "光影请求了你的 GPU 所ä¸æ”¯æŒçš„特定功能(SSBO),å¯èƒ½æ— æ³•æ­£å¸¸å·¥ä½œã€‚", "iris.keybind.reload": "é‡æ–°åŠ è½½å…‰å½±åŒ…", "iris.keybind.shaderPackSelection": "光影包选择界é¢", "iris.keybind.toggleShaders": "å¯ç”¨/ç¦ç”¨å…‰å½±", @@ -13,16 +14,17 @@ "iris.shaders.reloaded.failure": "é‡æ–°åŠ è½½å…‰å½±åŒ…失败ï¼åŽŸå› ï¼š%s", "iris.shaders.toggled.failure": "切æ¢å…‰å½±åŒ…失败ï¼åŽŸå› ï¼š%s", "iris.sodium.failure.title": "Oculus 加载失败ï¼", - "iris.sodium.failure.download": "下载 Rubidium", - "iris.sodium.failure.reason.notFound": "Oculus éœ€è¦ Rubidium æ¥æ供更好的性能,但你并没有安装 Rubidium。请下载 Rubidium,把它放到 mods 文件夹中,并é‡æ–°å¯åŠ¨æ¸¸æˆã€‚", - "iris.sodium.failure.reason.incompatible": "Oculus éœ€è¦ Rubidium æ¥æ供更好的性能,但ä¸å…¼å®¹å·²å®‰è£…çš„ Rubidium 版本。请下载正确的 Rubidium 版本,把它放到 mods 文件夹中,移除错误的 Rubidium 版本,并é‡æ–°å¯åŠ¨æ¸¸æˆã€‚", + "iris.sodium.failure.download": "下载 Sodium", + "iris.sodium.failure.reason.notFound": "Oculus éœ€è¦ Sodium æ¥æ供更好的性能,但你并没有安装 Sodium。请下载 Sodium,把它放到 mods 文件夹中,并é‡æ–°å¯åŠ¨æ¸¸æˆã€‚", + "iris.sodium.failure.reason.incompatible": "Oculus éœ€è¦ Sodium æ¥æ供更好的性能,但ä¸å…¼å®¹å·²å®‰è£…çš„ Sodium 版本。请下载正确的 Sodium 版本,把它放到 mods 文件夹中,移除错误的 Sodium 版本,并é‡æ–°å¯åŠ¨æ¸¸æˆã€‚", "iris.nec.failure.title": "[%s] 检测到 Not Enough Crashesï¼", - "iris.nec.failure.description": "在处ç†å´©æºƒæ—¶ï¼ŒNot Enough Crashes 会严é‡ç ´å游æˆï¼Œè€Œä¸”无法æ供准确的结果。\n好的替代å“有 MixinTrace å’Œ Crafty Crashes,它们都å¯ä»¥æ›´å‡†ç¡®åœ°è¯†åˆ«å´©æºƒåŽŸå› å¹¶ä¸”ä¸ä¼šä½¿æ¸¸æˆå¤„于无效状æ€ã€‚", + "iris.nec.failure.description": "在处ç†å´©æºƒæ—¶ï¼ŒNot Enough Crashes 会严é‡ç ´å游æˆï¼Œè€Œä¸”无法æ供准确的结果。\n好的替代å“有 MixinTrace,它们都å¯ä»¥æ›´å‡†ç¡®åœ°è¯†åˆ«å´©æºƒåŽŸå› å¹¶ä¸”ä¸ä¼šä½¿æ¸¸æˆå¤„于无效状æ€ã€‚", "iris.unsupported.irisorpc": "Oculus或你的电脑", "iris.unsupported.iris": "Oculus", "iris.unsupported.pc": "你的电脑", "iris.unsupported.pack": "光影包ä¸å…¼å®¹ï¼", "iris.unsupported.pack.description": "ä½ å°è¯•åŠ è½½çš„光影包å«%sä¸æ”¯æŒçš„功能。请å°è¯•å…¶ä»–光影。åå•ï¼š%s", + "iris.unsupported.pack.macos": "\nmacOS 已知与很多光影包都有兼容性问题。", "options.iris.apply": "应用", "options.iris.refresh": "刷新", "options.iris.openShaderPackFolder": "打开光影包文件夹…", @@ -57,8 +59,8 @@ "options.iris.shadowDistance.enabled": "å…许更改阴影的最远è·ç¦»ã€‚超出此è·ç¦»çš„地形和实体ä¸ä¼šæŠ•å°„阴影。é™ä½Žé˜´å½±è·ç¦»å¯ä»¥æ˜¾è‘—æ高性能。", "options.iris.shadowDistance.disabled": "ä½ ä¸èƒ½æ”¹å˜å½“å‰çš„光影包已ç»ä¸ºé˜´å½±è®¾ç½®çš„渲染è·ç¦»ã€‚", "options.iris.shadowDistance.sodium_tooltip": "阴影渲染è·ç¦»æŽ§åˆ¶åœ¨é˜´å½±é€šé“中å¯ä»¥æ¸²æŸ“到多远的地形。更短的è·ç¦»æ„味ç€å°†æ¸²æŸ“更少的地形,从而æ高帧率。在明确指定了阴影渲染è·ç¦»çš„光影包上无法更改此选项。实际阴影渲染的è·ç¦»å—“渲染è·ç¦»â€è®¾ç½®çš„é™åˆ¶ã€‚", - "options.iris.gui.hide": "éšè—GUI", - "options.iris.gui.show": "显示GUI", + "options.iris.gui.hide": "éšè— GUI", + "options.iris.gui.show": "显示 GUI", "pack.iris.select.title": "选择", "pack.iris.configure.title": "é…ç½®", diff --git a/src/main/resources/assets/iris/lang/zh_tw.json b/src/main/resources/assets/iris/lang/zh_tw.json index 809b973ae7..7eef9f3a64 100644 --- a/src/main/resources/assets/iris/lang/zh_tw.json +++ b/src/main/resources/assets/iris/lang/zh_tw.json @@ -2,44 +2,46 @@ "iris.shaders.reloaded": "å·²é‡æ–°è¼‰å…¥å…‰å½±ï¼", "iris.shaders.disabled": "å·²åœç”¨å…‰å½±ï¼", "iris.shaders.toggled": "使用光影:%sï¼", - "iris.shaders.debug.enabled": "已啟用åµéŒ¯ï¼Œå°‡é€²è¡Œè©³ç´°è¨˜éŒ„ï¼", - "iris.shaders.debug.disabled": "å·²åœç”¨åµéŒ¯ã€‚", - "iris.shaders.debug.failure": "無法啟用åµéŒ¯ï¼Œæ‚¨çš„電腦ä¸æ”¯æ´åµéŒ¯åŠŸèƒ½ã€‚", - "iris.shaders.debug.restart": "您沒有åµéŒ¯å…§å®¹ï¼Œè«‹é‡æ–°å•Ÿå‹•å¾Œå•Ÿç”¨åµéŒ¯ã€‚", + "iris.shaders.debug.enabled": "已啟用除錯,將進行詳細記錄ï¼", + "iris.shaders.debug.disabled": "å·²åœç”¨é™¤éŒ¯ã€‚", + "iris.shaders.debug.failure": "無法啟用除錯,您的電腦ä¸æ”¯æ´é™¤éŒ¯åŠŸèƒ½ã€‚", + "iris.shaders.debug.restart": "您沒有除錯內容,請é‡æ–°å•Ÿå‹•å¾Œå•Ÿç”¨é™¤éŒ¯ã€‚", + "iris.shaders.ssbofailure": "光影è¦æ±‚特定功能(SSBO),但您的 GPU ä¸æ”¯æ´ï¼Œå› æ­¤å®ƒå¯èƒ½ç„¡æ³•æ­£å¸¸é‹ä½œã€‚", "iris.keybind.reload": "é‡æ–°è¼‰å…¥å…‰å½±", "iris.keybind.shaderPackSelection": "光影包é¸æ“‡ç•«é¢", - "iris.keybind.toggleShaders": "光影開關", + "iris.keybind.toggleShaders": "開關光影", "iris.keybinds": "Oculus", "iris.shaders.reloaded.failure": "無法é‡æ–°è¼‰å…¥å…‰å½±ï¼åŽŸå› ï¼š%s", "iris.shaders.toggled.failure": "無法使用光影ï¼åŽŸå› ï¼š%s", "iris.sodium.failure.title": "無法載入 Oculusï¼", - "iris.sodium.failure.download": "下載 Rubidium", - "iris.sodium.failure.reason.notFound": "為了讓 Oculus 有良好的效能表ç¾ï¼Œæ‚¨éœ€è¦å®‰è£ Rubidium。請先下載它ã€å°‡å®ƒå­˜æ”¾æ–¼æ¨¡çµ„資料夾後é‡æ–°å•Ÿå‹•éŠæˆ²ã€‚", - "iris.sodium.failure.reason.incompatible": "為了讓 Oculus 有良好的效能表ç¾ï¼Œæ‚¨éœ€è¦å®‰è£ç‰ˆæœ¬ç›¸å®¹çš„ Rubidium。請先下載正確的版本ã€å°‡å®ƒå­˜æ”¾æ–¼æ¨¡çµ„資料夾ã€ç§»é™¤ä¸æ­£ç¢ºçš„版本後é‡æ–°å•Ÿå‹•éŠæˆ²ã€‚", - "iris.nec.failure.title": "%s:已åµæ¸¬åˆ°ï½¢Not Enough Crashesã€ï¼", - "iris.nec.failure.description": "「Not Enough Crashesã€å¯èƒ½æœƒåœ¨è™•ç†å´©æ½°å•é¡Œæ™‚,å°éŠæˆ²é€ æˆåš´é‡ç ´å£žï¼Œä¸¦ä¸”無法æ供精確çµæžœã€‚\n建議使用「MixinTraceã€å’Œã€ŒCrafty Crashesã€æ›¿ä»£ï¼Œä»–們在辨識崩潰原因上更å¯é ï¼Œä¸¦ä¸”ä¸æœƒè®“éŠæˆ²è™•æ–¼ç„¡æ•ˆç‹€æ…‹ã€‚", + "iris.sodium.failure.download": "下載 Sodium", + "iris.sodium.failure.reason.notFound": "為了讓 Oculus 有良好的效能表ç¾ï¼Œæ‚¨éœ€è¦å®‰è£ Sodium。請先下載它ã€å°‡å®ƒå­˜æ”¾æ–¼æ¨¡çµ„資料夾後é‡æ–°å•Ÿå‹•éŠæˆ²ã€‚", + "iris.sodium.failure.reason.incompatible": "為了讓 Oculus 有良好的效能表ç¾ï¼Œæ‚¨éœ€è¦å®‰è£ç‰ˆæœ¬ç›¸å®¹çš„ Sodium。請先下載正確的版本ã€å°‡å®ƒå­˜æ”¾æ–¼æ¨¡çµ„資料夾ã€ç§»é™¤ä¸æ­£ç¢ºçš„版本後é‡æ–°å•Ÿå‹•éŠæˆ²ã€‚", + "iris.nec.failure.title": "%s:已åµæ¸¬åˆ°ã€ŒNot Enough Crashesã€ï¼", + "iris.nec.failure.description": "「Not Enough Crashesã€å¯èƒ½æœƒåœ¨è™•ç†å´©æ½°å•é¡Œæ™‚,å°éŠæˆ²é€ æˆåš´é‡ç ´å£žï¼Œä¸¦ä¸”無法æ供精確çµæžœã€‚\n建議使用「MixinTraceã€ä»£æ›¿ï¼Œå®ƒåœ¨è¾¨è­˜å´©æ½°åŽŸå› ä¸Šæ›´å¯é ï¼Œä¸¦ä¸”ä¸æœƒè®“éŠæˆ²è™•æ–¼ç„¡æ•ˆç‹€æ…‹ã€‚", "iris.unsupported.irisorpc": "Oculus 或您的電腦", "iris.unsupported.iris": "Oculus", "iris.unsupported.pc": "您的電腦", "iris.unsupported.pack": "光影包ä¸ç›¸å®¹ï¼", "iris.unsupported.pack.description": "æ‚¨å˜—è©¦è¼‰å…¥çš„å…‰å½±åŒ…åŒ…å« %s ä¸æ”¯æ´çš„功能。請嘗試載入其他光影包。列出 %s", + "iris.unsupported.pack.macos": "\nmacOS 存在許多光影包å•é¡Œã€‚", "options.iris.apply": "套用", "options.iris.refresh": "é‡æ–°æ•´ç†", - "options.iris.openShaderPackFolder": "開啟光影包資料夾……", - "options.iris.shaderPackSettings": "光影包設定……", - "options.iris.shaderPackList": "光影包清單……", + "options.iris.openShaderPackFolder": "開啟光影包資料夾...", + "options.iris.shaderPackSettings": "光影包設定...", + "options.iris.shaderPackList": "光影包清單...", "options.iris.refreshShaderPacks": "é‡æ–°æ•´ç†", - "options.iris.shaderPackSelection": "光影包……", + "options.iris.shaderPackSelection": "光影包...", "options.iris.shaderPackSelection.title": "光影包", - "options.iris.shaderPackSelection.addedPack": "已新增 \"%s\" 光影包", + "options.iris.shaderPackSelection.addedPack": "已新增「%sã€å…‰å½±åŒ…", "options.iris.shaderPackSelection.addedPacks": "已新增 %s 個光影包", "options.iris.shaderPackSelection.failedAdd": "檔案並éžæœ‰æ•ˆçš„光影包", - "options.iris.shaderPackSelection.failedAddSingle": "\"%s\" ä¸æ˜¯æœ‰æ•ˆçš„光影包", - "options.iris.shaderPackSelection.copyError": "無法新增 \"%s\" 光影包", - "options.iris.shaderPackSelection.copyErrorAlreadyExists": "\"%s\" 已存在於光影包資料夾中ï¼", + "options.iris.shaderPackSelection.failedAddSingle": "「%sã€ä¸æ˜¯æœ‰æ•ˆçš„光影包", + "options.iris.shaderPackSelection.copyError": "無法新增「%sã€å…‰å½±åŒ…", + "options.iris.shaderPackSelection.copyErrorAlreadyExists": "「%sã€å·²å­˜åœ¨æ–¼å…‰å½±åŒ…資料夾中ï¼", "options.iris.shaderPackOptions.tooManyFiles": "無法一次匯入多個光影設定ï¼", - "options.iris.shaderPackOptions.failedImport": "無法自檔案 \"%s\" 匯入光影設定", - "options.iris.shaderPackOptions.importedSettings": "已自檔案 \"%s\" 匯入光影設定", + "options.iris.shaderPackOptions.failedImport": "無法從檔案「%sã€åŒ¯å…¥å…‰å½±è¨­å®š", + "options.iris.shaderPackOptions.importedSettings": "已從檔案「%sã€åŒ¯å…¥å…‰å½±è¨­å®š", "options.iris.shaders.disabled": "光影:已åœç”¨", "options.iris.shaders.enabled": "光影:已啟用", "options.iris.shaders.nonePresent": "光影:沒有光影包", @@ -48,20 +50,21 @@ "options.iris.reset.tooltip": "是å¦é‡è¨­ã€Œå…¨éƒ¨ã€é¸é …並套用?", "options.iris.reset.tooltip.holdShift": "æŒ‰ä½ SHIFT 後點擊以é‡è¨­", "options.iris.importSettings.tooltip": "從檔案匯入設定", - "options.iris.exportSettings.tooltip": "匯出設定至檔案", + "options.iris.exportSettings.tooltip": "將設定匯出至檔案", "options.iris.mustDisableFullscreen": "è«‹å…ˆçµæŸå…¨èž¢å¹•æ¨¡å¼ï¼", "options.iris.setToDefault": "å°‡é¸é …設為é è¨­ï¼Ÿ", "options.iris.profile": "設定檔", "options.iris.profile.custom": "自訂", "options.iris.shadowDistance": "最大陰影è·é›¢", - "options.iris.shadowDistance.enabled": "能讓您變更陰影的最大è·é›¢ã€‚超出此è·é›¢çš„地形和實體將ä¸æœƒæœ‰é™°å½±ã€‚調低陰影è·é›¢èƒ½é¡¯è‘—æå‡æ•ˆèƒ½ã€‚", + "options.iris.shadowDistance.enabled": "能讓您變更陰影的最大è·é›¢ã€‚超出此è·é›¢çš„地形和實體將ä¸æœƒæœ‰é™°å½±ã€‚é™ä½Žé™°å½±è·é›¢èƒ½é¡¯è‘—æå‡æ•ˆèƒ½ã€‚", "options.iris.shadowDistance.disabled": "您無法變更目å‰å…‰å½±åŒ…所設定的陰影顯示è·é›¢ã€‚", - "options.iris.gui.hide": "éš±è— GUI", - "options.iris.gui.show": "顯示 GUI", - + "options.iris.shadowDistance.sodium_tooltip": "陰影繪製è·é›¢æŽ§åˆ¶è‘—在陰影通é“中å¯ä»¥ç¹ªè£½å¤šé çš„地形。較低的è·é›¢æ„味著繪製的地形較少,從而æ高 FPS。在明確指定了陰影繪製è·é›¢çš„光影包中,此é¸é …無法更改。實際的陰影繪製è·é›¢å—顯示è·é›¢è¨­å®šçš„é™åˆ¶ã€‚", + "options.iris.gui.hide": "éš±è—介é¢", + "options.iris.gui.show": "顯示介é¢", + "pack.iris.select.title": "é¸æ“‡", "pack.iris.configure.title": "設定", - "pack.iris.list.label": "+ 將欲新增的光影包拖曳至此", + "pack.iris.list.label": "+ å°‡è¦æ–°å¢žçš„光影包拖曳至此", "label.iris.true": "é–‹å•Ÿ", "label.iris.false": "關閉" diff --git a/src/main/resources/colorSpace.csh b/src/main/resources/colorSpace.csh new file mode 100644 index 0000000000..016417bb04 --- /dev/null +++ b/src/main/resources/colorSpace.csh @@ -0,0 +1,145 @@ +#ifdef COMPUTE +#version 430 core +layout(local_size_x = 8, local_size_y = 8) in; +#else +#version 330 core +#endif + +#ifdef COMPUTE +layout(rgba8) uniform image2D readImage; +#else +uniform sampler2D readImage; +in vec2 uv; +out vec4 outColor; +#endif + +// https://en.wikipedia.org/wiki/Rec._709#Transfer_characteristics +vec3 EOTF_Curve(vec3 LinearCV, const float LinearFactor, const float Exponent, const float Alpha, const float Beta) { + return mix(LinearCV * LinearFactor, clamp(Alpha * pow(LinearCV, vec3(Exponent)) - (Alpha - 1.0), 0.0, 1.0), step(Beta, LinearCV)); +} + +// https://en.wikipedia.org/wiki/SRGB#Transfer_function_(%22gamma%22) +vec3 EOTF_IEC61966(vec3 LinearCV) { + return EOTF_Curve(LinearCV, 12.92, 1.0 / 2.4, 1.055, 0.0031308);; + //return mix(LinearCV * 12.92, clamp(pow(LinearCV, vec3(1.0/2.4)) * 1.055 - 0.055, 0.0, 1.0), step(0.0031308, LinearCV)); +} +vec3 InverseEOTF_IEC61966(vec3 DisplayCV){ + return max(mix(DisplayCV / 12.92, pow(0.947867 * DisplayCV + 0.0521327, vec3(2.4)), step(0.04045, DisplayCV)), 0.0); +} + +// https://en.wikipedia.org/wiki/Rec._709#Transfer_characteristics +vec3 EOTF_BT709(vec3 LinearCV) { + return EOTF_Curve(LinearCV, 4.5, 0.45, 1.099, 0.018); + //return mix(LinearCV * 4.5, clamp(pow(LinearCV, vec3(0.45)) * 1.099 - 0.099, 0.0, 1.0), step(0.018, LinearCV)); +} + +// https://en.wikipedia.org/wiki/Rec._2020#Transfer_characteristics +vec3 EOTF_BT2020_12Bit(vec3 LinearCV) { + return EOTF_Curve(LinearCV, 4.5, 0.45, 1.0993, 0.0181); +} + +// https://en.wikipedia.org/wiki/DCI-P3 +vec3 EOTF_P3DCI(vec3 LinearCV) { + return pow(LinearCV, vec3(1.0 / 2.6)); +} +// https://en.wikipedia.org/wiki/Adobe_RGB_color_space +vec3 EOTF_Adobe(vec3 LinearCV) { + return pow(LinearCV, vec3(1.0 / 2.2)); +} + +// Using calculations from https://github.com/ampas/aces-dev as reference +const mat3 sRGB_XYZ = mat3( + 0.4124564, 0.3575761, 0.1804375, + 0.2126729, 0.7151522, 0.0721750, + 0.0193339, 0.1191920, 0.9503041 +); +/* +// This Matrix from the acesdev repo is incorrect and produces a strong red-shift +const mat3 XYZ_P3DCI = mat3( + 2.7253940305, -1.0180030062, -0.4401631952, + -0.7951680258, 1.6897320548, 0.0226471906, + 0.0412418914, -0.0876390192, 1.1009293786 +); +*/ +const mat3 XYZ_P3D65 = mat3( + 2.4933963, -0.9313459, -0.4026945, + -0.8294868, 1.7626597, 0.0236246, + 0.0358507, -0.0761827, 0.9570140 +); +const mat3 XYZ_REC2020 = mat3( + 1.7166511880, -0.3556707838, -0.2533662814, + -0.6666843518, 1.6164812366, 0.0157685458, + 0.0176398574, -0.0427706133, 0.9421031212 +); +// https://en.wikipedia.org/wiki/Adobe_RGB_color_space +const mat3 XYZ_AdobeRGB = mat3( + 2.04158790381075, -0.56500697427886, -0.34473135077833, + -0.96924363628088, 1.87596750150772, 0.0415550574071756, + 0.0134442806320311, -0.118362392231018, 1.01517499439121 +); + +// Bradford chromatic adaptation from standard D65 to DCI Cinema White +const mat3 D65_DCI = mat3( + 1.02449672775258, 0.0151635410224164, 0.0196885223342068, + 0.0256121933371582, 0.972586305624413, 0.00471635229242733, + 0.00638423065008769, -0.0122680827367302, 1.14794244517368 +); + +// Bradford chromatic adaptation between D60 and D65 +const mat3 D65_D60 = mat3( + 1.01303, 0.00610531, -0.014971, + 0.00769823, 0.998165, -0.00503203, + -0.00284131, 0.00468516, 0.924507 +); +const mat3 D60_D65 = mat3( + 0.987224, -0.00611327, 0.0159533, + -0.00759836, 1.00186, 0.00533002, + 0.00307257, -0.00509595, 1.08168 +); + +const mat3 sRGB_to_P3DCI = ((sRGB_XYZ) * XYZ_P3D65) * D65_DCI; +//const mat3 sRGB_to_P3DCI = (sRGB_XYZ) * (XYZ_P3DCI); +const mat3 sRGB_to_P3D65 = sRGB_XYZ * XYZ_P3D65; +const mat3 sRGB_to_REC2020 = sRGB_XYZ * XYZ_REC2020; +const mat3 sRGB_to_AdobeRGB = sRGB_XYZ * XYZ_AdobeRGB; + +void main() { + #if CURRENT_COLOR_SPACE != SRGB + #ifdef COMPUTE + ivec2 PixelIndex = ivec2(gl_GlobalInvocationID.xy); + vec4 SourceColor = imageLoad(readImage, PixelIndex); + #else + vec4 SourceColor = texture(readImage, uv); + #endif + SourceColor.rgb = InverseEOTF_IEC61966(SourceColor.rgb); + + vec3 TargetColor = SourceColor.rgb; + + #if CURRENT_COLOR_SPACE == DCI_P3 + // https://en.wikipedia.org/wiki/DCI-P3 + TargetColor = TargetColor * sRGB_to_P3DCI; + TargetColor = EOTF_P3DCI(TargetColor); + + #elif CURRENT_COLOR_SPACE == DISPLAY_P3 + // https://en.wikipedia.org/wiki/DCI-P3#Display_technology + TargetColor = TargetColor * sRGB_to_P3D65; + TargetColor = EOTF_IEC61966(TargetColor); + + #elif CURRENT_COLOR_SPACE == REC2020 + // https://en.wikipedia.org/wiki/Rec._2020 + TargetColor = TargetColor * sRGB_to_REC2020; + TargetColor = EOTF_BT709(TargetColor); + + #elif CURRENT_COLOR_SPACE == ADOBE_RGB + // https://en.wikipedia.org/wiki/Adobe_RGB_color_space + TargetColor = TargetColor * sRGB_to_AdobeRGB; + TargetColor = EOTF_Adobe(TargetColor); + + #endif + #ifdef COMPUTE + imageStore(readImage, PixelIndex, vec4(TargetColor, SourceColor.a)); + #else + outColor = vec4(TargetColor, SourceColor.a); + #endif + #endif +} diff --git a/src/main/resources/colorSpace.vsh b/src/main/resources/colorSpace.vsh new file mode 100644 index 0000000000..ecb0e84688 --- /dev/null +++ b/src/main/resources/colorSpace.vsh @@ -0,0 +1,11 @@ +#version 330 core + +in vec3 iris_Position; +in vec2 iris_UV0; +uniform mat4 projection; +out vec2 uv; + +void main() { + gl_Position = projection * vec4(iris_Position, 1.0); + uv = iris_UV0; +} diff --git a/src/main/resources/iris.accesswidener b/src/main/resources/iris.accesswidener new file mode 100644 index 0000000000..7630f31ee6 --- /dev/null +++ b/src/main/resources/iris.accesswidener @@ -0,0 +1,23 @@ +accessWidener v1 named + +accessible class com/mojang/blaze3d/platform/GlStateManager$BlendState +accessible class com/mojang/blaze3d/platform/GlStateManager$BooleanState +accessible class com/mojang/blaze3d/platform/GlStateManager$TextureState +accessible class com/mojang/blaze3d/platform/GlStateManager$ColorMask +accessible class com/mojang/blaze3d/platform/GlStateManager$DepthState +accessible class net/minecraft/client/renderer/RenderStateShard$TransparencyStateShard +accessible class net/minecraft/client/renderer/RenderType$CompositeState +accessible class net/minecraft/client/renderer/texture/Stitcher$Holder +accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo +accessible class net/minecraft/client/Options$FieldAccess +extendable class net/minecraft/client/renderer/texture/TextureAtlasSprite$Info +accessible method net/minecraft/client/renderer/RenderType create (Ljava/lang/String;Lcom/mojang/blaze3d/vertex/VertexFormat;Lcom/mojang/blaze3d/vertex/VertexFormat$Mode;IZZLnet/minecraft/client/renderer/RenderType$CompositeState;)Lnet/minecraft/client/renderer/RenderType$CompositeRenderType; +accessible field com/mojang/blaze3d/platform/NativeImage pixels J +mutable field net/minecraft/client/renderer/ShaderInstance PROJECTION_MATRIX Lcom/mojang/blaze3d/shaders/Uniform; +mutable field net/minecraft/client/renderer/ShaderInstance MODEL_VIEW_MATRIX Lcom/mojang/blaze3d/shaders/Uniform; +mutable field net/minecraft/client/renderer/ShaderInstance TEXTURE_MATRIX Lcom/mojang/blaze3d/shaders/Uniform; +mutable field net/minecraft/client/renderer/ShaderInstance CHUNK_OFFSET Lcom/mojang/blaze3d/shaders/Uniform; +mutable field net/minecraft/client/renderer/ShaderInstance COLOR_MODULATOR Lcom/mojang/blaze3d/shaders/Uniform; +accessible field net/minecraft/client/renderer/ShaderInstance uniforms Ljava/util/List; +mutable field net/minecraft/client/renderer/LevelRenderer renderBuffers Lnet/minecraft/client/renderer/RenderBuffers; +accessible field com/mojang/blaze3d/platform/GlStateManager$BooleanState enabled Z diff --git a/src/main/resources/mixins.oculus.compat.dh.json b/src/main/resources/mixins.oculus.compat.dh.json new file mode 100644 index 0000000000..b9ab960fd0 --- /dev/null +++ b/src/main/resources/mixins.oculus.compat.dh.json @@ -0,0 +1,13 @@ +{ + "required": true, + "minVersion": "0.8", + "plugin": "net.coderbot.iris.compat.dh.mixin.IrisDHCompatMixinPlugin", + "package": "net.coderbot.iris.compat.dh.mixin", + "compatibilityLevel": "JAVA_8", + "client": [ + "MixinDHApplyShader" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/mixins.oculus.compat.sodium.json b/src/main/resources/mixins.oculus.compat.sodium.json index fa7e920e52..92a4bc7f78 100644 --- a/src/main/resources/mixins.oculus.compat.sodium.json +++ b/src/main/resources/mixins.oculus.compat.sodium.json @@ -1,51 +1,53 @@ { - "package": "net.coderbot.iris.compat.sodium.mixin", - "plugin": "net.coderbot.iris.compat.sodium.mixin.IrisSodiumCompatMixinPlugin", - "minVersion": "0.8", - "required": true, - "compatibilityLevel": "JAVA_8", - "injectors": { - "defaultRequire": 1 - }, - "overwrites": { - "conformVisibility": true - }, - "client": [ - "block_id.MixinChunkBuildBuffers", - "block_id.MixinChunkRenderRebuildTask", - "directional_shading.MixinFlatLightPipeline", - "directional_shading.MixinSmoothLightPipeline", - "options.MixinOptionImpl", - "options.MixinRenderSectionManager", - "options.MixinSodiumGameOptionPages", - "options.MixinSodiumGameOptions", - "options.MixinSodiumOptionsGUI", - "pbr_animation.MixinTextureAtlasSprite", - "separate_ao.MixinBlockRenderer", - "separate_ao.MixinFluidRenderer", - "shader_overrides.MixinBlockRenderPass", - "shader_overrides.MixinGlProgram", - "shader_overrides.MixinRegionChunkRenderer", - "shader_overrides.MixinShaderChunkRenderer", - "shader_overrides.MixinShaderType", - "shader_overrides.ShaderTypeAccessor", - "shadow_map.MixinRegionChunkRenderer", - "shadow_map.MixinRenderSectionManager", - "shadow_map.MixinSodiumWorldRenderer", - "shadow_map.frustum.MixinAdvancedShadowCullingFrustum", - "shadow_map.frustum.MixinBoxCullingFrustum", - "shadow_map.frustum.MixinCullEverythingFrustum", - "shadow_map.frustum.MixinNonCullingFrustum", - "sky.MixinLevelRenderer", - "vertex_format.entity.MixinBufferBuilder_ExtendedVertexFormatCompat", - "vertex_format.ChunkMeshAttributeAccessor", - "vertex_format.MixinFluidRenderer", - "vertex_format.GlVertexAttributeFormatAccessor", - "vertex_format.MixinChunkMeshAttribute", - "vertex_format.MixinGlVertexFormatBuilder", - "vertex_format.MixinModelVertexType", - "vertex_format.MixinRegionChunkRenderer", - "vertex_format.MixinRenderRegionArenas", - "vertex_format.MixinRenderSectionManager" - ] + "package": "net.coderbot.iris.compat.sodium.mixin", + "plugin": "net.coderbot.iris.compat.sodium.mixin.IrisSodiumCompatMixinPlugin", + "required": true, + "compatibilityLevel": "JAVA_8", + "injectors": { + "defaultRequire": 1 + }, + "overwrites": { + "conformVisibility": true + }, + "client": [ + "block_id.MixinChunkBuildBuffers", + "block_id.MixinChunkRenderRebuildTask", + "directional_shading.MixinFlatLightPipeline", + "directional_shading.MixinSmoothLightPipeline", + "options.MixinOptionImpl", + "options.MixinRenderSectionManager", + "options.MixinSodiumGameOptionPages", + "options.MixinSodiumGameOptions", + "options.MixinSodiumOptionsGUI", + "pbr_animation.MixinTextureAtlasSprite", + "separate_ao.MixinBlockRenderer", + "separate_ao.MixinBufferBuilder_IntrinsicSeparateAo", + "separate_ao.MixinFluidRenderer", + "shader_overrides.MixinBlockRenderPass", + "shader_overrides.MixinGlProgram", + "shader_overrides.MixinGlRenderDevice", + "shader_overrides.MixinRegionChunkRenderer", + "shader_overrides.MixinShaderChunkRenderer", + "shader_overrides.MixinShaderType", + "shader_overrides.ShaderTypeAccessor", + "shadow_map.MixinRegionChunkRenderer", + "shadow_map.MixinRenderSectionManager", + "shadow_map.MixinSodiumWorldRenderer", + "shadow_map.frustum.MixinAdvancedShadowCullingFrustum", + "shadow_map.frustum.MixinBoxCullingFrustum", + "shadow_map.frustum.MixinCullEverythingFrustum", + "shadow_map.frustum.MixinNonCullingFrustum", + "sky.MixinLevelRenderer", + "vertex_format.ChunkMeshAttributeAccessor", + "vertex_format.GlVertexAttributeFormatAccessor", + "vertex_format.MixinChunkMeshAttribute", + "vertex_format.MixinFluidRenderer", + "vertex_format.MixinGlAbstractTesselation", + "vertex_format.MixinGlVertexFormatBuilder", + "vertex_format.MixinModelVertexType", + "vertex_format.MixinRegionChunkRenderer", + "vertex_format.MixinRenderRegionArenas", + "vertex_format.MixinRenderSectionManager", + "vertex_format.entity.MixinBufferBuilder_ExtendedVertexFormatCompat" + ] } diff --git a/src/main/resources/mixins.oculus.fixes.maxfpscrash.json b/src/main/resources/mixins.oculus.fixes.maxfpscrash.json index e62f2ccb6b..90c0761384 100644 --- a/src/main/resources/mixins.oculus.fixes.maxfpscrash.json +++ b/src/main/resources/mixins.oculus.fixes.maxfpscrash.json @@ -1,12 +1,13 @@ { - "required": true, - "minVersion": "0.8", - "package": "net.coderbot.iris.mixin", - "compatibilityLevel": "JAVA_8", - "client": [ - "MixinMaxFpsCrashFix" - ], - "injectors": { - "defaultRequire": 1 + "required": true, + "minVersion": "0.8", + "package": "net.coderbot.iris.mixin", + "compatibilityLevel": "JAVA_8", + "client": [ + "MixinMaxFpsCrashFix", + "MixinWindow" + ], + "injectors": { + "defaultRequire": 1 } } diff --git a/src/main/resources/mixins.oculus.json b/src/main/resources/mixins.oculus.json index b8869f8b6a..60d119ac16 100644 --- a/src/main/resources/mixins.oculus.json +++ b/src/main/resources/mixins.oculus.json @@ -2,7 +2,6 @@ "required": true, "minVersion": "0.8", "package": "net.coderbot.iris.mixin", - "plugin": "net.coderbot.iris.mixin.MixinExtrasPlugin", "compatibilityLevel": "JAVA_8", "client": [ "DimensionTypeAccessor", @@ -12,6 +11,8 @@ "LightTextureAccessor", "ProgramTypeAccessor", "MixinBlockStateBehavior", + "MixinBooleanState", + "MixinBiomes", "MixinClientLanguage", "MixinDebugScreenOverlay", "MixinTheEndPortalRenderer", @@ -32,6 +33,7 @@ "MixinItemBlockRenderTypes", "MixinItemInHandRenderer", "MixinLevelRenderer", + "MixinLightningBoltRenderer", "MixinMinecraft_Keybinds", "MixinMinecraft_Images", "MixinMinecraft_PipelineManagement", @@ -43,12 +45,16 @@ "MixinShaderInstance", "MixinTheEndPortalRenderer", "MixinTitleScreen", - "MixinTweakFarPlane", "MixinSystemReport", "MixinUniform", "MixinVertexBuffer", "entity_render_context.MixinBlockEntityRenderDispatcher", + "entity_render_context.MixinCapeLayer", + "entity_render_context.MixinElytraLayer", "entity_render_context.MixinEntityRenderDispatcher", + "entity_render_context.MixinHorseArmorLayer", + "entity_render_context.MixinHumanoidArmorLayer", + "entity_render_context.MixinItemRenderer", "fabulous.MixinDisableFabulousGraphics", "gui.MixinGui", "gui.MixinVideoSettingsScreen", diff --git a/src/main/resources/oculus-batched-entity-rendering.mixins.json b/src/main/resources/oculus-batched-entity-rendering.mixins.json index 66e9c0c54e..af20eac9b8 100644 --- a/src/main/resources/oculus-batched-entity-rendering.mixins.json +++ b/src/main/resources/oculus-batched-entity-rendering.mixins.json @@ -9,6 +9,7 @@ "MixinBufferBuilder", "MixinBufferBuilder_SegmentRendering", "MixinRenderBuffers", + "MixinRenderType", "MixinDebugScreenOverlay", "MixinFishingHookRenderer", "MixinBufferSource",