mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-28 16:06:28 +01:00
Start work on shader pipeline system
- Unbulit, untested so far - Will ultimately supersede shader contexts/templating - Laying framework for better compile errors via Span.java
This commit is contained in:
parent
d30ff87203
commit
2325db4cdf
10 changed files with 307 additions and 6 deletions
|
@ -10,13 +10,13 @@ import java.util.regex.Pattern;
|
|||
public class TaggedStruct {
|
||||
|
||||
// https://regexr.com/5t207
|
||||
static final Pattern taggedStruct = Pattern.compile("#\\[(\\w*)]\\s*struct\\s+([\\w\\d]*)\\s*\\{([\\w\\d \\t#\\[\\](),;\\n]*)}\\s*;");
|
||||
public static final Pattern taggedStruct = Pattern.compile("#\\[(\\w*)]\\s*struct\\s+([\\w\\d]*)\\s*\\{([\\w\\d \\t#\\[\\](),;\\n]*)}\\s*;");
|
||||
|
||||
int srcStart, srcEnd;
|
||||
String source;
|
||||
String tag;
|
||||
String name;
|
||||
String body;
|
||||
public int srcStart, srcEnd;
|
||||
public String source;
|
||||
public String tag;
|
||||
public String name;
|
||||
public String body;
|
||||
|
||||
List<TaggedField> fields = new ArrayList<>(4);
|
||||
Map<String, String> fields2Types = new HashMap<>();
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline;
|
||||
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ShaderFunction {
|
||||
|
||||
public static final Pattern assignment = Pattern.compile("(\\w+)\\s*=");
|
||||
|
||||
private final Span returnType;
|
||||
private final Span name;
|
||||
private final Span body;
|
||||
|
||||
public ShaderFunction(Span self, Span returnType, Span name, Span body) {
|
||||
this.returnType = returnType;
|
||||
this.name = name;
|
||||
this.body = body;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline;
|
||||
|
||||
import com.jozufozu.flywheel.backend.loading.Program;
|
||||
import com.jozufozu.flywheel.backend.loading.TaggedField;
|
||||
import com.jozufozu.flywheel.backend.loading.TypeHelper;
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ShaderStruct {
|
||||
|
||||
// https://regexr.com/5t207
|
||||
public static final Pattern struct = Pattern.compile("struct\\s+([\\w\\d]*)\\s*\\{([\\w\\d \\t#\\[\\](),;\\n]*)}\\s*;");
|
||||
|
||||
public Span name;
|
||||
public Span body;
|
||||
|
||||
List<StructField> fields = new ArrayList<>(4);
|
||||
Map<String, String> fields2Types = new HashMap<>();
|
||||
|
||||
public ShaderStruct(Span self, Span name, Span body) {
|
||||
Matcher fielder = StructField.fieldPattern.matcher(body.getValue());
|
||||
|
||||
while (fielder.find()) {
|
||||
fields.add(new StructField(fielder));
|
||||
fields2Types.put(fielder.group(2), fielder.group(1));
|
||||
}
|
||||
}
|
||||
|
||||
public void addPrefixedAttributes(Program builder, String prefix) {
|
||||
for (StructField field : fields) {
|
||||
int attributeCount = TypeHelper.getAttributeCount(field.type);
|
||||
|
||||
builder.addAttribute(prefix + field.name, attributeCount);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.StringReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.jozufozu.flywheel.backend.ShaderSources;
|
||||
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.ErrorSpan;
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.StringSpan;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class SourceFile {
|
||||
// #use "valid_namespace:valid/path_to_file.glsl"
|
||||
private static final Pattern includePattern = Pattern.compile("#use \"(\\w+:[\\w./]+)\"");
|
||||
|
||||
// https://regexr.com/60n3d
|
||||
public static final Pattern functionDeclaration = Pattern.compile("(\\w+)\\s+(\\w+)\\s*\\(([\\w,\\s]*)\\)\\s*\\{");
|
||||
|
||||
public static final Pattern versionDetector = Pattern.compile("#version[^\\n]*");
|
||||
|
||||
public final ResourceLocation name;
|
||||
private final String source;
|
||||
private final ShaderSources loader;
|
||||
|
||||
private final Map<String, ShaderFunction> functions = new HashMap<>();
|
||||
|
||||
public SourceFile(ShaderSources loader, ResourceLocation name, String source) {
|
||||
this.loader = loader;
|
||||
this.name = name;
|
||||
this.source = source;
|
||||
|
||||
parseFunctions();
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
protected void parseFunctions() {
|
||||
Matcher matcher = functionDeclaration.matcher(source);
|
||||
|
||||
while (matcher.find()) {
|
||||
Span type = Span.fromMatcherGroup(this, matcher, 1);
|
||||
Span name = Span.fromMatcherGroup(this, matcher, 2);
|
||||
|
||||
int blockStart = matcher.end();
|
||||
int blockEnd = findEndOfBlock(blockStart);
|
||||
|
||||
Span self;
|
||||
Span body;
|
||||
if (blockEnd > blockStart) {
|
||||
self = new StringSpan(this, matcher.start(), blockEnd);
|
||||
body = new StringSpan(this, blockStart, blockEnd);
|
||||
} else {
|
||||
self = new ErrorSpan(this, matcher.start(), matcher.end());
|
||||
body = new ErrorSpan(this, blockStart);
|
||||
}
|
||||
|
||||
ShaderFunction function = new ShaderFunction(self, type, name, body);
|
||||
|
||||
functions.put(name.getValue(), function);
|
||||
}
|
||||
}
|
||||
|
||||
private int findEndOfBlock(int end) {
|
||||
char[] rest = source.substring(end).toCharArray();
|
||||
|
||||
int blockDepth = 0;
|
||||
for (int i = 0; i < rest.length; i++) {
|
||||
char ch = rest[i];
|
||||
|
||||
if (ch == '{') blockDepth++;
|
||||
if (ch == '}') blockDepth--;
|
||||
|
||||
if (blockDepth < 0) {
|
||||
return end + i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public String printSource() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("Source for shader '").append(name).append("':\n");
|
||||
int i = 1;
|
||||
for (String s : source.split("\n")) {
|
||||
builder.append(String.format("%1$4s: ", i++))
|
||||
.append(s)
|
||||
.append('\n');
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static Stream<String> lines(String s) {
|
||||
return new BufferedReader(new StringReader(s)).lines();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline;
|
||||
|
||||
import com.jozufozu.flywheel.backend.loading.LayoutTag;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class StructField {
|
||||
public static final Pattern fieldPattern = Pattern.compile("(\\S+)\\s*(\\S+);");
|
||||
|
||||
public String name;
|
||||
public String type;
|
||||
public LayoutTag layout;
|
||||
|
||||
public StructField(Matcher fieldMatcher) {
|
||||
type = fieldMatcher.group(2);
|
||||
name = fieldMatcher.group(3);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TaggedField{" +
|
||||
"name='" + name + '\'' +
|
||||
", type='" + type + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline;
|
||||
|
||||
import com.jozufozu.flywheel.core.shader.IMultiProgram;
|
||||
import com.jozufozu.flywheel.core.shader.StateSensitiveMultiProgram;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class WorldShaderPipeline<P extends WorldProgram> {
|
||||
|
||||
@Nullable // TODO: temporary null return
|
||||
public IMultiProgram<P> compile(SourceFile file) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package com.jozufozu.flywheel.backend.pipeline;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
|
@ -0,0 +1,18 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline.span;
|
||||
|
||||
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
||||
|
||||
public class ErrorSpan extends Span {
|
||||
public ErrorSpan(SourceFile in, int loc) {
|
||||
super(in, loc, loc);
|
||||
}
|
||||
|
||||
public ErrorSpan(SourceFile in, int start, int end) {
|
||||
super(in, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return "";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline.span;
|
||||
|
||||
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
public abstract class Span {
|
||||
|
||||
protected final SourceFile in;
|
||||
protected final int start;
|
||||
protected final int end;
|
||||
|
||||
public Span(SourceFile in, int start, int end) {
|
||||
this.in = in;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public SourceFile getSourceFile() {
|
||||
return in;
|
||||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public int getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public abstract String getValue();
|
||||
|
||||
public static Span fromMatcherGroup(SourceFile src, Matcher m, int group) {
|
||||
return new StringSpan(src, m.start(group), m.end(group));
|
||||
}
|
||||
|
||||
public static Span fromMatcher(SourceFile src, Matcher m) {
|
||||
return new StringSpan(src, m.start(), m.end());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline.span;
|
||||
|
||||
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
||||
|
||||
public class StringSpan extends Span {
|
||||
|
||||
public StringSpan(SourceFile in, int start, int end) {
|
||||
super(in, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return in.getSource().substring(start, end);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue