VulkanShader_1.21.10-0.0.4-alpha.jar

Download file
    package net.vulkanmod.vulkan.shader.converter;

import com.mojang.blaze3d.vertex.VertexFormat;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import net.vulkanmod.Initializer;
import net.vulkanmod.vulkan.shader.descriptor.ImageDescriptor;
import net.vulkanmod.vulkan.shader.descriptor.UBO;
import net.vulkanmod.vulkan.shader.layout.AlignedStruct;
import net.vulkanmod.vulkan.shader.layout.Uniform;

public class GLSLParser {
   private Lexer lexer;
   private List<Token> tokens;
   private int currentTokenIdx;
   private Token currentToken;
   private Stage stage;
   State state;
   LinkedList<Node> vsStream;
   LinkedList<Node> fsStream;
   int currentUniformLocation;
   List<UniformBlock> uniformBlocks;
   Map<String, UniformBlock> uniformBlockMap;
   List<Sampler> samplers;
   Map<String, Sampler> samplerMap;
   VertexFormat vertexFormat;
   int currentInAtt;
   int currentOutAtt;
   ArrayList<Attribute> vertInAttributes;
   ArrayList<Attribute> vertOutAttributes;
   ArrayList<Attribute> fragInAttributes;
   ArrayList<Attribute> fragOutAttributes;

   public GLSLParser() {
      this.state = GLSLParser.State.DEFAULT;
      this.vsStream = new LinkedList();
      this.fsStream = new LinkedList();
      this.currentUniformLocation = 0;
      this.uniformBlocks = new ArrayList();
      this.uniformBlockMap = new HashMap();
      this.samplers = new ArrayList();
      this.samplerMap = new HashMap();
      this.currentInAtt = 0;
      this.currentOutAtt = 0;
      this.vertInAttributes = new ArrayList();
      this.vertOutAttributes = new ArrayList();
      this.fragInAttributes = new ArrayList();
      this.fragOutAttributes = new ArrayList();
   }

   public void setVertexFormat(VertexFormat vertexFormat) {
      this.vertexFormat = vertexFormat;
   }

   public void parse(Lexer lexer, Stage stage) {
      this.stage = stage;
      this.lexer = lexer;
      this.tokens = this.lexer.tokenize();
      this.currentTokenIdx = 0;
      this.currentInAtt = 0;
      this.currentOutAtt = 0;
      this.nextToken();
      if (this.currentToken.type != Token.TokenType.PREPROCESSOR && !this.currentToken.value.startsWith("#version")) {
         throw new IllegalStateException("First glsl line must contain version");
      } else {
         this.appendToken(new Token(Token.TokenType.PREPROCESSOR, "#version 450\n"));
         this.nextToken();

         for(; this.currentToken.type != Token.TokenType.EOF; this.nextToken()) {
            switch (this.currentToken.type) {
               case PREPROCESSOR:
                  this.parsePreprocessor();
                  break;
               case IDENTIFIER:
                  switch (this.currentToken.value) {
                     case "layout":
                        this.parseUniformBlock();
                        continue;
                     case "uniform":
                        this.parseUniform();
                        continue;
                     case "in":
                     case "out":
                        this.parseAttribute();
                        continue;
                     default:
                        this.appendToken(this.currentToken);
                        continue;
                  }
               case OPERATOR:
                  this.appendToken(this.currentToken);
                  break;
               default:
                  this.appendToken(this.currentToken);
            }
         }

      }
   }

   private void parsePreprocessor() {
      if (!this.currentToken.value.startsWith("#line")) {
         this.appendToken(this.currentToken);
      }

   }

   private void parseUniform() {
      this.nextToken(true);
      if (this.currentToken.type != Token.TokenType.IDENTIFIER) {
         throw new IllegalStateException();
      } else {
         switch (this.currentToken.value) {
            case "sampler2D" -> this.parseSampler(Sampler.Type.SAMPLER_2D);
            case "samplerCube" -> this.parseSampler(Sampler.Type.SAMPLER_CUBE);
            case "isamplerBuffer" -> this.parseSampler(Sampler.Type.I_SAMPLER_BUFFER);
            default -> throw new IllegalStateException("Unrecognized value: %s".formatted(this.currentToken.value));
         }

      }
   }

   private void parseSampler(Sampler.Type type) {
      this.nextToken(true);
      if (this.currentToken.type != Token.TokenType.IDENTIFIER) {
         throw new IllegalStateException();
      } else {
         String name = this.currentToken.value;
         this.nextToken(true);
         if (this.currentToken.type != Token.TokenType.SEMICOLON) {
            throw new IllegalStateException();
         } else {
            Token next = (Token)this.tokens.get(this.currentTokenIdx);
            if (next.type == Token.TokenType.SPACING) {
               if (Objects.equals(next.value, "\n")) {
                  ++this.currentTokenIdx;
               } else {
                  int i = next.value.indexOf("\n");
                  if (i >= 0) {
                     next.value = next.value.substring(i + 1);
                  }
               }
            }

            Sampler sampler = new Sampler(type, name);
            if (this.samplerMap.get(name) != null) {
               sampler = (Sampler)this.samplerMap.get(name);
            } else {
               sampler.setBinding(this.currentUniformLocation++);
               this.samplerMap.put(name, sampler);
               this.samplers.add(sampler);
            }

            this.appendNode(sampler.getNode());
         }
      }
   }

