mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-27 23:47:09 +01:00
Rewrite the layout API
This commit is contained in:
parent
c8590629a1
commit
2cb68fea95
29 changed files with 529 additions and 193 deletions
|
@ -26,11 +26,11 @@ public interface InstanceType<I extends Instance> {
|
||||||
* @deprecated Use {@link #layout()} instead.
|
* @deprecated Use {@link #layout()} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
BufferLayout getLayout();
|
BufferLayout oldLayout();
|
||||||
|
|
||||||
Layout layout();
|
Layout layout();
|
||||||
|
|
||||||
InstanceWriter<I> getWriter();
|
InstanceWriter<I> writer();
|
||||||
|
|
||||||
ResourceLocation vertexShader();
|
ResourceLocation vertexShader();
|
||||||
|
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
package com.jozufozu.flywheel.api.layout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A single element in a {@link Layout}.
|
|
||||||
*/
|
|
||||||
public sealed interface Element {
|
|
||||||
String name();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple vector of floats, i.e. {@code vec3}, {@code dvec2}.
|
|
||||||
* <br>
|
|
||||||
* If {@link #type} is an integral type, the shader will implicitly convert it to a float without normalization.
|
|
||||||
* If you want normalization, use {@link NormalizedVector}.
|
|
||||||
*
|
|
||||||
* @param name The name of the element to be used in the shader.
|
|
||||||
* @param type The backing type of the element.
|
|
||||||
* @param size The number of components in the vector.
|
|
||||||
*/
|
|
||||||
record Vector(String name, FloatType type, VectorSize size) implements Element {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A vector of integers, i.e. {@code ivec3}, {@code uvec2}.
|
|
||||||
* <br>
|
|
||||||
* All backing types will be presented as either {@code int} or {@code uint} in the shader,
|
|
||||||
* depending on the signedness of the type.
|
|
||||||
*
|
|
||||||
* @param name The name of the element to be used in the shader.
|
|
||||||
* @param type The backing type of the element.
|
|
||||||
* @param size The number of components in the vector.
|
|
||||||
*/
|
|
||||||
record IntegerVector(String name, IntegerType type, VectorSize size) implements Element {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A vector of integers, normalized and presented as a float in the shader.
|
|
||||||
*
|
|
||||||
* @param name The name of the element to be used in the shader.
|
|
||||||
* @param type The backing type of the element.
|
|
||||||
* @param size The number of components in the vector.
|
|
||||||
*/
|
|
||||||
record NormalizedVector(String name, IntegerType type, VectorSize size) implements Element {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A matrix of 32-bit floating point numbers, i.e. {@code mat3}, {@code mat2x4}.
|
|
||||||
*
|
|
||||||
* @param name The name of the element to be used in the shader.
|
|
||||||
* @param rows The number of rows in the matrix.
|
|
||||||
* @param cols The number of columns in the matrix.
|
|
||||||
*/
|
|
||||||
record Matrix(String name, MatrixSize rows, MatrixSize cols) implements Element {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.jozufozu.flywheel.api.layout;
|
||||||
|
|
||||||
|
public sealed interface ElementType permits ScalarElementType, VectorElementType, MatrixElementType {
|
||||||
|
int byteSize();
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.jozufozu.flywheel.api.layout;
|
||||||
|
|
||||||
|
public enum FloatRepr implements ValueRepr {
|
||||||
|
BYTE(Byte.BYTES),
|
||||||
|
NORMALIZED_BYTE(Byte.BYTES),
|
||||||
|
UNSIGNED_BYTE(Byte.BYTES),
|
||||||
|
NORMALIZED_UNSIGNED_BYTE(Byte.BYTES),
|
||||||
|
SHORT(Short.BYTES),
|
||||||
|
NORMALIZED_SHORT(Short.BYTES),
|
||||||
|
UNSIGNED_SHORT(Short.BYTES),
|
||||||
|
NORMALIZED_UNSIGNED_SHORT(Short.BYTES),
|
||||||
|
INT(Integer.BYTES),
|
||||||
|
NORMALIZED_INT(Integer.BYTES),
|
||||||
|
UNSIGNED_INT(Integer.BYTES),
|
||||||
|
NORMALIZED_UNSIGNED_INT(Integer.BYTES),
|
||||||
|
FLOAT(Float.BYTES);
|
||||||
|
|
||||||
|
private final int byteSize;
|
||||||
|
|
||||||
|
FloatRepr(int byteSize) {
|
||||||
|
this.byteSize = byteSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int byteSize() {
|
||||||
|
return byteSize;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
package com.jozufozu.flywheel.api.layout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The backing type of traditional floating point vertex attributes.
|
|
||||||
* <br>
|
|
||||||
* Integral types are implicitly converted to floats in the shader.
|
|
||||||
*/
|
|
||||||
public enum FloatType {
|
|
||||||
BYTE,
|
|
||||||
UNSIGNED_BYTE,
|
|
||||||
SHORT,
|
|
||||||
UNSIGNED_SHORT,
|
|
||||||
INT,
|
|
||||||
UNSIGNED_INT,
|
|
||||||
HALF_FLOAT,
|
|
||||||
FLOAT,
|
|
||||||
DOUBLE,
|
|
||||||
FIXED,
|
|
||||||
}
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.jozufozu.flywheel.api.layout;
|
||||||
|
|
||||||
|
public enum IntegerRepr implements ValueRepr {
|
||||||
|
BYTE(Byte.BYTES),
|
||||||
|
SHORT(Short.BYTES),
|
||||||
|
INT(Integer.BYTES);
|
||||||
|
|
||||||
|
private final int byteSize;
|
||||||
|
|
||||||
|
IntegerRepr(int byteSize) {
|
||||||
|
this.byteSize = byteSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int byteSize() {
|
||||||
|
return byteSize;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
package com.jozufozu.flywheel.api.layout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Integral types backing layout elements.
|
|
||||||
*/
|
|
||||||
public enum IntegerType {
|
|
||||||
BYTE,
|
|
||||||
UNSIGNED_BYTE,
|
|
||||||
SHORT,
|
|
||||||
UNSIGNED_SHORT,
|
|
||||||
INT,
|
|
||||||
UNSIGNED_INT
|
|
||||||
}
|
|
|
@ -1,6 +1,27 @@
|
||||||
package com.jozufozu.flywheel.api.layout;
|
package com.jozufozu.flywheel.api.layout;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record Layout(List<Element> elements) {
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
public interface Layout {
|
||||||
|
int MAX_ELEMENT_NAME_LENGTH = 896;
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
List<Element> elements();
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
Map<String, ElementType> asMap();
|
||||||
|
|
||||||
|
int byteSize();
|
||||||
|
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
interface Element {
|
||||||
|
String name();
|
||||||
|
|
||||||
|
ElementType type();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.jozufozu.flywheel.api.layout;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.impl.layout.LayoutBuilderImpl;
|
||||||
|
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
public interface LayoutBuilder {
|
||||||
|
LayoutBuilder scalar(String name, ValueRepr repr);
|
||||||
|
|
||||||
|
LayoutBuilder vector(String name, ValueRepr repr, @Range(from = 2, to = 4) int size);
|
||||||
|
|
||||||
|
LayoutBuilder matrix(String name, FloatRepr repr, @Range(from = 2, to = 4) int rows, @Range(from = 2, to = 4) int columns);
|
||||||
|
|
||||||
|
LayoutBuilder matrix(String name, FloatRepr repr, @Range(from = 2, to = 4) int size);
|
||||||
|
|
||||||
|
Layout build();
|
||||||
|
|
||||||
|
static LayoutBuilder create() {
|
||||||
|
return new LayoutBuilderImpl();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.jozufozu.flywheel.api.layout;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
public non-sealed interface MatrixElementType extends ElementType {
|
||||||
|
FloatRepr repr();
|
||||||
|
|
||||||
|
@Range(from = 2, to = 4)
|
||||||
|
int rows();
|
||||||
|
|
||||||
|
@Range(from = 2, to = 4)
|
||||||
|
int columns();
|
||||||
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
package com.jozufozu.flywheel.api.layout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The size of a single dimension in a matrix.
|
|
||||||
*/
|
|
||||||
public enum MatrixSize {
|
|
||||||
TWO,
|
|
||||||
THREE,
|
|
||||||
FOUR,
|
|
||||||
}
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.jozufozu.flywheel.api.layout;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
public non-sealed interface ScalarElementType extends ElementType {
|
||||||
|
ValueRepr repr();
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.jozufozu.flywheel.api.layout;
|
||||||
|
|
||||||
|
public enum UnsignedIntegerRepr implements ValueRepr {
|
||||||
|
UNSIGNED_BYTE(Byte.BYTES),
|
||||||
|
UNSIGNED_SHORT(Short.BYTES),
|
||||||
|
UNSIGNED_INT(Integer.BYTES);
|
||||||
|
|
||||||
|
private final int byteSize;
|
||||||
|
|
||||||
|
UnsignedIntegerRepr(int byteSize) {
|
||||||
|
this.byteSize = byteSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int byteSize() {
|
||||||
|
return byteSize;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.jozufozu.flywheel.api.layout;
|
||||||
|
|
||||||
|
public sealed interface ValueRepr permits IntegerRepr, UnsignedIntegerRepr, FloatRepr {
|
||||||
|
int byteSize();
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.jozufozu.flywheel.api.layout;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
public non-sealed interface VectorElementType extends ElementType {
|
||||||
|
ValueRepr repr();
|
||||||
|
|
||||||
|
@Range(from = 2, to = 4)
|
||||||
|
int size();
|
||||||
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
package com.jozufozu.flywheel.api.layout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of components in a vector.
|
|
||||||
* <br>
|
|
||||||
* If the vector size is 1, the attribute is presented as a scalar.
|
|
||||||
*/
|
|
||||||
public enum VectorSize {
|
|
||||||
ONE,
|
|
||||||
TWO,
|
|
||||||
THREE,
|
|
||||||
FOUR,
|
|
||||||
}
|
|
|
@ -34,7 +34,7 @@ public class IndirectComponent implements SourceComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IndirectComponent create(InstanceType<?> instanceType) {
|
public static IndirectComponent create(InstanceType<?> instanceType) {
|
||||||
return new IndirectComponent(instanceType.getLayout().layoutItems);
|
return new IndirectComponent(instanceType.oldLayout().layoutItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class InstancedArraysComponent implements SourceComponent {
|
||||||
|
|
||||||
public InstancedArraysComponent(Pipeline.InstanceAssemblerContext ctx) {
|
public InstancedArraysComponent(Pipeline.InstanceAssemblerContext ctx) {
|
||||||
this.layoutItems = ctx.instanceType()
|
this.layoutItems = ctx.instanceType()
|
||||||
.getLayout().layoutItems;
|
.oldLayout().layoutItems;
|
||||||
this.baseIndex = ctx.baseAttribute();
|
this.baseIndex = ctx.baseAttribute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ public class IndirectCullingGroup<I extends Instance> {
|
||||||
applyProgram = programs.getApplyProgram();
|
applyProgram = programs.getApplyProgram();
|
||||||
drawProgram = programs.getIndirectProgram(instanceType, Contexts.DEFAULT);
|
drawProgram = programs.getIndirectProgram(instanceType, Contexts.DEFAULT);
|
||||||
|
|
||||||
objectStride = instanceType.getLayout()
|
objectStride = instanceType.oldLayout()
|
||||||
.getStride() + IndirectBuffers.INT_SIZE;
|
.getStride() + IndirectBuffers.INT_SIZE;
|
||||||
|
|
||||||
buffers = new IndirectBuffers(objectStride);
|
buffers = new IndirectBuffers(objectStride);
|
||||||
|
|
|
@ -20,10 +20,10 @@ public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I>
|
||||||
|
|
||||||
public IndirectInstancer(InstanceType<I> type) {
|
public IndirectInstancer(InstanceType<I> type) {
|
||||||
super(type);
|
super(type);
|
||||||
long instanceStride = type.getLayout()
|
long instanceStride = type.oldLayout()
|
||||||
.getStride();
|
.getStride();
|
||||||
this.objectStride = instanceStride + IndirectBuffers.INT_SIZE;
|
this.objectStride = instanceStride + IndirectBuffers.INT_SIZE;
|
||||||
writer = this.type.getWriter();
|
writer = this.type.writer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDraw(IndirectDraw draw) {
|
public void addDraw(IndirectDraw draw) {
|
||||||
|
|
|
@ -28,9 +28,9 @@ public class InstancedInstancer<I extends Instance> extends AbstractInstancer<I>
|
||||||
|
|
||||||
public InstancedInstancer(InstanceType<I> type) {
|
public InstancedInstancer(InstanceType<I> type) {
|
||||||
super(type);
|
super(type);
|
||||||
instanceFormat = type.getLayout();
|
instanceFormat = type.oldLayout();
|
||||||
instanceStride = instanceFormat.getStride();
|
instanceStride = instanceFormat.getStride();
|
||||||
writer = type.getWriter();
|
writer = type.writer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAttributeCount() {
|
public int getAttributeCount() {
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
package com.jozufozu.flywheel.impl.layout;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.layout.FloatRepr;
|
||||||
|
import com.jozufozu.flywheel.api.layout.Layout;
|
||||||
|
import com.jozufozu.flywheel.api.layout.Layout.Element;
|
||||||
|
import com.jozufozu.flywheel.api.layout.LayoutBuilder;
|
||||||
|
import com.jozufozu.flywheel.api.layout.ValueRepr;
|
||||||
|
import com.jozufozu.flywheel.impl.layout.LayoutImpl.ElementImpl;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
|
|
||||||
|
public class LayoutBuilderImpl implements LayoutBuilder {
|
||||||
|
private static final Set<String> GLSL_KEYWORDS = Set.of(
|
||||||
|
// standard keywords
|
||||||
|
"const", "uniform", "buffer", "shared", "attribute", "varying",
|
||||||
|
"coherent", "volatile", "restrict", "readonly", "writeonly",
|
||||||
|
"atomic_uint",
|
||||||
|
"layout",
|
||||||
|
"centroid", "flat", "smooth", "noperspective",
|
||||||
|
"patch", "sample",
|
||||||
|
"invariant", "precise",
|
||||||
|
"break", "continue", "do", "for", "while", "switch", "case", "default",
|
||||||
|
"if", "else",
|
||||||
|
"subroutine",
|
||||||
|
"in", "out", "inout",
|
||||||
|
"int", "void", "bool", "true", "false", "float", "double",
|
||||||
|
"discard", "return",
|
||||||
|
"vec2", "vec3", "vec4", "ivec2", "ivec3", "ivec4", "bvec2", "bvec3", "bvec4",
|
||||||
|
"uint", "uvec2", "uvec3", "uvec4",
|
||||||
|
"dvec2", "dvec3", "dvec4",
|
||||||
|
"mat2", "mat3", "mat4",
|
||||||
|
"mat2x2", "mat2x3", "mat2x4",
|
||||||
|
"mat3x2", "mat3x3", "mat3x4",
|
||||||
|
"mat4x2", "mat4x3", "mat4x4",
|
||||||
|
"dmat2", "dmat3", "dmat4",
|
||||||
|
"dmat2x2", "dmat2x3", "dmat2x4",
|
||||||
|
"dmat3x2", "dmat3x3", "dmat3x4",
|
||||||
|
"dmat4x2", "dmat4x3", "dmat4x4",
|
||||||
|
"lowp", "mediump", "highp", "precision",
|
||||||
|
"sampler1D", "sampler1DShadow", "sampler1DArray", "sampler1DArrayShadow",
|
||||||
|
"isampler1D", "isampler1DArray", "usampler1D", "usampler1DArray",
|
||||||
|
"sampler2D", "sampler2DShadow", "sampler2DArray", "sampler2DArrayShadow",
|
||||||
|
"isampler2D", "isampler2DArray", "usampler2D", "usampler2DArray",
|
||||||
|
"sampler2DRect", "sampler2DRectShadow", "isampler2DRect", "usampler2DRect",
|
||||||
|
"sampler2DMS", "isampler2DMS", "usampler2DMS",
|
||||||
|
"sampler2DMSArray", "isampler2DMSArray", "usampler2DMSArray",
|
||||||
|
"sampler3D", "isampler3D", "usampler3D",
|
||||||
|
"samplerCube", "samplerCubeShadow", "isamplerCube", "usamplerCube",
|
||||||
|
"samplerCubeArray", "samplerCubeArrayShadow",
|
||||||
|
"isamplerCubeArray", "usamplerCubeArray",
|
||||||
|
"samplerBuffer", "isamplerBuffer", "usamplerBuffer",
|
||||||
|
"image1D", "iimage1D", "uimage1D",
|
||||||
|
"image1DArray", "iimage1DArray", "uimage1DArray",
|
||||||
|
"image2D", "iimage2D", "uimage2D",
|
||||||
|
"image2DArray", "iimage2DArray", "uimage2DArray",
|
||||||
|
"image2DRect", "iimage2DRect", "uimage2DRect",
|
||||||
|
"image2DMS", "iimage2DMS", "uimage2DMS",
|
||||||
|
"image2DMSArray", "iimage2DMSArray", "uimage2DMSArray",
|
||||||
|
"image3D", "iimage3D", "uimage3D",
|
||||||
|
"imageCube", "iimageCube", "uimageCube",
|
||||||
|
"imageCubeArray", "iimageCubeArray", "uimageCubeArray",
|
||||||
|
"imageBuffer", "iimageBuffer", "uimageBuffer",
|
||||||
|
"struct",
|
||||||
|
// Vulkan keywords
|
||||||
|
"texture1D", "texture1DArray",
|
||||||
|
"itexture1D", "itexture1DArray", "utexture1D", "utexture1DArray",
|
||||||
|
"texture2D", "texture2DArray",
|
||||||
|
"itexture2D", "itexture2DArray", "utexture2D", "utexture2DArray",
|
||||||
|
"texture2DRect", "itexture2DRect", "utexture2DRect",
|
||||||
|
"texture2DMS", "itexture2DMS", "utexture2DMS",
|
||||||
|
"texture2DMSArray", "itexture2DMSArray", "utexture2DMSArray",
|
||||||
|
"texture3D", "itexture3D", "utexture3D",
|
||||||
|
"textureCube", "itextureCube", "utextureCube",
|
||||||
|
"textureCubeArray", "itextureCubeArray", "utextureCubeArray",
|
||||||
|
"textureBuffer", "itextureBuffer", "utextureBuffer",
|
||||||
|
"sampler", "samplerShadow",
|
||||||
|
"subpassInput", "isubpassInput", "usubpassInput",
|
||||||
|
"subpassInputMS", "isubpassInputMS", "usubpassInputMS",
|
||||||
|
// reserved keywords
|
||||||
|
"common", "partition", "active",
|
||||||
|
"asm",
|
||||||
|
"class", "union", "enum", "typedef", "template", "this",
|
||||||
|
"resource",
|
||||||
|
"goto",
|
||||||
|
"inline", "noinline", "public", "static", "extern", "external", "interface",
|
||||||
|
"long", "short", "half", "fixed", "unsigned", "superp",
|
||||||
|
"input", "output",
|
||||||
|
"hvec2", "hvec3", "hvec4", "fvec2", "fvec3", "fvec4",
|
||||||
|
"filter",
|
||||||
|
"sizeof", "cast",
|
||||||
|
"namespace", "using",
|
||||||
|
"sampler3DRect"
|
||||||
|
);
|
||||||
|
|
||||||
|
private final List<Element> elements = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LayoutBuilder scalar(String name, ValueRepr repr) {
|
||||||
|
elements.add(new ElementImpl(name, new ScalarElementTypeImpl(repr)));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LayoutBuilder vector(String name, ValueRepr repr, @Range(from = 2, to = 4) int size) {
|
||||||
|
elements.add(new ElementImpl(name, new VectorElementTypeImpl(repr, size)));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LayoutBuilder matrix(String name, FloatRepr repr, @Range(from = 2, to = 4) int rows, @Range(from = 2, to = 4) int columns) {
|
||||||
|
elements.add(new ElementImpl(name, new MatrixElementTypeImpl(repr, rows, columns)));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LayoutBuilder matrix(String name, FloatRepr repr, @Range(from = 2, to = 4) int size) {
|
||||||
|
return matrix(name, repr, size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Layout build() {
|
||||||
|
Object2IntMap<String> name2IndexMap = new Object2IntOpenHashMap<>();
|
||||||
|
name2IndexMap.defaultReturnValue(-1);
|
||||||
|
|
||||||
|
for (int i = 0; i < elements.size(); i++) {
|
||||||
|
Element element = elements.get(i);
|
||||||
|
String name = element.name();
|
||||||
|
|
||||||
|
if (GLSL_KEYWORDS.contains(name)) {
|
||||||
|
throw new IllegalStateException("Element at index " + i + " has invalid name '" + name + "'; this is a GLSL keyword!");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < name.length(); j++) {
|
||||||
|
char c = name.charAt(j);
|
||||||
|
if (j == 0) {
|
||||||
|
if (!isLetter(c)) {
|
||||||
|
throw new IllegalStateException("Element at index " + i + " has invalid name '" + name + "'! Names must start with a letter.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!isValidNameCharacter(c)) {
|
||||||
|
throw new IllegalStateException("Element at index " + i + " has invalid name '" + name + "'! Names must only contain letters, digits, and underscores.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String lowerCaseName = name.toLowerCase(Locale.ROOT);
|
||||||
|
if (lowerCaseName.startsWith("gl") || lowerCaseName.startsWith("flw")) {
|
||||||
|
throw new IllegalStateException("Element at index " + i + " has invalid name '" + name + "'! Names must not start with 'gl' or 'flw' (case-insensitive).");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.length() > Layout.MAX_ELEMENT_NAME_LENGTH) {
|
||||||
|
throw new IllegalStateException("Element at index " + i + " has invalid name '" + name + "'! Names must not be longer than " + Layout.MAX_ELEMENT_NAME_LENGTH + " characters.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int prevIndex = name2IndexMap.putIfAbsent(name, i);
|
||||||
|
if (prevIndex != -1) {
|
||||||
|
throw new IllegalStateException("Elements at indices " + prevIndex + " and " + i + " have the same name; this is not valid!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LayoutImpl(List.copyOf(elements));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isValidNameCharacter(char c) {
|
||||||
|
return isLetter(c) || c >= '0' && c <= '9' || c == '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isLetter(char c) {
|
||||||
|
return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.jozufozu.flywheel.impl.layout;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.layout.ElementType;
|
||||||
|
import com.jozufozu.flywheel.api.layout.Layout;
|
||||||
|
|
||||||
|
final class LayoutImpl implements Layout {
|
||||||
|
private final List<Element> elements;
|
||||||
|
private final Map<String, ElementType> map;
|
||||||
|
private final int byteSize;
|
||||||
|
|
||||||
|
LayoutImpl(List<Element> elements) {
|
||||||
|
this.elements = elements;
|
||||||
|
|
||||||
|
map = new HashMap<>();
|
||||||
|
int byteSize = 0;
|
||||||
|
for (Element element : this.elements) {
|
||||||
|
map.put(element.name(), element.type());
|
||||||
|
byteSize += element.type().byteSize();
|
||||||
|
}
|
||||||
|
this.byteSize = byteSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Unmodifiable
|
||||||
|
public List<Element> elements() {
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Unmodifiable
|
||||||
|
public Map<String, ElementType> asMap() {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int byteSize() {
|
||||||
|
return byteSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
record ElementImpl(String name, ElementType type) implements Element {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.jozufozu.flywheel.impl.layout;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.layout.FloatRepr;
|
||||||
|
import com.jozufozu.flywheel.api.layout.MatrixElementType;
|
||||||
|
|
||||||
|
final class MatrixElementTypeImpl implements MatrixElementType {
|
||||||
|
private final FloatRepr repr;
|
||||||
|
@Range(from = 2, to = 4)
|
||||||
|
private final int rows;
|
||||||
|
@Range(from = 2, to = 4)
|
||||||
|
private final int columns;
|
||||||
|
private final int byteSize;
|
||||||
|
|
||||||
|
MatrixElementTypeImpl(FloatRepr repr, @Range(from = 2, to = 4) int rows, @Range(from = 2, to = 4) int columns) {
|
||||||
|
if (rows < 2 || rows > 4) {
|
||||||
|
throw new IllegalArgumentException("Matrix element row count must be in range [2, 4]!");
|
||||||
|
}
|
||||||
|
if (columns < 2 || columns > 4) {
|
||||||
|
throw new IllegalArgumentException("Matrix element column count must be in range [2, 4]!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.repr = repr;
|
||||||
|
this.rows = rows;
|
||||||
|
this.columns = columns;
|
||||||
|
byteSize = repr.byteSize() * rows * columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FloatRepr repr() {
|
||||||
|
return repr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Range(from = 2, to = 4)
|
||||||
|
public int rows() {
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Range(from = 2, to = 4)
|
||||||
|
public int columns() {
|
||||||
|
return columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int byteSize() {
|
||||||
|
return byteSize;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.jozufozu.flywheel.impl.layout;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.layout.ScalarElementType;
|
||||||
|
import com.jozufozu.flywheel.api.layout.ValueRepr;
|
||||||
|
|
||||||
|
final class ScalarElementTypeImpl implements ScalarElementType {
|
||||||
|
private final ValueRepr repr;
|
||||||
|
private final int byteSize;
|
||||||
|
|
||||||
|
ScalarElementTypeImpl(ValueRepr repr) {
|
||||||
|
this.repr = repr;
|
||||||
|
byteSize = repr.byteSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueRepr repr() {
|
||||||
|
return repr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int byteSize() {
|
||||||
|
return byteSize;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.jozufozu.flywheel.impl.layout;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.layout.ValueRepr;
|
||||||
|
import com.jozufozu.flywheel.api.layout.VectorElementType;
|
||||||
|
|
||||||
|
final class VectorElementTypeImpl implements VectorElementType {
|
||||||
|
private final ValueRepr repr;
|
||||||
|
@Range(from = 2, to = 4)
|
||||||
|
private final int size;
|
||||||
|
private final int byteSize;
|
||||||
|
|
||||||
|
VectorElementTypeImpl(ValueRepr repr, @Range(from = 2, to = 4) int size) {
|
||||||
|
if (size < 2 || size > 4) {
|
||||||
|
throw new IllegalArgumentException("Vector element size must be in range [2, 4]!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.repr = repr;
|
||||||
|
this.size = size;
|
||||||
|
byteSize = repr.byteSize() * size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueRepr repr() {
|
||||||
|
return repr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Range(from = 2, to = 4)
|
||||||
|
public int size() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int byteSize() {
|
||||||
|
return byteSize;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,17 +4,17 @@ import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceHandle;
|
import com.jozufozu.flywheel.api.instance.InstanceHandle;
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceWriter;
|
import com.jozufozu.flywheel.api.instance.InstanceWriter;
|
||||||
import com.jozufozu.flywheel.api.layout.FloatType;
|
import com.jozufozu.flywheel.api.layout.FloatRepr;
|
||||||
import com.jozufozu.flywheel.api.layout.IntegerType;
|
import com.jozufozu.flywheel.api.layout.IntegerRepr;
|
||||||
import com.jozufozu.flywheel.api.layout.Layout;
|
import com.jozufozu.flywheel.api.layout.Layout;
|
||||||
import com.jozufozu.flywheel.api.layout.VectorSize;
|
import com.jozufozu.flywheel.api.layout.LayoutBuilder;
|
||||||
import com.jozufozu.flywheel.lib.layout.BufferLayout;
|
import com.jozufozu.flywheel.lib.layout.BufferLayout;
|
||||||
import com.jozufozu.flywheel.lib.layout.CommonItems;
|
import com.jozufozu.flywheel.lib.layout.CommonItems;
|
||||||
import com.jozufozu.flywheel.lib.layout.LayoutBuilder;
|
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public class OrientedType implements InstanceType<OrientedInstance> {
|
public class OrientedType implements InstanceType<OrientedInstance> {
|
||||||
|
@Deprecated
|
||||||
private static final BufferLayout OLD_LAYOUT = BufferLayout.builder()
|
private static final BufferLayout OLD_LAYOUT = BufferLayout.builder()
|
||||||
.addItem(CommonItems.LIGHT_COORD, "light")
|
.addItem(CommonItems.LIGHT_COORD, "light")
|
||||||
.addItem(CommonItems.UNORM_4x8, "color")
|
.addItem(CommonItems.UNORM_4x8, "color")
|
||||||
|
@ -23,12 +23,12 @@ public class OrientedType implements InstanceType<OrientedInstance> {
|
||||||
.addItem(CommonItems.VEC4, "rotation")
|
.addItem(CommonItems.VEC4, "rotation")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private static final Layout LAYOUT = LayoutBuilder.of()
|
private static final Layout LAYOUT = LayoutBuilder.create()
|
||||||
.integer("light", IntegerType.SHORT, VectorSize.TWO)
|
.vector("light", IntegerRepr.SHORT, 2)
|
||||||
.normalized("color", IntegerType.BYTE, VectorSize.FOUR)
|
.vector("color", FloatRepr.NORMALIZED_UNSIGNED_BYTE, 4)
|
||||||
.vector("position", FloatType.FLOAT, VectorSize.THREE)
|
.vector("position", FloatRepr.FLOAT, 3)
|
||||||
.vector("pivot", FloatType.FLOAT, VectorSize.THREE)
|
.vector("pivot", FloatRepr.FLOAT, 3)
|
||||||
.vector("rotation", FloatType.FLOAT, VectorSize.FOUR)
|
.vector("rotation", FloatRepr.FLOAT, 4)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private static final ResourceLocation VERTEX_SHADER = Flywheel.rl("instance/oriented.vert");
|
private static final ResourceLocation VERTEX_SHADER = Flywheel.rl("instance/oriented.vert");
|
||||||
|
@ -40,7 +40,8 @@ public class OrientedType implements InstanceType<OrientedInstance> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BufferLayout getLayout() {
|
@Deprecated
|
||||||
|
public BufferLayout oldLayout() {
|
||||||
return OLD_LAYOUT;
|
return OLD_LAYOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +51,7 @@ public class OrientedType implements InstanceType<OrientedInstance> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InstanceWriter<OrientedInstance> getWriter() {
|
public InstanceWriter<OrientedInstance> writer() {
|
||||||
return OrientedWriter.INSTANCE;
|
return OrientedWriter.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,5 +64,4 @@ public class OrientedType implements InstanceType<OrientedInstance> {
|
||||||
public ResourceLocation cullShader() {
|
public ResourceLocation cullShader() {
|
||||||
return CULL_SHADER;
|
return CULL_SHADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,17 @@ import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceHandle;
|
import com.jozufozu.flywheel.api.instance.InstanceHandle;
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceWriter;
|
import com.jozufozu.flywheel.api.instance.InstanceWriter;
|
||||||
import com.jozufozu.flywheel.api.layout.IntegerType;
|
import com.jozufozu.flywheel.api.layout.FloatRepr;
|
||||||
|
import com.jozufozu.flywheel.api.layout.IntegerRepr;
|
||||||
import com.jozufozu.flywheel.api.layout.Layout;
|
import com.jozufozu.flywheel.api.layout.Layout;
|
||||||
import com.jozufozu.flywheel.api.layout.MatrixSize;
|
import com.jozufozu.flywheel.api.layout.LayoutBuilder;
|
||||||
import com.jozufozu.flywheel.api.layout.VectorSize;
|
|
||||||
import com.jozufozu.flywheel.lib.layout.BufferLayout;
|
import com.jozufozu.flywheel.lib.layout.BufferLayout;
|
||||||
import com.jozufozu.flywheel.lib.layout.CommonItems;
|
import com.jozufozu.flywheel.lib.layout.CommonItems;
|
||||||
import com.jozufozu.flywheel.lib.layout.LayoutBuilder;
|
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public class TransformedType implements InstanceType<TransformedInstance> {
|
public class TransformedType implements InstanceType<TransformedInstance> {
|
||||||
|
@Deprecated
|
||||||
private static final BufferLayout OLD_LAYOUT = BufferLayout.builder()
|
private static final BufferLayout OLD_LAYOUT = BufferLayout.builder()
|
||||||
.addItem(CommonItems.LIGHT_COORD, "light")
|
.addItem(CommonItems.LIGHT_COORD, "light")
|
||||||
.addItem(CommonItems.UNORM_4x8, "color")
|
.addItem(CommonItems.UNORM_4x8, "color")
|
||||||
|
@ -22,11 +22,11 @@ public class TransformedType implements InstanceType<TransformedInstance> {
|
||||||
.addItem(CommonItems.MAT3, "normal")
|
.addItem(CommonItems.MAT3, "normal")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public static final Layout LAYOUT = LayoutBuilder.of()
|
private static final Layout LAYOUT = LayoutBuilder.create()
|
||||||
.integer("light", IntegerType.SHORT, VectorSize.TWO)
|
.vector("light", IntegerRepr.SHORT, 2)
|
||||||
.normalized("color", IntegerType.BYTE, VectorSize.FOUR)
|
.vector("color", FloatRepr.NORMALIZED_UNSIGNED_BYTE, 4)
|
||||||
.mat("pose", MatrixSize.FOUR)
|
.matrix("pose", FloatRepr.FLOAT, 4)
|
||||||
.mat("normal", MatrixSize.THREE)
|
.matrix("normal", FloatRepr.FLOAT, 3)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private static final ResourceLocation VERTEX_SHADER = Flywheel.rl("instance/transformed.vert");
|
private static final ResourceLocation VERTEX_SHADER = Flywheel.rl("instance/transformed.vert");
|
||||||
|
@ -38,7 +38,8 @@ public class TransformedType implements InstanceType<TransformedInstance> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BufferLayout getLayout() {
|
@Deprecated
|
||||||
|
public BufferLayout oldLayout() {
|
||||||
return OLD_LAYOUT;
|
return OLD_LAYOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ public class TransformedType implements InstanceType<TransformedInstance> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InstanceWriter<TransformedInstance> getWriter() {
|
public InstanceWriter<TransformedInstance> writer() {
|
||||||
return TransformedWriter.INSTANCE;
|
return TransformedWriter.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,5 +62,4 @@ public class TransformedType implements InstanceType<TransformedInstance> {
|
||||||
public ResourceLocation cullShader() {
|
public ResourceLocation cullShader() {
|
||||||
return CULL_SHADER;
|
return CULL_SHADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
package com.jozufozu.flywheel.lib.layout;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.jozufozu.flywheel.api.layout.Element;
|
|
||||||
import com.jozufozu.flywheel.api.layout.FloatType;
|
|
||||||
import com.jozufozu.flywheel.api.layout.IntegerType;
|
|
||||||
import com.jozufozu.flywheel.api.layout.Layout;
|
|
||||||
import com.jozufozu.flywheel.api.layout.MatrixSize;
|
|
||||||
import com.jozufozu.flywheel.api.layout.VectorSize;
|
|
||||||
|
|
||||||
public class LayoutBuilder {
|
|
||||||
private final List<Element> elements = new ArrayList<>();
|
|
||||||
|
|
||||||
public static LayoutBuilder of() {
|
|
||||||
return new LayoutBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Layout build() {
|
|
||||||
return new Layout(ImmutableList.copyOf(elements));
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutBuilder element(Element element) {
|
|
||||||
elements.add(element);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutBuilder integer(String name, IntegerType type, VectorSize size) {
|
|
||||||
return element(new Element.IntegerVector(name, type, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutBuilder normalized(String name, IntegerType type, VectorSize size) {
|
|
||||||
return element(new Element.NormalizedVector(name, type, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutBuilder vector(String name, FloatType type, VectorSize size) {
|
|
||||||
return element(new Element.Vector(name, type, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutBuilder mat(String name, MatrixSize rows, MatrixSize cols) {
|
|
||||||
return element(new Element.Matrix(name, rows, cols));
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutBuilder mat(String name, MatrixSize size) {
|
|
||||||
return mat(name, size, size);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue