Instandirect

- Finishing touches on the unification
This commit is contained in:
Jozufozu 2022-09-12 22:32:30 -07:00
parent bf03f084c3
commit 03c2df4664
24 changed files with 86 additions and 165 deletions

View File

@ -1,8 +1,9 @@
package com.jozufozu.flywheel.api.pipeline;
import java.util.function.Function;
import java.util.function.BiFunction;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
import com.jozufozu.flywheel.core.SourceComponent;
import com.jozufozu.flywheel.core.source.FileResolution;
@ -16,11 +17,11 @@ public record PipelineShader(GLSLVersion glslVersion, FileResolution vertex, Fil
* @param structType The struct type to convert.
* @return A source component defining functions that unpack a representation of the given struct type.
*/
public SourceComponent assemble(StructType<?> structType) {
return factory.apply(structType);
public SourceComponent assemble(VertexType vertexType, StructType<?> structType) {
return factory.apply(vertexType, structType);
}
public interface InstanceAssemblerFactory extends Function<StructType<?>, SourceComponent> {
public interface InstanceAssemblerFactory extends BiFunction<VertexType, StructType<?>, SourceComponent> {
}
}

View File

@ -29,8 +29,6 @@ public interface StructType<S extends InstancedPart> {
VertexTransformer<S> getVertexTransformer();
StorageBufferWriter<S> getStorageBufferWriter();
interface VertexTransformer<S extends InstancedPart> {
void transform(MutableVertexList vertexList, S struct, ClientLevel level);
}

View File

@ -9,5 +9,6 @@ public interface StructWriter<S extends InstancedPart> {
/**
* Write the given struct to the given memory address.
*/
void write(long ptr, S struct);
void write(final long ptr, final S struct);
}

View File

@ -99,7 +99,7 @@ public class PipelineCompiler extends Memoizer<PipelineCompiler.Context, GlProgr
ImmutableList<SourceComponent> getVertexComponents() {
var layout = vertexType.getLayoutShader()
.getFile();
var instanceAssembly = pipelineShader.assemble(structType);
var instanceAssembly = pipelineShader.assemble(vertexType, structType);
var instance = structType.getInstanceShader()
.getFile();
var material = this.material.getVertexShader()
@ -133,7 +133,6 @@ public class PipelineCompiler extends Memoizer<PipelineCompiler.Context, GlProgr
StringBuilder finalSource = new StringBuilder(key.generateHeader());
finalSource.append("#extension GL_ARB_explicit_attrib_location : enable\n");
finalSource.append("#extension GL_ARB_conservative_depth : enable\n");
finalSource.append("#extension GL_ARB_enhanced_layouts : enable\n");
var ctx = new CompilationContext();

View File

@ -13,8 +13,8 @@ import static org.lwjgl.opengl.GL46.glVertexArrayVertexBuffer;
import com.jozufozu.flywheel.api.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.struct.StorageBufferWriter;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
import com.jozufozu.flywheel.backend.instancing.PipelineCompiler;
@ -27,7 +27,7 @@ public class IndirectCullingGroup<T extends InstancedPart> {
private static final int BARRIER_BITS = GL_SHADER_STORAGE_BARRIER_BIT | GL_COMMAND_BARRIER_BIT;
final StorageBufferWriter<T> storageBufferWriter;
final StructWriter<T> storageBufferWriter;
final GlProgram compute;
final GlProgram draw;
private final VertexType vertexType;
@ -48,9 +48,10 @@ public class IndirectCullingGroup<T extends InstancedPart> {
IndirectCullingGroup(StructType<T> structType, VertexType vertexType) {
this.vertexType = vertexType;
storageBufferWriter = structType.getStorageBufferWriter();
storageBufferWriter = structType.getWriter();
objectStride = storageBufferWriter.getAlignment();
objectStride = structType.getLayout()
.getStride();
buffers = new IndirectBuffers(objectStride);
buffers.createBuffers();
buffers.createObjectStorage(128);

View File

@ -4,21 +4,22 @@ import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
import com.jozufozu.flywheel.core.layout.BufferLayout;
public class IndirectInstancer<D extends InstancedPart> extends AbstractInstancer<D> {
public final BufferLayout instanceFormat;
public final IndirectModel<D> parent;
private final long objectStride;
private final StructWriter<D> writer;
int instanceCount = 0;
boolean anyToUpdate;
public IndirectInstancer(IndirectModel<D> parent, StructType<D> type) {
public IndirectInstancer(StructType<D> type) {
super(type);
this.parent = parent;
this.instanceFormat = type.getLayout();
this.objectStride = type.getLayout()
.getStride();
writer = type.getWriter();
}
@Override
@ -41,12 +42,10 @@ public class IndirectInstancer<D extends InstancedPart> extends AbstractInstance
}
public void writeSparse(long objectPtr, long batchIDPtr, int batchID) {
var storageBufferWriter = this.type.getStorageBufferWriter();
long objectStride = storageBufferWriter.getAlignment();
for (int i = 0, size = data.size(); i < size; i++) {
final var element = data.get(i);
if (element.checkDirtyAndClear()) {
storageBufferWriter.write(objectPtr + i * objectStride, element);
writer.write(objectPtr + i * objectStride, element);
MemoryUtil.memPutInt(batchIDPtr + i * IndirectBuffers.INT_SIZE, batchID);
}
@ -54,11 +53,9 @@ public class IndirectInstancer<D extends InstancedPart> extends AbstractInstance
}
public void writeFull(long objectPtr, long batchIDPtr, int batchID) {
var storageBufferWriter = this.type.getStorageBufferWriter();
var objectStride = storageBufferWriter.getAlignment();
for (var object : data) {
// write object
storageBufferWriter.write(objectPtr, object);
writer.write(objectPtr, object);
objectPtr += objectStride;
// write batchID

View File

@ -11,7 +11,7 @@ public class IndirectModel<D extends InstancedPart> {
public IndirectModel(StructType<D> type, Model model) {
this.model = model;
this.instancer = new IndirectInstancer<>(this, type);
this.instancer = new IndirectInstancer<>(type);
}
public void init(IndirectDrawManager indirectDrawManager) {

View File

@ -29,9 +29,10 @@ public class Components {
public static final ContextShader WORLD = ComponentRegistry.register(new ContextShader(WorldProgram::new, Files.WORLD_VERTEX, Files.WORLD_FRAGMENT));
public static final ContextShader CRUMBLING = ComponentRegistry.register(new ContextShader(CrumblingProgram::new, Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT));
public static final PipelineShader INSTANCED_ARRAYS = new PipelineShader(GLSLVersion.V420, Pipeline.INSTANCED_ARRAYS_DRAW, Pipeline.DRAW_FRAGMENT, (structType) -> structType.getLayout()
.getInstancedArraysComponent());
public static final PipelineShader INDIRECT = new PipelineShader(GLSLVersion.V460, Pipeline.INDIRECT_DRAW, Pipeline.DRAW_FRAGMENT, (structType) -> structType.getLayout()
public static final PipelineShader INSTANCED_ARRAYS = new PipelineShader(GLSLVersion.V420, Pipeline.INSTANCED_ARRAYS_DRAW, Pipeline.DRAW_FRAGMENT, (vertexType, structType) -> structType.getLayout()
.getInstancedArraysComponent(vertexType.getLayout()
.getAttributeCount()));
public static final PipelineShader INDIRECT = new PipelineShader(GLSLVersion.V460, Pipeline.INDIRECT_DRAW, Pipeline.DRAW_FRAGMENT, (vertexType, structType) -> structType.getLayout()
.getIndirectComponent());
public static final FileResolution UTIL_TYPES = FileResolution.get(Flywheel.rl("util/types.glsl"));

View File

@ -59,8 +59,8 @@ public class BufferLayout {
return stride;
}
public InstancedArraysComponent getInstancedArraysComponent() {
return new InstancedArraysComponent();
public InstancedArraysComponent getInstancedArraysComponent(int baseIndex) {
return new InstancedArraysComponent(baseIndex);
}
public IndirectComponent getIndirectComponent() {
@ -109,6 +109,14 @@ public class BufferLayout {
}
public class InstancedArraysComponent implements SourceComponent {
private static final String ATTRIBUTE_SUFFIX = "_vertex_in";
private final int baseIndex;
public InstancedArraysComponent(int baseIndex) {
this.baseIndex = baseIndex;
}
@Override
public Collection<? extends SourceComponent> included() {
return Collections.emptyList();
@ -116,7 +124,8 @@ public class BufferLayout {
@Override
public String source(CompilationContext ctx) {
return generateInstancedArrays(5, "Instance");
var generated = generateInstancedArrays("Instance");
return ctx.generatedHeader(generated, name().toString()) + generated;
}
@Override
@ -124,17 +133,16 @@ public class BufferLayout {
return Flywheel.rl("generated_instanced_arrays");
}
public String generateInstancedArrays(int baseIndex, String structName) {
public String generateInstancedArrays(String structName) {
var builder = new GlslBuilder();
builder.define("FlwInstance", structName);
int i = baseIndex;
final var attributeSuffix = "_vertex_in";
for (var field : layoutItems) {
builder.vertexInput()
.binding(i)
.type(field.type.typeName())
.name(field.name + attributeSuffix);
.name(field.name + ATTRIBUTE_SUFFIX);
i += field.type.attributeCount();
}
@ -155,7 +163,7 @@ public class BufferLayout {
.name("flw_unpackInstance");
var args = layoutItems.stream()
.map(it -> new GlslExpr.Variable(it.name + attributeSuffix))
.map(it -> new GlslExpr.Variable(it.name + ATTRIBUTE_SUFFIX))
.map(GlslExpr::minPrint)
.collect(Collectors.joining(", "));
@ -169,7 +177,7 @@ public class BufferLayout {
private static final String UNPACK_ARG = "p";
private static GlslExpr intoGlsl(LayoutItem layoutItem) {
private static GlslExpr genGlslForLayoutItem(LayoutItem layoutItem) {
return GlslExpr.variable(UNPACK_ARG)
.access(layoutItem.name)
.transform(layoutItem.type::unpack);
@ -187,8 +195,8 @@ public class BufferLayout {
@Override
public String source(CompilationContext ctx) {
var content = generateIndirect("IndirectStruct");
return ctx.generatedHeader(content, name().toString()) + content;
var generated = generateIndirect("IndirectStruct");
return ctx.generatedHeader(generated, name().toString()) + generated;
}
public String generateIndirect(String structName) {
@ -216,7 +224,7 @@ public class BufferLayout {
.argumentIn(packedStructName, UNPACK_ARG);
var args = layoutItems.stream()
.map(IndirectComponent::intoGlsl)
.map(IndirectComponent::genGlslForLayoutItem)
.map(GlslExpr::minPrint)
.collect(Collectors.joining(", "));

View File

@ -10,12 +10,23 @@ public class CommonItems {
private static final String VEC4_TYPE = "vec4";
private static final String VEC2_TYPE = "vec2";
private static final String FLOAT_TYPE = "float";
private static final String IVEC2_TYPE = "ivec2";
private static final String UINT_TYPE = "uint";
private static final String VEC4F_TYPE = "Vec4F";
private static final String VEC3F_TYPE = "Vec3F";
private static final String LIGHT_COORD_TYPE = "LightCoord";
public static final PrimitiveItem LIGHT_COORD = PrimitiveItem.builder()
.setAttribute(new VertexAttributeI(GlNumericType.USHORT, 2))
.setTypeName(IVEC2_TYPE)
.setPackedTypeName(LIGHT_COORD_TYPE)
.unpack(expr -> expr.callFunction("unpackLightCoord"))
.createPrimitiveItem();
public static final PrimitiveItem FLOAT = PrimitiveItem.builder()
.setAttribute(new VertexAttributeF(GlNumericType.FLOAT, 1, false))
.setTypeName(FLOAT_TYPE)
.setPackedTypeName(FLOAT_TYPE)
.createPrimitiveItem();
private static final String UINT_TYPE = "uint";
public static final PrimitiveItem NORM_3x8 = PrimitiveItem.builder()
.setAttribute(new VertexAttributeF(GlNumericType.BYTE, 3, true))
.setTypeName(VEC3_TYPE)
@ -36,35 +47,25 @@ public class CommonItems {
.unpack(expr -> expr.callFunction("unpackUnorm4x8")
.swizzle("xyz"))
.createPrimitiveItem();
private static final String IVEC2_TYPE = "ivec2";
private static final String VEC4F_TYPE = "Vec4F";
public static final PrimitiveItem VEC4 = PrimitiveItem.builder()
.setAttribute(new VertexAttributeF(GlNumericType.FLOAT, 4, false))
.setTypeName(VEC4_TYPE)
.setPackedTypeName(VEC4F_TYPE)
.unpack(expr -> expr.callFunction("unpackVec4F"))
.createPrimitiveItem();
private static final String VEC3F_TYPE = "Vec3F";
public static final PrimitiveItem VEC3 = PrimitiveItem.builder()
.setAttribute(new VertexAttributeF(GlNumericType.FLOAT, 3, false))
.setTypeName(VEC3_TYPE)
.setPackedTypeName(VEC3F_TYPE)
.unpack(expr -> expr.callFunction("unpackVec3F"))
.createPrimitiveItem();
private static final String VEC2F_TYPE = "Vec2F";
public static final PrimitiveItem VEC2 = PrimitiveItem.builder()
.setAttribute(new VertexAttributeF(GlNumericType.FLOAT, 2, false))
.setTypeName(VEC2_TYPE)
.setPackedTypeName(VEC2F_TYPE)
.unpack(expr -> expr.callFunction("unpackVec2F"))
.createPrimitiveItem();
private static final String LIGHT_COORD_TYPE = "LightCoord";
public static final PrimitiveItem LIGHT_COORD = PrimitiveItem.builder()
.setAttribute(new VertexAttributeI(GlNumericType.USHORT, 2))
.setTypeName(VEC2_TYPE)
.setPackedTypeName(LIGHT_COORD_TYPE)
.unpack(expr -> expr.callFunction("unpackLightCoord"))
.createPrimitiveItem();
private static final String VEC2F_TYPE = "Vec2F";
public static final MatrixItem MAT3 = new MatrixItem(3, 3, "mat3", "Mat3F", "unpackMat3F");

View File

@ -14,6 +14,7 @@ public class CompilationContext {
private String generatedSource = "";
private int generatedLines = 0;
String sourceHeader(SourceFile sourceFile) {
return "#line " + 0 + ' ' + getOrCreateFileID(sourceFile) + " // " + sourceFile.name + '\n';
}

View File

@ -6,12 +6,12 @@ import com.jozufozu.flywheel.api.struct.StructWriter;
public abstract class ColoredLitWriter<D extends ColoredLitPart> implements StructWriter<D> {
@Override
public void write(long ptr, D d) {
MemoryUtil.memPutByte(ptr, d.blockLight);
MemoryUtil.memPutByte(ptr + 1, d.skyLight);
MemoryUtil.memPutByte(ptr + 2, d.r);
MemoryUtil.memPutByte(ptr + 3, d.g);
MemoryUtil.memPutByte(ptr + 4, d.b);
MemoryUtil.memPutByte(ptr + 5, d.a);
public void write(final long ptr, final D d) {
MemoryUtil.memPutShort(ptr, d.blockLight);
MemoryUtil.memPutShort(ptr + 2, d.skyLight);
MemoryUtil.memPutByte(ptr + 4, d.r);
MemoryUtil.memPutByte(ptr + 5, d.g);
MemoryUtil.memPutByte(ptr + 6, d.b);
MemoryUtil.memPutByte(ptr + 7, d.a);
}
}

View File

@ -1,43 +0,0 @@
package com.jozufozu.flywheel.core.structs.oriented;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.struct.StorageBufferWriter;
public class OrientedStorageWriter implements StorageBufferWriter<OrientedPart> {
public static final OrientedStorageWriter INSTANCE = new OrientedStorageWriter();
private OrientedStorageWriter() {
}
@Override
public void write(final long ptr, OrientedPart d) {
MemoryUtil.memPutFloat(ptr, d.qX);
MemoryUtil.memPutFloat(ptr + 4, d.qY);
MemoryUtil.memPutFloat(ptr + 8, d.qZ);
MemoryUtil.memPutFloat(ptr + 12, d.qW);
MemoryUtil.memPutFloat(ptr + 16, d.posX);
MemoryUtil.memPutFloat(ptr + 20, d.posY);
MemoryUtil.memPutFloat(ptr + 24, d.posZ);
MemoryUtil.memPutFloat(ptr + 28, d.pivotX);
MemoryUtil.memPutFloat(ptr + 32, d.pivotY);
MemoryUtil.memPutFloat(ptr + 36, d.pivotZ);
MemoryUtil.memPutShort(ptr + 40, d.skyLight);
MemoryUtil.memPutShort(ptr + 42, d.blockLight);
MemoryUtil.memPutByte(ptr + 44, d.r);
MemoryUtil.memPutByte(ptr + 45, d.g);
MemoryUtil.memPutByte(ptr + 46, d.b);
MemoryUtil.memPutByte(ptr + 47, d.a);
}
@Override
public int getAlignment() {
return 48;
}
}

View File

@ -37,11 +37,6 @@ public class OrientedType implements StructType<OrientedPart> {
return OrientedWriter.INSTANCE;
}
@Override
public OrientedStorageWriter getStorageBufferWriter() {
return OrientedStorageWriter.INSTANCE;
}
@Override
public FileResolution getInstanceShader() {
return Components.Files.ORIENTED;

View File

@ -11,15 +11,16 @@ public class OrientedWriter extends ColoredLitWriter<OrientedPart> {
public void write(long ptr, OrientedPart d) {
super.write(ptr, d);
MemoryUtil.memPutFloat(ptr + 6, d.posX);
MemoryUtil.memPutFloat(ptr + 10, d.posY);
MemoryUtil.memPutFloat(ptr + 14, d.posZ);
MemoryUtil.memPutFloat(ptr + 18, d.pivotX);
MemoryUtil.memPutFloat(ptr + 22, d.pivotY);
MemoryUtil.memPutFloat(ptr + 26, d.pivotZ);
MemoryUtil.memPutFloat(ptr + 30, d.qX);
MemoryUtil.memPutFloat(ptr + 34, d.qY);
MemoryUtil.memPutFloat(ptr + 38, d.qZ);
MemoryUtil.memPutFloat(ptr + 42, d.qW);
MemoryUtil.memPutFloat(ptr + 8, d.posX);
MemoryUtil.memPutFloat(ptr + 12, d.posY);
MemoryUtil.memPutFloat(ptr + 16, d.posZ);
MemoryUtil.memPutFloat(ptr + 20, d.pivotX);
MemoryUtil.memPutFloat(ptr + 24, d.pivotY);
MemoryUtil.memPutFloat(ptr + 28, d.pivotZ);
MemoryUtil.memPutFloat(ptr + 32, d.qX);
MemoryUtil.memPutFloat(ptr + 36, d.qY);
MemoryUtil.memPutFloat(ptr + 40, d.qZ);
MemoryUtil.memPutFloat(ptr + 44, d.qW);
}
}

View File

@ -1,31 +0,0 @@
package com.jozufozu.flywheel.core.structs.transformed;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.struct.StorageBufferWriter;
import com.jozufozu.flywheel.extension.MatrixWrite;
public class TransformedStorageWriter implements StorageBufferWriter<TransformedPart> {
public static final TransformedStorageWriter INSTANCE = new TransformedStorageWriter();
private TransformedStorageWriter() {
}
@Override
public void write(long ptr, TransformedPart instance) {
MatrixWrite.writeUnsafe(instance.model, ptr);
MatrixWrite.writeUnsafe(instance.normal, ptr + 64);
MemoryUtil.memPutByte(ptr + 100, instance.r);
MemoryUtil.memPutByte(ptr + 101, instance.g);
MemoryUtil.memPutByte(ptr + 102, instance.b);
MemoryUtil.memPutByte(ptr + 103, instance.a);
MemoryUtil.memPutShort(ptr + 104, instance.skyLight);
MemoryUtil.memPutShort(ptr + 106, instance.blockLight);
}
@Override
public int getAlignment() {
return 108;
}
}

View File

@ -1,6 +1,5 @@
package com.jozufozu.flywheel.core.structs.transformed;
import com.jozufozu.flywheel.api.struct.StorageBufferWriter;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.core.Components;
@ -34,11 +33,6 @@ public class TransformedType implements StructType<TransformedPart> {
return TransformedWriter.INSTANCE;
}
@Override
public StorageBufferWriter<TransformedPart> getStorageBufferWriter() {
return TransformedStorageWriter.INSTANCE;
}
@Override
public FileResolution getInstanceShader() {
return Components.Files.TRANSFORMED;

View File

@ -7,11 +7,10 @@ public class TransformedWriter extends ColoredLitWriter<TransformedPart> {
public static final TransformedWriter INSTANCE = new TransformedWriter();
@Override
public void write(long ptr, TransformedPart d) {
public void write(final long ptr, final TransformedPart d) {
super.write(ptr, d);
ptr += 6;
((MatrixWrite) (Object) d.model).flywheel$writeUnsafe(ptr);
((MatrixWrite) (Object) d.normal).flywheel$writeUnsafe(ptr + 4 * 16);
MatrixWrite.writeUnsafe(d.model, ptr + 8);
MatrixWrite.writeUnsafe(d.normal, ptr + 72);
}
}

View File

@ -15,6 +15,6 @@ void flw_instanceVertex(in FlwInstance i) {
flw_vertexPos = vec4(rotateVertexByQuat(flw_vertexPos.xyz - i.pivot, i.rotation) + i.pivot + i.position, 1.0);
flw_vertexNormal = rotateVertexByQuat(flw_vertexNormal, i.rotation);
flw_vertexColor = i.color;
flw_vertexLight = i.light;
flw_vertexLight = i.light / 15.0;
}
#endif

View File

@ -14,6 +14,6 @@ void flw_instanceVertex(in FlwInstance i) {
flw_vertexPos = i.pose * flw_vertexPos;
flw_vertexNormal = i.normal * flw_vertexNormal;
flw_vertexColor = i.color;
flw_vertexLight = i.light;
flw_vertexLight = i.light / 15.0;
}
#endif

View File

@ -5,7 +5,6 @@ layout(location = 1) in vec4 _flw_v_color;
layout(location = 2) in vec2 _flw_v_texCoord;
layout(location = 3) in ivec2 _flw_v_light;
layout(location = 4) in vec3 _flw_v_normal;
#define FLW_INSTANCE_BASE_INDEX 5
void flw_layoutVertex() {
flw_vertexPos = vec4(_flw_v_pos, 1.0);

View File

@ -3,7 +3,6 @@
layout(location = 0) in vec3 _flw_v_pos;
layout(location = 1) in vec2 _flw_v_texCoord;
layout(location = 2) in vec3 _flw_v_normal;
#define FLW_INSTANCE_BASE_INDEX 3
void flw_layoutVertex() {
flw_vertexPos = vec4(_flw_v_pos, 1.0);

View File

@ -66,6 +66,6 @@ void unpackBoundingSphere(in BoundingSphere sphere, out vec3 center, out float r
radius = sphere.radius;
}
vec2 unpackLightCoord(in LightCoord light) {
return vec2(float((light.p >> 16) & 0xFFFFu), float(light.p & 0xFFFFu)) / 15.0;
ivec2 unpackLightCoord(in LightCoord light) {
return ivec2(light.p & 0xFFFFu, (light.p >> 16) & 0xFFFFu);
}