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