Skip to content

Commit

Permalink
Harvesting
Browse files Browse the repository at this point in the history
- Cherry-pick misc cleanups from last-frame-visibility
- Smarter multibind logic
- Make offsets in IndirectBuffers dependent on BufferBindings
- Organize buffer bindings based on where they're used to allow each
  pass to bind exactly which buffers it needs
- Use DSA for the depth pyramid
- Pass the map of util programs to IndirectPrograms rather than
  unpacking them individually
- Actually delete all the indirect utils
  • Loading branch information
Jozufozu committed Sep 14, 2024
1 parent f009cb8 commit a527af5
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class IndirectPrograms extends AtomicReferenceCounted {
private static final ResourceLocation APPLY_SHADER_MAIN = Flywheel.rl("internal/indirect/apply.glsl");
private static final ResourceLocation SCATTER_SHADER_MAIN = Flywheel.rl("internal/indirect/scatter.glsl");
private static final ResourceLocation DEPTH_REDUCE_SHADER_MAIN = Flywheel.rl("internal/indirect/depth_reduce.glsl");
public static final List<ResourceLocation> UTIL_SHADERS = List.of(APPLY_SHADER_MAIN, SCATTER_SHADER_MAIN, DEPTH_REDUCE_SHADER_MAIN);

private static final Compile<InstanceType<?>> CULL = new Compile<>();
private static final Compile<ResourceLocation> UTIL = new Compile<>();
Expand All @@ -43,16 +44,12 @@ public class IndirectPrograms extends AtomicReferenceCounted {

private final Map<PipelineProgramKey, GlProgram> pipeline;
private final Map<InstanceType<?>, GlProgram> culling;
private final GlProgram apply;
private final GlProgram scatter;
private final GlProgram depthReduce;
private final Map<ResourceLocation, GlProgram> utils;

private IndirectPrograms(Map<PipelineProgramKey, GlProgram> pipeline, Map<InstanceType<?>, GlProgram> culling, GlProgram apply, GlProgram scatter, GlProgram depthReduce) {
private IndirectPrograms(Map<PipelineProgramKey, GlProgram> pipeline, Map<InstanceType<?>, GlProgram> culling, Map<ResourceLocation, GlProgram> utils) {
this.pipeline = pipeline;
this.culling = culling;
this.apply = apply;
this.scatter = scatter;
this.depthReduce = depthReduce;
this.utils = utils;
}

private static List<String> getExtensions(GlslVersion glslVersion) {
Expand Down Expand Up @@ -97,10 +94,10 @@ static void reload(ShaderSources sources, ImmutableList<PipelineProgramKey> pipe
try {
var pipelineResult = pipelineCompiler.compileAndReportErrors(pipelineKeys);
var cullingResult = cullingCompiler.compileAndReportErrors(createCullingKeys());
var utils = utilCompiler.compileAndReportErrors(List.of(APPLY_SHADER_MAIN, SCATTER_SHADER_MAIN, DEPTH_REDUCE_SHADER_MAIN));
var utils = utilCompiler.compileAndReportErrors(UTIL_SHADERS);

if (pipelineResult != null && cullingResult != null && utils != null) {
newInstance = new IndirectPrograms(pipelineResult, cullingResult, utils.get(APPLY_SHADER_MAIN), utils.get(SCATTER_SHADER_MAIN), utils.get(DEPTH_REDUCE_SHADER_MAIN));
newInstance = new IndirectPrograms(pipelineResult, cullingResult, utils);
}
} catch (Throwable t) {
FlwPrograms.LOGGER.error("Failed to compile indirect programs", t);
Expand Down Expand Up @@ -180,23 +177,23 @@ public GlProgram getCullingProgram(InstanceType<?> instanceType) {
}

public GlProgram getApplyProgram() {
return apply;
return utils.get(APPLY_SHADER_MAIN);
}

public GlProgram getScatterProgram() {
return scatter;
return utils.get(SCATTER_SHADER_MAIN);
}

public GlProgram getDepthReduceProgram() {
return depthReduce;
return utils.get(DEPTH_REDUCE_SHADER_MAIN);
}

@Override
protected void _delete() {
pipeline.values()
.forEach(GlProgram::delete);
culling.values()
.forEach(GlProgram::delete);
apply.delete();
utils.values()
.forEach(GlProgram::delete);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package dev.engine_room.flywheel.backend.engine.indirect;

public final class BufferBindings {
public static final int INSTANCE = 0;
public static final int TARGET = 1;
public static final int PAGE_FRAME_DESCRIPTOR = 2;
public static final int PAGE_FRAME_DESCRIPTOR = 0;
public static final int INSTANCE = 1;
public static final int DRAW_INSTANCE_INDEX = 2;
public static final int MODEL = 3;
public static final int DRAW = 4;

public static final int LIGHT_LUT = 5;
public static final int LIGHT_SECTION = 6;
public static final int MATRICES = 7;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,21 @@

import com.mojang.blaze3d.platform.GlStateManager;

import dev.engine_room.flywheel.backend.gl.GlTextureUnit;
import dev.engine_room.flywheel.backend.gl.shader.GlProgram;
import dev.engine_room.flywheel.lib.math.MoreMath;
import net.minecraft.client.Minecraft;

public class DepthPyramid {
private final GlProgram depthReduceProgram;

public final int pyramidTextureId;
public int pyramidTextureId = -1;

private int lastWidth = -1;
private int lastHeight = -1;

public DepthPyramid(GlProgram depthReduceProgram) {
this.depthReduceProgram = depthReduceProgram;

pyramidTextureId = GL32.glGenTextures();

GlStateManager._bindTexture(pyramidTextureId);
GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST);
GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST);
GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_COMPARE_MODE, GL32.GL_NONE);
GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_WRAP_S, GL32.GL_CLAMP_TO_EDGE);
GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_WRAP_T, GL32.GL_CLAMP_TO_EDGE);

}

public void generate() {
Expand All @@ -44,11 +35,9 @@ public void generate() {

int depthBufferId = mainRenderTarget.getDepthTextureId();

GlStateManager._bindTexture(depthBufferId);

GL46.glMemoryBarrier(GL46.GL_FRAMEBUFFER_BARRIER_BIT);

GL46.glActiveTexture(GL32.GL_TEXTURE1);
GlTextureUnit.T1.makeActive();

depthReduceProgram.bind();

Expand All @@ -57,7 +46,7 @@ public void generate() {
int mipHeight = mipSize(height, i);

int srcTexture = (i == 0) ? depthBufferId : pyramidTextureId;
GL46.glBindTexture(GL32.GL_TEXTURE_2D, srcTexture);
GlStateManager._bindTexture(srcTexture);

GL46.glBindImageTexture(0, pyramidTextureId, i, false, 0, GL32.GL_WRITE_ONLY, GL32.GL_R32F);

Expand All @@ -71,7 +60,10 @@ public void generate() {
}

public void delete() {
GL32.glDeleteTextures(pyramidTextureId);
if (pyramidTextureId != -1) {
GL32.glDeleteTextures(pyramidTextureId);
pyramidTextureId = -1;
}
}

private void createPyramidMips(int mipLevels, int width, int height) {
Expand All @@ -82,14 +74,16 @@ private void createPyramidMips(int mipLevels, int width, int height) {
lastWidth = width;
lastHeight = height;

GL32.glBindTexture(GL32.GL_TEXTURE_2D, pyramidTextureId);
delete();

for (int i = 0; i < mipLevels; i++) {
int mipWidth = mipSize(width, i);
int mipHeight = mipSize(height, i);
pyramidTextureId = GL46.glCreateTextures(GL46.GL_TEXTURE_2D);
GL46.glTextureStorage2D(pyramidTextureId, mipLevels, GL32.GL_R32F, width, height);

GL32.glTexImage2D(GL32.GL_TEXTURE_2D, i, GL32.GL_R32F, mipWidth, mipHeight, 0, GL32.GL_RED, GL32.GL_FLOAT, 0);
}
GL46.glTextureParameteri(pyramidTextureId, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST);
GL46.glTextureParameteri(pyramidTextureId, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST);
GL46.glTextureParameteri(pyramidTextureId, GL32.GL_TEXTURE_COMPARE_MODE, GL32.GL_NONE);
GL46.glTextureParameteri(pyramidTextureId, GL32.GL_TEXTURE_WRAP_S, GL32.GL_CLAMP_TO_EDGE);
GL46.glTextureParameteri(pyramidTextureId, GL32.GL_TEXTURE_WRAP_T, GL32.GL_CLAMP_TO_EDGE);
}

public static int mipSize(int mip0Size, int level) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,19 @@ public class IndirectBuffers {
private static final long BUFFERS_SIZE_BYTES = SIZE_OFFSET + BUFFER_COUNT * PTR_SIZE;

// Offsets to the vbos
private static final long INSTANCE_HANDLE_OFFSET = HANDLE_OFFSET;
private static final long TARGET_HANDLE_OFFSET = INT_SIZE;
private static final long PAGE_FRAME_DESCRIPTOR_HANDLE_OFFSET = INT_SIZE * 2;
private static final long MODEL_HANDLE_OFFSET = INT_SIZE * 3;
private static final long DRAW_HANDLE_OFFSET = INT_SIZE * 4;
private static final long PAGE_FRAME_DESCRIPTOR_HANDLE_OFFSET = HANDLE_OFFSET + BufferBindings.PAGE_FRAME_DESCRIPTOR * INT_SIZE;
private static final long INSTANCE_HANDLE_OFFSET = HANDLE_OFFSET + BufferBindings.INSTANCE * INT_SIZE;
private static final long DRAW_INSTANCE_INDEX_HANDLE_OFFSET = HANDLE_OFFSET + BufferBindings.DRAW_INSTANCE_INDEX * INT_SIZE;
private static final long MODEL_HANDLE_OFFSET = HANDLE_OFFSET + BufferBindings.MODEL * INT_SIZE;
private static final long DRAW_HANDLE_OFFSET = HANDLE_OFFSET + BufferBindings.DRAW * INT_SIZE;

// Offsets to the sizes
private static final long INSTANCE_SIZE_OFFSET = SIZE_OFFSET;
private static final long TARGET_SIZE_OFFSET = SIZE_OFFSET + PTR_SIZE;
private static final long PAGE_FRAME_DESCRIPTOR_SIZE_OFFSET = SIZE_OFFSET + PTR_SIZE * 2;
private static final long MODEL_SIZE_OFFSET = SIZE_OFFSET + PTR_SIZE * 3;
private static final long DRAW_SIZE_OFFSET = SIZE_OFFSET + PTR_SIZE * 4;
private static final long PAGE_FRAME_DESCRIPTOR_SIZE_OFFSET = SIZE_OFFSET + BufferBindings.PAGE_FRAME_DESCRIPTOR * PTR_SIZE;
private static final long INSTANCE_SIZE_OFFSET = SIZE_OFFSET + BufferBindings.INSTANCE * PTR_SIZE;
private static final long DRAW_INSTANCE_INDEX_SIZE_OFFSET = SIZE_OFFSET + BufferBindings.DRAW_INSTANCE_INDEX * PTR_SIZE;
private static final long MODEL_SIZE_OFFSET = SIZE_OFFSET + BufferBindings.MODEL * PTR_SIZE;
private static final long DRAW_SIZE_OFFSET = SIZE_OFFSET + BufferBindings.DRAW * PTR_SIZE;


private static final float INSTANCE_GROWTH_FACTOR = 1.25f;
private static final float MODEL_GROWTH_FACTOR = 2f;
Expand All @@ -60,69 +61,71 @@ public class IndirectBuffers {
* one for the instance buffer, target buffer, model index buffer, model buffer, and draw buffer.
*/
private final MemoryBlock multiBindBlock;
private final long instanceStride;

public final ObjectStorage objectStorage;
public final ResizableStorageArray target;
public final ResizableStorageArray drawInstanceIndex;
public final ResizableStorageArray model;
public final ResizableStorageArray draw;

IndirectBuffers(long instanceStride) {
this.instanceStride = instanceStride;
this.multiBindBlock = MemoryBlock.calloc(BUFFERS_SIZE_BYTES, 1);

objectStorage = new ObjectStorage(instanceStride);
target = new ResizableStorageArray(INT_SIZE, INSTANCE_GROWTH_FACTOR);
drawInstanceIndex = new ResizableStorageArray(INT_SIZE, INSTANCE_GROWTH_FACTOR);
model = new ResizableStorageArray(MODEL_STRIDE, MODEL_GROWTH_FACTOR);
draw = new ResizableStorageArray(DRAW_COMMAND_STRIDE, DRAW_GROWTH_FACTOR);
}

void updateCounts(int instanceCount, int modelCount, int drawCount) {
target.ensureCapacity(instanceCount);
drawInstanceIndex.ensureCapacity(instanceCount);
model.ensureCapacity(modelCount);
draw.ensureCapacity(drawCount);

final long ptr = multiBindBlock.ptr();
MemoryUtil.memPutInt(ptr + INSTANCE_HANDLE_OFFSET, objectStorage.objectBuffer.handle());
MemoryUtil.memPutInt(ptr + TARGET_HANDLE_OFFSET, target.handle());

MemoryUtil.memPutInt(ptr + PAGE_FRAME_DESCRIPTOR_HANDLE_OFFSET, objectStorage.frameDescriptorBuffer.handle());
MemoryUtil.memPutInt(ptr + INSTANCE_HANDLE_OFFSET, objectStorage.objectBuffer.handle());
MemoryUtil.memPutInt(ptr + DRAW_INSTANCE_INDEX_HANDLE_OFFSET, drawInstanceIndex.handle());
MemoryUtil.memPutInt(ptr + MODEL_HANDLE_OFFSET, model.handle());
MemoryUtil.memPutInt(ptr + DRAW_HANDLE_OFFSET, draw.handle());

MemoryUtil.memPutAddress(ptr + INSTANCE_SIZE_OFFSET, objectStorage.objectBuffer.capacity());
MemoryUtil.memPutAddress(ptr + TARGET_SIZE_OFFSET, INT_SIZE * instanceCount);
MemoryUtil.memPutAddress(ptr + PAGE_FRAME_DESCRIPTOR_SIZE_OFFSET, objectStorage.frameDescriptorBuffer.capacity());
MemoryUtil.memPutAddress(ptr + INSTANCE_SIZE_OFFSET, objectStorage.objectBuffer.capacity());
MemoryUtil.memPutAddress(ptr + DRAW_INSTANCE_INDEX_SIZE_OFFSET, INT_SIZE * instanceCount);
MemoryUtil.memPutAddress(ptr + MODEL_SIZE_OFFSET, MODEL_STRIDE * modelCount);
MemoryUtil.memPutAddress(ptr + DRAW_SIZE_OFFSET, DRAW_COMMAND_STRIDE * drawCount);
}

public void bindForCompute() {
multiBind();
public void bindForCull() {
multiBind(0, 4);
}

public void bindForDraw() {
multiBind();
GlBufferType.DRAW_INDIRECT_BUFFER.bind(draw.handle());
public void bindForApply() {
multiBind(3, 2);
}

private void multiBind() {
final long ptr = multiBindBlock.ptr();
nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, BufferBindings.INSTANCE, IndirectBuffers.BUFFER_COUNT, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET);
public void bindForDraw() {
multiBind(1, 4);
GlBufferType.DRAW_INDIRECT_BUFFER.bind(draw.handle());
}

/**
* Bind all buffers except the draw command buffer.
*/
public void bindForCrumbling() {
multiBind(3, 3);
}

private void multiBind(int base, int count) {
final long ptr = multiBindBlock.ptr();
nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, BufferBindings.INSTANCE, 4, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET);
nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, base, count, ptr + base * INT_SIZE, ptr + OFFSET_OFFSET + base * PTR_SIZE, ptr + SIZE_OFFSET + base * PTR_SIZE);
}

public void delete() {
multiBindBlock.free();

objectStorage.delete();
target.delete();
drawInstanceIndex.delete();
model.delete();
draw.delete();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public void dispatchCull() {
Uniforms.bindAll();
cullProgram.bind();

buffers.bindForCompute();
buffers.bindForCull();
glDispatchCompute(buffers.objectStorage.capacity(), 1, 1);
}

Expand All @@ -127,7 +127,7 @@ public void dispatchApply() {
return;
}

buffers.bindForCompute();
buffers.bindForApply();
glDispatchCompute(GlCompat.getComputeGroupCount(indirectDraws.size()), 1, 1);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
#define _FLW_INSTANCE_BUFFER_BINDING 0
#define _FLW_TARGET_BUFFER_BINDING 1
#define _FLW_PAGE_FRAME_DESCRIPTOR_BUFFER_BINDING 2
#define _FLW_MODEL_BUFFER_BINDING 3
#define _FLW_DRAW_BUFFER_BINDING 4
// Per culling group
#define _FLW_PAGE_FRAME_DESCRIPTOR_BUFFER_BINDING 0// cull
#define _FLW_INSTANCE_BUFFER_BINDING 1// cull, draw
#define _FLW_DRAW_INSTANCE_INDEX_BUFFER_BINDING 2// cull, draw
#define _FLW_MODEL_BUFFER_BINDING 3// cull, apply
#define _FLW_DRAW_BUFFER_BINDING 4// apply, draw

// Global to the engine
#define _FLW_LIGHT_LUT_BUFFER_BINDING 5
#define _FLW_LIGHT_SECTIONS_BUFFER_BINDING 6

#define _FLW_MATRIX_BUFFER_BINDING 7
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

layout(local_size_x = 32) in;

layout(std430, binding = _FLW_TARGET_BUFFER_BINDING) restrict writeonly buffer TargetBuffer {
layout(std430, binding = _FLW_DRAW_INSTANCE_INDEX_BUFFER_BINDING) restrict writeonly buffer TargetBuffer {
uint _flw_instanceIndices[];
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "flywheel:internal/indirect/light.glsl"
#include "flywheel:internal/indirect/matrices.glsl"

layout(std430, binding = _FLW_TARGET_BUFFER_BINDING) restrict readonly buffer TargetBuffer {
layout(std430, binding = _FLW_DRAW_INSTANCE_INDEX_BUFFER_BINDING) restrict readonly buffer TargetBuffer {
uint _flw_instanceIndices[];
};

Expand Down

0 comments on commit a527af5

Please sign in to comment.