mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-14 06:24:12 +01:00
More direct buffers
- Merge object and batch ID buffer. - ShaderCompiler accepts a Compilation callback. - Use callback to enable the conservative depth extension only in fragment shaders. - Query subgroup size if available and use callback to set a compile definition in compute shaders.
This commit is contained in:
parent
ddd159bb6c
commit
0b165df0e9
@ -6,11 +6,13 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.compile.core.Compilation;
|
||||||
import com.jozufozu.flywheel.backend.compile.core.ProgramLinker;
|
import com.jozufozu.flywheel.backend.compile.core.ProgramLinker;
|
||||||
import com.jozufozu.flywheel.backend.compile.core.ShaderCompiler;
|
import com.jozufozu.flywheel.backend.compile.core.ShaderCompiler;
|
||||||
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
||||||
@ -83,6 +85,8 @@ public class Compile {
|
|||||||
public static class ShaderCompilerBuilder<K> {
|
public static class ShaderCompilerBuilder<K> {
|
||||||
private final GLSLVersion glslVersion;
|
private final GLSLVersion glslVersion;
|
||||||
private final ShaderType shaderType;
|
private final ShaderType shaderType;
|
||||||
|
private Consumer<Compilation> compilationCallbacks = $ -> {
|
||||||
|
};
|
||||||
private final List<BiFunction<K, SourceLoader, SourceComponent>> fetchers = new ArrayList<>();
|
private final List<BiFunction<K, SourceLoader, SourceComponent>> fetchers = new ArrayList<>();
|
||||||
|
|
||||||
public ShaderCompilerBuilder(GLSLVersion glslVersion, ShaderType shaderType) {
|
public ShaderCompilerBuilder(GLSLVersion glslVersion, ShaderType shaderType) {
|
||||||
@ -111,6 +115,19 @@ public class Compile {
|
|||||||
return withResource($ -> resourceLocation);
|
return withResource($ -> resourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ShaderCompilerBuilder<K> onCompile(Consumer<Compilation> cb) {
|
||||||
|
compilationCallbacks = compilationCallbacks.andThen(cb);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShaderCompilerBuilder<K> define(String def, int value) {
|
||||||
|
return onCompile(ctx -> ctx.define(def, String.valueOf(value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShaderCompilerBuilder<K> enableExtension(String extension) {
|
||||||
|
return onCompile(ctx -> ctx.enableExtension(extension));
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private GlShader compile(K key, ShaderCompiler compiler, SourceLoader loader) {
|
private GlShader compile(K key, ShaderCompiler compiler, SourceLoader loader) {
|
||||||
var components = new ArrayList<SourceComponent>();
|
var components = new ArrayList<SourceComponent>();
|
||||||
@ -127,7 +144,7 @@ public class Compile {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return compiler.compile(glslVersion, shaderType, components);
|
return compiler.compile(glslVersion, shaderType, compilationCallbacks, components);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import com.jozufozu.flywheel.api.vertex.VertexType;
|
|||||||
import com.jozufozu.flywheel.backend.compile.component.IndirectComponent;
|
import com.jozufozu.flywheel.backend.compile.component.IndirectComponent;
|
||||||
import com.jozufozu.flywheel.backend.compile.component.MaterialAdapterComponent;
|
import com.jozufozu.flywheel.backend.compile.component.MaterialAdapterComponent;
|
||||||
import com.jozufozu.flywheel.backend.compile.component.UniformComponent;
|
import com.jozufozu.flywheel.backend.compile.component.UniformComponent;
|
||||||
|
import com.jozufozu.flywheel.gl.GlCompat;
|
||||||
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
||||||
import com.jozufozu.flywheel.gl.shader.ShaderType;
|
import com.jozufozu.flywheel.gl.shader.ShaderType;
|
||||||
import com.jozufozu.flywheel.glsl.GLSLVersion;
|
import com.jozufozu.flywheel.glsl.GLSLVersion;
|
||||||
@ -75,6 +76,7 @@ public class IndirectPrograms {
|
|||||||
private static CompilationHarness<InstanceType<?>> createCullingCompiler(UniformComponent uniformComponent, ShaderSources sources) {
|
private static CompilationHarness<InstanceType<?>> createCullingCompiler(UniformComponent uniformComponent, ShaderSources sources) {
|
||||||
return new CompilationHarness<>(sources, createCullingKeys(), Compile.<InstanceType<?>>program()
|
return new CompilationHarness<>(sources, createCullingKeys(), Compile.<InstanceType<?>>program()
|
||||||
.link(Compile.<InstanceType<?>>shader(GLSLVersion.V460, ShaderType.COMPUTE)
|
.link(Compile.<InstanceType<?>>shader(GLSLVersion.V460, ShaderType.COMPUTE)
|
||||||
|
.define("FLW_SUBGROUP_SIZE", GlCompat.SUBGROUP_SIZE)
|
||||||
.withComponent(uniformComponent)
|
.withComponent(uniformComponent)
|
||||||
.withComponent(IndirectComponent::create)
|
.withComponent(IndirectComponent::create)
|
||||||
.withResource(InstanceType::instanceShader)
|
.withResource(InstanceType::instanceShader)
|
||||||
|
@ -23,6 +23,7 @@ public class PipelineCompiler {
|
|||||||
.vertexShader())
|
.vertexShader())
|
||||||
.withResource(pipeline.vertexShader()))
|
.withResource(pipeline.vertexShader()))
|
||||||
.link(Compile.<PipelineProgramKey>shader(pipeline.glslVersion(), ShaderType.FRAGMENT)
|
.link(Compile.<PipelineProgramKey>shader(pipeline.glslVersion(), ShaderType.FRAGMENT)
|
||||||
|
.enableExtension("GL_ARB_conservative_depth")
|
||||||
.withComponent(uniformComponent)
|
.withComponent(uniformComponent)
|
||||||
.withComponent(fragmentMaterialComponent)
|
.withComponent(fragmentMaterialComponent)
|
||||||
.withResource(key -> key.contextShader()
|
.withResource(key -> key.contextShader()
|
||||||
|
@ -70,6 +70,14 @@ public class Compilation {
|
|||||||
.append(" : enable\n");
|
.append(" : enable\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void define(String key, String value) {
|
||||||
|
fullSource.append("#define ")
|
||||||
|
.append(key)
|
||||||
|
.append(' ')
|
||||||
|
.append(value)
|
||||||
|
.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
public void appendComponent(SourceComponent component) {
|
public void appendComponent(SourceComponent component) {
|
||||||
var source = component.source();
|
var source = component.source();
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public class ShaderCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public GlShader compile(GLSLVersion glslVersion, ShaderType shaderType, List<SourceComponent> sourceComponents) {
|
public GlShader compile(GLSLVersion glslVersion, ShaderType shaderType, Consumer<Compilation> callback, List<SourceComponent> sourceComponents) {
|
||||||
var key = new ShaderKey(glslVersion, shaderType, sourceComponents);
|
var key = new ShaderKey(glslVersion, shaderType, sourceComponents);
|
||||||
var cached = shaderCache.get(key);
|
var cached = shaderCache.get(key);
|
||||||
if (cached != null) {
|
if (cached != null) {
|
||||||
@ -32,7 +32,8 @@ public class ShaderCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Compilation ctx = new Compilation(glslVersion, shaderType);
|
Compilation ctx = new Compilation(glslVersion, shaderType);
|
||||||
ctx.enableExtension("GL_ARB_conservative_depth");
|
|
||||||
|
callback.accept(ctx);
|
||||||
|
|
||||||
expand(sourceComponents, ctx::appendComponent);
|
expand(sourceComponents, ctx::appendComponent);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker;
|
|||||||
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
||||||
|
|
||||||
public class IndirectBuffers {
|
public class IndirectBuffers {
|
||||||
public static final int BUFFER_COUNT = 4;
|
public static final int BUFFER_COUNT = 3;
|
||||||
public static final long INT_SIZE = Integer.BYTES;
|
public static final long INT_SIZE = Integer.BYTES;
|
||||||
public static final long PTR_SIZE = Pointer.POINTER_SIZE;
|
public static final long PTR_SIZE = Pointer.POINTER_SIZE;
|
||||||
|
|
||||||
@ -45,18 +45,15 @@ public class IndirectBuffers {
|
|||||||
|
|
||||||
private static final long OBJECT_SIZE_OFFSET = SIZE_OFFSET;
|
private static final long OBJECT_SIZE_OFFSET = SIZE_OFFSET;
|
||||||
private static final long TARGET_SIZE_OFFSET = OBJECT_SIZE_OFFSET + PTR_SIZE;
|
private static final long TARGET_SIZE_OFFSET = OBJECT_SIZE_OFFSET + PTR_SIZE;
|
||||||
private static final long BATCH_SIZE_OFFSET = TARGET_SIZE_OFFSET + PTR_SIZE;
|
private static final long DRAW_SIZE_OFFSET = TARGET_SIZE_OFFSET + PTR_SIZE;
|
||||||
private static final long DRAW_SIZE_OFFSET = BATCH_SIZE_OFFSET + PTR_SIZE;
|
|
||||||
|
|
||||||
private final MemoryBlock buffers;
|
private final MemoryBlock buffers;
|
||||||
private final long objectStride;
|
private final long objectStride;
|
||||||
private int object;
|
private int object;
|
||||||
private int target;
|
private int target;
|
||||||
private int batch;
|
|
||||||
private int draw;
|
private int draw;
|
||||||
|
|
||||||
long objectPtr;
|
long objectPtr;
|
||||||
long batchPtr;
|
|
||||||
long drawPtr;
|
long drawPtr;
|
||||||
|
|
||||||
private int maxObjectCount = 0;
|
private int maxObjectCount = 0;
|
||||||
@ -72,11 +69,10 @@ public class IndirectBuffers {
|
|||||||
|
|
||||||
void createBuffers() {
|
void createBuffers() {
|
||||||
final long ptr = buffers.ptr();
|
final long ptr = buffers.ptr();
|
||||||
nglCreateBuffers(4, ptr);
|
nglCreateBuffers(BUFFER_COUNT, ptr);
|
||||||
object = MemoryUtil.memGetInt(ptr);
|
object = MemoryUtil.memGetInt(ptr);
|
||||||
target = MemoryUtil.memGetInt(ptr + 4);
|
target = MemoryUtil.memGetInt(ptr + 4);
|
||||||
batch = MemoryUtil.memGetInt(ptr + 8);
|
draw = MemoryUtil.memGetInt(ptr + 8);
|
||||||
draw = MemoryUtil.memGetInt(ptr + 12);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateCounts(int objectCount, int drawCount) {
|
void updateCounts(int objectCount, int drawCount) {
|
||||||
@ -94,7 +90,6 @@ public class IndirectBuffers {
|
|||||||
final long ptr = buffers.ptr();
|
final long ptr = buffers.ptr();
|
||||||
MemoryUtil.memPutAddress(ptr + OBJECT_SIZE_OFFSET, objectSize);
|
MemoryUtil.memPutAddress(ptr + OBJECT_SIZE_OFFSET, objectSize);
|
||||||
MemoryUtil.memPutAddress(ptr + TARGET_SIZE_OFFSET, targetSize);
|
MemoryUtil.memPutAddress(ptr + TARGET_SIZE_OFFSET, targetSize);
|
||||||
MemoryUtil.memPutAddress(ptr + BATCH_SIZE_OFFSET, targetSize);
|
|
||||||
MemoryUtil.memPutAddress(ptr + DRAW_SIZE_OFFSET, drawSize);
|
MemoryUtil.memPutAddress(ptr + DRAW_SIZE_OFFSET, drawSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,38 +100,31 @@ public class IndirectBuffers {
|
|||||||
|
|
||||||
if (maxObjectCount > 0) {
|
if (maxObjectCount > 0) {
|
||||||
final long ptr = buffers.ptr();
|
final long ptr = buffers.ptr();
|
||||||
nglCreateBuffers(3, ptr);
|
nglCreateBuffers(BUFFER_COUNT - 1, ptr);
|
||||||
|
|
||||||
int objectNew = MemoryUtil.memGetInt(ptr);
|
int objectNew = MemoryUtil.memGetInt(ptr);
|
||||||
int targetNew = MemoryUtil.memGetInt(ptr + 4);
|
int targetNew = MemoryUtil.memGetInt(ptr + 4);
|
||||||
int batchNew = MemoryUtil.memGetInt(ptr + 8);
|
|
||||||
|
|
||||||
glNamedBufferStorage(objectNew, objectSize, PERSISTENT_BITS);
|
glNamedBufferStorage(objectNew, objectSize, PERSISTENT_BITS);
|
||||||
glNamedBufferStorage(targetNew, targetSize, GPU_ONLY_BITS);
|
glNamedBufferStorage(targetNew, targetSize, GPU_ONLY_BITS);
|
||||||
glNamedBufferStorage(batchNew, targetSize, PERSISTENT_BITS);
|
|
||||||
|
|
||||||
glCopyNamedBufferSubData(object, objectNew, 0, 0, objectStride * maxObjectCount);
|
glCopyNamedBufferSubData(object, objectNew, 0, 0, objectStride * maxObjectCount);
|
||||||
glCopyNamedBufferSubData(target, targetNew, 0, 0, INT_SIZE * maxObjectCount);
|
glCopyNamedBufferSubData(target, targetNew, 0, 0, INT_SIZE * maxObjectCount);
|
||||||
glCopyNamedBufferSubData(batch, batchNew, 0, 0, INT_SIZE * maxObjectCount);
|
|
||||||
|
|
||||||
glDeleteBuffers(object);
|
glDeleteBuffers(object);
|
||||||
glDeleteBuffers(target);
|
glDeleteBuffers(target);
|
||||||
glDeleteBuffers(batch);
|
|
||||||
|
|
||||||
object = objectNew;
|
object = objectNew;
|
||||||
target = targetNew;
|
target = targetNew;
|
||||||
batch = batchNew;
|
|
||||||
} else {
|
} else {
|
||||||
glNamedBufferStorage(object, objectSize, PERSISTENT_BITS);
|
glNamedBufferStorage(object, objectSize, PERSISTENT_BITS);
|
||||||
glNamedBufferStorage(target, targetSize, GPU_ONLY_BITS);
|
glNamedBufferStorage(target, targetSize, GPU_ONLY_BITS);
|
||||||
glNamedBufferStorage(batch, targetSize, PERSISTENT_BITS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
objectPtr = nglMapNamedBufferRange(object, 0, objectSize, MAP_BITS);
|
objectPtr = nglMapNamedBufferRange(object, 0, objectSize, MAP_BITS);
|
||||||
batchPtr = nglMapNamedBufferRange(batch, 0, targetSize, MAP_BITS);
|
|
||||||
maxObjectCount = objectCount;
|
maxObjectCount = objectCount;
|
||||||
|
|
||||||
FlwMemoryTracker._allocGPUMemory(maxObjectCount * objectStride + maxObjectCount * INT_SIZE);
|
FlwMemoryTracker._allocGPUMemory(maxObjectCount * objectStride);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createDrawStorage(int drawCount) {
|
void createDrawStorage(int drawCount) {
|
||||||
@ -150,7 +138,7 @@ public class IndirectBuffers {
|
|||||||
|
|
||||||
glDeleteBuffers(draw);
|
glDeleteBuffers(draw);
|
||||||
|
|
||||||
MemoryUtil.memPutInt(buffers.ptr() + INT_SIZE * 3, drawNew);
|
MemoryUtil.memPutInt(buffers.ptr() + INT_SIZE * 2, drawNew);
|
||||||
draw = drawNew;
|
draw = drawNew;
|
||||||
drawPtr = MemoryUtil.nmemRealloc(drawPtr, drawSize);
|
drawPtr = MemoryUtil.nmemRealloc(drawPtr, drawSize);
|
||||||
} else {
|
} else {
|
||||||
@ -163,7 +151,7 @@ public class IndirectBuffers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void freeObjectStogare() {
|
private void freeObjectStogare() {
|
||||||
FlwMemoryTracker._freeGPUMemory(maxObjectCount * objectStride + maxObjectCount * INT_SIZE);
|
FlwMemoryTracker._freeGPUMemory(maxObjectCount * objectStride);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void freeDrawStorage() {
|
private void freeDrawStorage() {
|
||||||
@ -184,10 +172,6 @@ public class IndirectBuffers {
|
|||||||
nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, 0, IndirectBuffers.BUFFER_COUNT, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET);
|
nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, 0, IndirectBuffers.BUFFER_COUNT, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
void flushBatchIDs(long length) {
|
|
||||||
glFlushMappedNamedBufferRange(batch, 0, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
void flushObjects(long length) {
|
void flushObjects(long length) {
|
||||||
glFlushMappedNamedBufferRange(object, 0, length);
|
glFlushMappedNamedBufferRange(object, 0, length);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ public class IndirectCullingGroup<I extends Instance> {
|
|||||||
|
|
||||||
private final GlProgram compute;
|
private final GlProgram compute;
|
||||||
private final GlProgram draw;
|
private final GlProgram draw;
|
||||||
private final long instanceStride;
|
private final long objectStride;
|
||||||
private final IndirectBuffers buffers;
|
private final IndirectBuffers buffers;
|
||||||
public final IndirectMeshPool meshPool;
|
public final IndirectMeshPool meshPool;
|
||||||
public final IndirectDrawSet<I> drawSet = new IndirectDrawSet<>();
|
public final IndirectDrawSet<I> drawSet = new IndirectDrawSet<>();
|
||||||
@ -30,9 +30,10 @@ public class IndirectCullingGroup<I extends Instance> {
|
|||||||
private int instanceCountThisFrame;
|
private int instanceCountThisFrame;
|
||||||
|
|
||||||
IndirectCullingGroup(InstanceType<I> instanceType, VertexType vertexType) {
|
IndirectCullingGroup(InstanceType<I> instanceType, VertexType vertexType) {
|
||||||
instanceStride = instanceType.getLayout()
|
objectStride = instanceType.getLayout()
|
||||||
.getStride();
|
.getStride() + IndirectBuffers.INT_SIZE;
|
||||||
buffers = new IndirectBuffers(instanceStride);
|
|
||||||
|
buffers = new IndirectBuffers(objectStride);
|
||||||
buffers.createBuffers();
|
buffers.createBuffers();
|
||||||
buffers.createObjectStorage(128);
|
buffers.createObjectStorage(128);
|
||||||
buffers.createDrawStorage(2);
|
buffers.createDrawStorage(2);
|
||||||
@ -108,20 +109,17 @@ public class IndirectCullingGroup<I extends Instance> {
|
|||||||
|
|
||||||
private void uploadInstances() {
|
private void uploadInstances() {
|
||||||
long objectPtr = buffers.objectPtr;
|
long objectPtr = buffers.objectPtr;
|
||||||
long batchIDPtr = buffers.batchPtr;
|
|
||||||
|
|
||||||
for (int i = 0, batchesSize = drawSet.indirectDraws.size(); i < batchesSize; i++) {
|
for (int i = 0, batchesSize = drawSet.indirectDraws.size(); i < batchesSize; i++) {
|
||||||
var batch = drawSet.indirectDraws.get(i);
|
var batch = drawSet.indirectDraws.get(i);
|
||||||
var instanceCount = batch.instancer()
|
var instanceCount = batch.instancer()
|
||||||
.getInstanceCount();
|
.getInstanceCount();
|
||||||
batch.writeObjects(objectPtr, batchIDPtr, i);
|
batch.writeObjects(objectPtr, i);
|
||||||
|
|
||||||
objectPtr += instanceCount * instanceStride;
|
objectPtr += instanceCount * objectStride;
|
||||||
batchIDPtr += instanceCount * IndirectBuffers.INT_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffers.flushObjects(objectPtr - buffers.objectPtr);
|
buffers.flushObjects(objectPtr - buffers.objectPtr);
|
||||||
buffers.flushBatchIDs(batchIDPtr - buffers.batchPtr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void uploadIndirectCommands() {
|
private void uploadIndirectCommands() {
|
||||||
|
@ -55,11 +55,11 @@ public class IndirectDraw<I extends Instance> {
|
|||||||
needsFullWrite = true;
|
needsFullWrite = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeObjects(long objectPtr, long batchIDPtr, int batchID) {
|
public void writeObjects(long objectPtr, int batchID) {
|
||||||
if (needsFullWrite) {
|
if (needsFullWrite) {
|
||||||
instancer.writeFull(objectPtr, batchIDPtr, batchID);
|
instancer.writeFull(objectPtr, batchID);
|
||||||
} else {
|
} else {
|
||||||
instancer.writeSparse(objectPtr, batchIDPtr, batchID);
|
instancer.writeSparse(objectPtr, batchID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,40 +9,42 @@ import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
|
|||||||
|
|
||||||
public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I> {
|
public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I> {
|
||||||
private final long instanceStride;
|
private final long instanceStride;
|
||||||
|
private final long objectStride;
|
||||||
|
|
||||||
public IndirectInstancer(InstanceType<I> type) {
|
public IndirectInstancer(InstanceType<I> type) {
|
||||||
super(type);
|
super(type);
|
||||||
this.instanceStride = type.getLayout()
|
this.instanceStride = type.getLayout()
|
||||||
.getStride();
|
.getStride();
|
||||||
|
this.objectStride = instanceStride + IndirectBuffers.INT_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
removeDeletedInstances();
|
removeDeletedInstances();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeSparse(long objectPtr, long batchIDPtr, int batchID) {
|
public void writeSparse(long objectPtr, int batchID) {
|
||||||
int count = instances.size();
|
int count = instances.size();
|
||||||
InstanceWriter<I> writer = type.getWriter();
|
InstanceWriter<I> writer = type.getWriter();
|
||||||
for (int i = changed.nextSetBit(0); i >= 0 && i < count; i = changed.nextSetBit(i + 1)) {
|
for (int i = changed.nextSetBit(0); i >= 0 && i < count; i = changed.nextSetBit(i + 1)) {
|
||||||
// write object
|
long ptr = objectPtr + objectStride * i;
|
||||||
writer.write(objectPtr + instanceStride * i, instances.get(i));
|
|
||||||
|
|
||||||
// write batchID
|
// write batchID
|
||||||
MemoryUtil.memPutInt(batchIDPtr + IndirectBuffers.INT_SIZE * i, batchID);
|
MemoryUtil.memPutInt(ptr, batchID);
|
||||||
|
// write object
|
||||||
|
writer.write(ptr + IndirectBuffers.INT_SIZE, instances.get(i));
|
||||||
}
|
}
|
||||||
changed.clear();
|
changed.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeFull(long objectPtr, long batchIDPtr, int batchID) {
|
public void writeFull(long objectPtr, int batchID) {
|
||||||
InstanceWriter<I> writer = type.getWriter();
|
InstanceWriter<I> writer = type.getWriter();
|
||||||
for (I object : instances) {
|
for (I object : instances) {
|
||||||
|
// write batchID
|
||||||
|
MemoryUtil.memPutInt(objectPtr, batchID);
|
||||||
|
objectPtr += IndirectBuffers.INT_SIZE;
|
||||||
|
|
||||||
// write object
|
// write object
|
||||||
writer.write(objectPtr, object);
|
writer.write(objectPtr, object);
|
||||||
objectPtr += instanceStride;
|
objectPtr += instanceStride;
|
||||||
|
|
||||||
// write batchID
|
|
||||||
MemoryUtil.memPutInt(batchIDPtr, batchID);
|
|
||||||
batchIDPtr += IndirectBuffers.INT_SIZE;
|
|
||||||
}
|
}
|
||||||
changed.clear();
|
changed.clear();
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,9 @@ import java.nio.ByteBuffer;
|
|||||||
import org.lwjgl.PointerBuffer;
|
import org.lwjgl.PointerBuffer;
|
||||||
import org.lwjgl.opengl.GL;
|
import org.lwjgl.opengl.GL;
|
||||||
import org.lwjgl.opengl.GL20C;
|
import org.lwjgl.opengl.GL20C;
|
||||||
|
import org.lwjgl.opengl.GL31C;
|
||||||
import org.lwjgl.opengl.GLCapabilities;
|
import org.lwjgl.opengl.GLCapabilities;
|
||||||
|
import org.lwjgl.opengl.KHRShaderSubgroup;
|
||||||
import org.lwjgl.system.MemoryStack;
|
import org.lwjgl.system.MemoryStack;
|
||||||
|
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
@ -19,14 +21,16 @@ import net.minecraft.Util;
|
|||||||
public class GlCompat {
|
public class GlCompat {
|
||||||
public static final boolean ALLOW_DSA = true;
|
public static final boolean ALLOW_DSA = true;
|
||||||
public static final GLCapabilities CAPABILITIES = GL.createCapabilities();
|
public static final GLCapabilities CAPABILITIES = GL.createCapabilities();
|
||||||
private static final boolean amd = _decideIfWeAreAMDWindows();
|
private static final boolean amd = _decideIfWeAreAMD();
|
||||||
|
private static final boolean windows = _decideIfWeAreWindows();
|
||||||
private static final boolean supportsIndirect = _decideIfWeSupportIndirect();
|
private static final boolean supportsIndirect = _decideIfWeSupportIndirect();
|
||||||
|
public static final int SUBGROUP_SIZE = _subgroupSize();
|
||||||
|
|
||||||
private GlCompat() {
|
private GlCompat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean onAMDWindows() {
|
public static boolean onAMDWindows() {
|
||||||
return amd;
|
return amd && windows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean supportsInstancing() {
|
public static boolean supportsInstancing() {
|
||||||
@ -41,6 +45,14 @@ public class GlCompat {
|
|||||||
return CAPABILITIES.OpenGL46 || (CAPABILITIES.GL_ARB_compute_shader && CAPABILITIES.GL_ARB_shader_draw_parameters && CAPABILITIES.GL_ARB_base_instance && CAPABILITIES.GL_ARB_multi_draw_indirect && CAPABILITIES.GL_ARB_direct_state_access);
|
return CAPABILITIES.OpenGL46 || (CAPABILITIES.GL_ARB_compute_shader && CAPABILITIES.GL_ARB_shader_draw_parameters && CAPABILITIES.GL_ARB_base_instance && CAPABILITIES.GL_ARB_multi_draw_indirect && CAPABILITIES.GL_ARB_direct_state_access);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int _subgroupSize() {
|
||||||
|
if (CAPABILITIES.GL_KHR_shader_subgroup) {
|
||||||
|
return GL31C.glGetInteger(KHRShaderSubgroup.GL_SUBGROUP_SIZE_KHR);
|
||||||
|
}
|
||||||
|
// try to guess
|
||||||
|
return amd ? 64 : 32;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modified from:
|
* Modified from:
|
||||||
* <br> <a href="https://github.com/grondag/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96">canvas</a>
|
* <br> <a href="https://github.com/grondag/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96">canvas</a>
|
||||||
@ -62,11 +74,11 @@ public class GlCompat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean _decideIfWeAreAMDWindows() {
|
private static boolean _decideIfWeAreWindows() {
|
||||||
if (Util.getPlatform() != Util.OS.WINDOWS) {
|
return Util.getPlatform() == Util.OS.WINDOWS;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
private static boolean _decideIfWeAreAMD() {
|
||||||
String vendor = GL20C.glGetString(GL20C.GL_VENDOR);
|
String vendor = GL20C.glGetString(GL20C.GL_VENDOR);
|
||||||
|
|
||||||
if (vendor == null) {
|
if (vendor == null) {
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
#define FLW_SUBGROUP_SIZE 32
|
|
||||||
layout(local_size_x = FLW_SUBGROUP_SIZE) in;
|
layout(local_size_x = FLW_SUBGROUP_SIZE) in;
|
||||||
|
|
||||||
#include "flywheel:internal/indirect_draw_command.glsl"
|
#include "flywheel:internal/indirect_draw_command.glsl"
|
||||||
|
|
||||||
|
struct Object {
|
||||||
|
uint batchID;
|
||||||
|
FlwPackedInstance instance;
|
||||||
|
};
|
||||||
|
|
||||||
// populated by instancers
|
// populated by instancers
|
||||||
layout(std430, binding = 0) restrict readonly buffer ObjectBuffer {
|
layout(std430, binding = 0) restrict readonly buffer ObjectBuffer {
|
||||||
FlwPackedInstance objects[];
|
Object objects[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 1) restrict writeonly buffer TargetBuffer {
|
layout(std430, binding = 1) restrict writeonly buffer TargetBuffer {
|
||||||
uint objectIDs[];
|
uint objectIDs[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 2) restrict readonly buffer BatchBuffer {
|
layout(std430, binding = 2) restrict buffer DrawCommands {
|
||||||
uint batchIDs[];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(std430, binding = 3) restrict buffer DrawCommands {
|
|
||||||
MeshDrawCommand drawCommands[];
|
MeshDrawCommand drawCommands[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ bool isVisible() {
|
|||||||
float radius;
|
float radius;
|
||||||
unpackBoundingSphere(sphere, center, radius);
|
unpackBoundingSphere(sphere, center, radius);
|
||||||
|
|
||||||
FlwInstance object = _flw_unpackInstance(objects[flw_objectID]);
|
FlwInstance object = _flw_unpackInstance(objects[flw_objectID].instance);
|
||||||
flw_transformBoundingSphere(object, center, radius);
|
flw_transformBoundingSphere(object, center, radius);
|
||||||
|
|
||||||
return testSphere(center, radius);
|
return testSphere(center, radius);
|
||||||
@ -51,7 +51,7 @@ void main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
flw_batchID = batchIDs[flw_objectID];
|
flw_batchID = objects[flw_objectID].batchID;
|
||||||
|
|
||||||
if (isVisible()) {
|
if (isVisible()) {
|
||||||
uint batchIndex = atomicAdd(drawCommands[flw_batchID].instanceCount, 1);
|
uint batchIndex = atomicAdd(drawCommands[flw_batchID].instanceCount, 1);
|
||||||
|
@ -1,26 +1,28 @@
|
|||||||
#include "flywheel:api/vertex.glsl"
|
#include "flywheel:api/vertex.glsl"
|
||||||
#include "flywheel:internal/indirect_draw_command.glsl"
|
#include "flywheel:internal/indirect_draw_command.glsl"
|
||||||
|
|
||||||
|
struct Object {
|
||||||
|
uint batchID;
|
||||||
|
FlwPackedInstance instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
layout(std430, binding = 0) restrict readonly buffer ObjectBuffer {
|
layout(std430, binding = 0) restrict readonly buffer ObjectBuffer {
|
||||||
FlwPackedInstance objects[];
|
Object objects[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 1) restrict readonly buffer TargetBuffer {
|
layout(std430, binding = 1) restrict readonly buffer TargetBuffer {
|
||||||
uint objectIDs[];
|
uint objectIDs[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 2) restrict readonly buffer BatchBuffer {
|
layout(std430, binding = 2) restrict readonly buffer DrawCommands {
|
||||||
uint batchIDs[];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(std430, binding = 3) restrict readonly buffer DrawCommands {
|
|
||||||
MeshDrawCommand drawCommands[];
|
MeshDrawCommand drawCommands[];
|
||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
uint instanceIndex = objectIDs[gl_BaseInstance + gl_InstanceID];
|
uint instanceIndex = objectIDs[gl_BaseInstance + gl_InstanceID];
|
||||||
uint batchID = batchIDs[instanceIndex];
|
uint batchID = objects[instanceIndex].batchID;
|
||||||
FlwInstance i = _flw_unpackInstance(objects[instanceIndex]);
|
FlwInstance i = _flw_unpackInstance(objects[instanceIndex].instance);
|
||||||
|
|
||||||
_flw_materialVertexID = drawCommands[batchID].vertexMaterialID;
|
_flw_materialVertexID = drawCommands[batchID].vertexMaterialID;
|
||||||
_flw_materialFragmentID = drawCommands[batchID].fragmentMaterialID;
|
_flw_materialFragmentID = drawCommands[batchID].fragmentMaterialID;
|
||||||
|
Loading…
Reference in New Issue
Block a user