   private void parseUniformBlock() {
      this.state = GLSLParser.State.LAYOUT;
      this.nextToken(true);
      if (this.currentToken.type != Token.TokenType.LEFT_PARENTHESIS) {
         throw new IllegalStateException();
      } else {
         do {
            this.nextToken(true);
         } while(this.currentToken.type != Token.TokenType.RIGHT_PARENTHESIS);

         this.nextToken(true);
         if (!Objects.equals(this.currentToken.value, "uniform")) {
            throw new IllegalStateException();
         } else {
            this.nextToken(true);
            String name = this.currentToken.value;
            UniformBlock ub = new UniformBlock(name);
            this.nextToken(true);
            if (this.currentToken.type != Token.TokenType.LEFT_BRACE) {
               throw new IllegalStateException();
            } else {
               this.nextToken(true);

               while(this.currentToken.type != Token.TokenType.RIGHT_BRACE) {
                  if (this.currentToken.type != Token.TokenType.IDENTIFIER) {
                     throw new IllegalStateException();
                  }

                  String fieldType = this.currentToken.value;
                  this.nextToken(true);
                  if (this.currentToken.type != Token.TokenType.IDENTIFIER) {
                     throw new IllegalStateException();
                  }

                  String fieldName = this.currentToken.value;
                  this.nextToken(true);
                  if (this.currentToken.type != Token.TokenType.SEMICOLON) {
                     throw new IllegalStateException();
                  }

                  ub.addField(new UniformBlock.Field(fieldType, fieldName));
                  this.nextToken(true);
               }

               this.nextToken(true);
               switch (this.currentToken.type) {
                  case IDENTIFIER:
                     ub.setAlias(this.currentToken.value);
                     this.nextToken(true);
                     if (this.currentToken.type != Token.TokenType.SEMICOLON) {
                        throw new IllegalStateException();
                     }
                  case SEMICOLON:
                     Token next = (Token)this.tokens.get(this.currentTokenIdx);
                     if (next.type == Token.TokenType.SPACING) {
                        if (Objects.equals(next.value, "\n")) {
                           ++this.currentTokenIdx;
                        } else {
                           int i = next.value.indexOf("\n");
                           if (i >= 0) {
                              next.value = next.value.substring(i + 1);
                           }
                        }
                     }

                     if (this.uniformBlockMap.get(ub.name) != null) {
                        ub = (UniformBlock)this.uniformBlockMap.get(ub.name);
                     } else {
                        ub.setBinding(this.currentUniformLocation++);
                        this.uniformBlockMap.put(ub.name, ub);
                        this.uniformBlocks.add(ub);
                     }

                     this.appendNode(ub.getNode());
                     return;
                  default:
                     throw new IllegalStateException();
               }
            }
         }
      }
   }

   private void parseAttribute() {
      this.state = GLSLParser.State.ATTRIBUTE;
      String ioType = this.currentToken.value;
      this.nextToken(true);
      if (this.currentToken.type != Token.TokenType.IDENTIFIER) {
         throw new IllegalStateException();
      } else {
         String type = this.currentToken.value;
         this.nextToken(true);
         if (this.currentToken.type != Token.TokenType.IDENTIFIER) {
            throw new IllegalStateException();
         } else {
            String id = this.currentToken.value;
            this.nextToken(true);
            if (this.currentToken.type != Token.TokenType.SEMICOLON) {
               throw new IllegalStateException();
            } else {
               Token next = (Token)this.tokens.get(this.currentTokenIdx);
               if (next.type == Token.TokenType.SPACING) {
                  if (Objects.equals(next.value, "\n")) {
                     ++this.currentTokenIdx;
                  } else {
                     int i = next.value.indexOf("\n");
                     if (i >= 0) {
                        next.value = next.value.substring(i + 1);
                     }
                  }
               }

               Attribute attribute;
               attribute = new Attribute(ioType, type, id);
               label68:
               switch (this.stage.ordinal()) {
                  case 0:
                     switch (attribute.ioType) {
                        case "in":
                           int attributeLocation;
                           if (this.vertexFormat != null) {
                              List<String> attributeNames = this.vertexFormat.getElementAttributeNames();
                              attributeLocation = attributeNames.indexOf(attribute.id);
                              if (attributeLocation == -1) {
                                 Initializer.LOGGER.error("Element %s not found in elements %s".formatted(attribute.id, attributeNames));
                                 attributeLocation = this.currentInAtt;
                              }

                              ++this.currentInAtt;
                           } else {
                              attributeLocation = this.currentInAtt++;
                           }

                           attribute.setLocation(attributeLocation);
                           this.vertInAttributes.add(attribute);
                           break label68;
                        case "out":
                           attribute.setLocation(this.currentOutAtt++);
                           this.vertOutAttributes.add(attribute);
                           break label68;
                        default:
                           throw new IllegalStateException();
                     }
                  case 1:
                     switch (attribute.ioType) {
                        case "in":
                           Attribute vertAttribute = this.getVertAttribute(attribute);
                           if (vertAttribute == null) {
                              return;
                           }

                           attribute.setLocation(vertAttribute.location);
                           this.fragInAttributes.add(attribute);
                           break;
                        case "out":
                           if (this.currentOutAtt > 0) {
                              throw new UnsupportedOperationException("Multiple outputs not currently supported.");
                           }

                           attribute.setLocation(this.currentOutAtt++);
                           this.fragOutAttributes.add(attribute);
                           break;
                        default:
                           throw new IllegalStateException();
                     }
               }

               this.appendNode(attribute.getNode());
            }
         }
      }
   }

   private Attribute getVertAttribute(Attribute attribute) {
      Attribute vertAttribute = null;

      for(Attribute attribute1 : this.vertOutAttributes) {
         if (Objects.equals(attribute1.id, attribute.id)) {
            vertAttribute = attribute1;
         }
      }

      if (vertAttribute == null) {
      }

      return vertAttribute;
   }

   private void nextToken() {
      this.nextToken(false);
   }

   private void nextToken(boolean skipSpace) {
      for(this.currentToken = (Token)this.tokens.get(this.currentTokenIdx++); skipSpace && this.currentToken.type == Token.TokenType.SPACING; this.currentToken = (Token)this.tokens.get(this.currentTokenIdx++)) {
      }

   }

   private void appendToken(Token token) {
      this.appendNode(GLSLParser.Node.fromToken(token));
   }

   private void appendNode(Node node) {
      switch (this.stage.ordinal()) {
         case 0 -> this.vsStream.add(node);
         case 1 -> this.fsStream.add(node);
      }

   }

   public String getOutput(Stage stage) {
      StringBuilder stringBuilder = new StringBuilder();
      LinkedList var10000;
      switch (stage.ordinal()) {
         case 0 -> var10000 = this.vsStream;
         case 1 -> var10000 = this.fsStream;
         default -> throw new MatchException((String)null, (Throwable)null);
      }

      LinkedList<Node> stream = var10000;
      Node node = (Node)stream.getFirst();
      stringBuilder.append(node.value);
      stringBuilder.append("\n");
      switch (stage.ordinal()) {
         case 0:
            stringBuilder.append("#define gl_VertexID gl_VertexIndex\n\n");
         default:
            stringBuilder.append("#define sampler sampler1\n\n");
            stringBuilder.append("#define sample sample1\n\n");

            for(int i = 1; i < stream.size(); ++i) {
               node = (Node)stream.get(i);
               stringBuilder.append(node.value);
            }

            return stringBuilder.toString();
      }
   }

   public UBO[] createUBOs() {
      if (this.uniformBlockMap.isEmpty()) {
         return new UBO[0];
      } else {
         int uboCount = this.uniformBlockMap.size();
         UBO[] ubos = new UBO[uboCount];
         int i = 0;

         for(UniformBlock uniformBlock : this.uniformBlocks) {
            AlignedStruct.Builder builder = new AlignedStruct.Builder();

            for(UniformBlock.Field field : uniformBlock.fields) {
               String name = field.name;
               String type = field.type;
               Uniform.Info uniformInfo = Uniform.createUniformInfo(type, name);
               uniformInfo.setupSupplier();
               builder.addUniformInfo(uniformInfo);
            }

            ubos[i] = builder.buildUBO(uniformBlock.name, uniformBlock.binding, Integer.MAX_VALUE);
            ++i;
         }

         return ubos;
      }
   }

   public List<ImageDescriptor> getSamplerList() {
      List<ImageDescriptor> imageDescriptors = new ObjectArrayList();
      int imageIdx = 0;

      for(Sampler sampler : this.samplers) {
         byte var10000;
         switch (sampler.type) {
            case SAMPLER_2D:
            case SAMPLER_CUBE:
               var10000 = 1;
               break;
            case I_SAMPLER_BUFFER:
               var10000 = 4;
               break;
            default:
               throw new MatchException((String)null, (Throwable)null);
         }

         int descriptorType = var10000;
         imageDescriptors.add(new ImageDescriptor(sampler.binding, "sampler2D", sampler.id, imageIdx, descriptorType));
         ++imageIdx;
      }

      return imageDescriptors;
   }

   static enum State {
      LAYOUT,
      UNIFORM,
      UNIFORM_BLOCK,
      ATTRIBUTE,
      DEFAULT;

      // $FF: synthetic method
      private static State[] $values() {
         return new State[]{LAYOUT, UNIFORM, UNIFORM_BLOCK, ATTRIBUTE, DEFAULT};
      }
   }

   public static enum Stage {
      VERTEX,
      FRAGMENT;

      // $FF: synthetic method
      private static Stage[] $values() {
         return new Stage[]{VERTEX, FRAGMENT};
      }
   }

   public static class Node {
      String type;
      String value;

      public Node(String type, String value) {
         this.type = type;
         this.value = value;
      }

      public static Node fromToken(Token token) {
         return new Node("token:%s".formatted(token.type), token.value);
      }
   }
}
    
Download file