185 lines
8.5 KiB
Java
185 lines
8.5 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* org.lwjgl.system.MemoryStack
|
|
*/
|
|
package net.minecraft.client.renderer;
|
|
|
|
import com.mojang.blaze3d.ProjectionType;
|
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
|
import com.mojang.blaze3d.buffers.Std140Builder;
|
|
import com.mojang.blaze3d.buffers.Std140SizeCalculator;
|
|
import com.mojang.blaze3d.framegraph.FrameGraphBuilder;
|
|
import com.mojang.blaze3d.framegraph.FramePass;
|
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
|
import com.mojang.blaze3d.pipeline.RenderTarget;
|
|
import com.mojang.blaze3d.resource.ResourceHandle;
|
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
|
import com.mojang.blaze3d.systems.RenderPass;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import com.mojang.blaze3d.systems.SamplerCache;
|
|
import com.mojang.blaze3d.textures.FilterMode;
|
|
import com.mojang.blaze3d.textures.GpuSampler;
|
|
import com.mojang.blaze3d.textures.GpuTextureView;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.OptionalDouble;
|
|
import java.util.OptionalInt;
|
|
import net.minecraft.client.renderer.MappableRingBuffer;
|
|
import net.minecraft.client.renderer.UniformValue;
|
|
import net.minecraft.client.renderer.texture.AbstractTexture;
|
|
import net.minecraft.resources.Identifier;
|
|
import org.lwjgl.system.MemoryStack;
|
|
|
|
public class PostPass
|
|
implements AutoCloseable {
|
|
private static final int UBO_SIZE_PER_SAMPLER = new Std140SizeCalculator().putVec2().get();
|
|
private final String name;
|
|
private final RenderPipeline pipeline;
|
|
private final Identifier outputTargetId;
|
|
private final Map<String, GpuBuffer> customUniforms = new HashMap<String, GpuBuffer>();
|
|
private final MappableRingBuffer infoUbo;
|
|
private final List<Input> inputs;
|
|
|
|
public PostPass(RenderPipeline pipeline, Identifier outputTargetId, Map<String, List<UniformValue>> uniformGroups, List<Input> inputs) {
|
|
this.pipeline = pipeline;
|
|
this.name = pipeline.getLocation().toString();
|
|
this.outputTargetId = outputTargetId;
|
|
this.inputs = inputs;
|
|
for (Map.Entry<String, List<UniformValue>> uniformGroup : uniformGroups.entrySet()) {
|
|
List<UniformValue> uniforms = uniformGroup.getValue();
|
|
if (uniforms.isEmpty()) continue;
|
|
Std140SizeCalculator calculator = new Std140SizeCalculator();
|
|
for (UniformValue uniform : uniforms) {
|
|
uniform.addSize(calculator);
|
|
}
|
|
int size = calculator.get();
|
|
MemoryStack stack = MemoryStack.stackPush();
|
|
try {
|
|
Std140Builder builder = Std140Builder.onStack(stack, size);
|
|
for (UniformValue uniform : uniforms) {
|
|
uniform.writeTo(builder);
|
|
}
|
|
this.customUniforms.put(uniformGroup.getKey(), RenderSystem.getDevice().createBuffer(() -> this.name + " / " + (String)uniformGroup.getKey(), 128, builder.get()));
|
|
}
|
|
finally {
|
|
if (stack == null) continue;
|
|
stack.close();
|
|
}
|
|
}
|
|
this.infoUbo = new MappableRingBuffer(() -> this.name + " SamplerInfo", 130, (inputs.size() + 1) * UBO_SIZE_PER_SAMPLER);
|
|
}
|
|
|
|
public void addToFrame(FrameGraphBuilder frame, Map<Identifier, ResourceHandle<RenderTarget>> targets, GpuBufferSlice shaderOrthoMatrix) {
|
|
FramePass pass = frame.addPass(this.name);
|
|
for (Input input : this.inputs) {
|
|
input.addToPass(pass, targets);
|
|
}
|
|
ResourceHandle outputHandle = targets.computeIfPresent(this.outputTargetId, (id, handle) -> pass.readsAndWrites(handle));
|
|
if (outputHandle == null) {
|
|
throw new IllegalStateException("Missing handle for target " + String.valueOf(this.outputTargetId));
|
|
}
|
|
pass.executes(() -> {
|
|
RenderTarget outputTarget = (RenderTarget)outputHandle.get();
|
|
RenderSystem.backupProjectionMatrix();
|
|
RenderSystem.setProjectionMatrix(shaderOrthoMatrix, ProjectionType.ORTHOGRAPHIC);
|
|
CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder();
|
|
SamplerCache samplerCache = RenderSystem.getSamplerCache();
|
|
List<InputTexture> inputTextures = this.inputs.stream().map(i -> new InputTexture(i.samplerName(), i.texture(targets), samplerCache.getClampToEdge(i.bilinear() ? FilterMode.LINEAR : FilterMode.NEAREST))).toList();
|
|
try (GpuBuffer.MappedView view = commandEncoder.mapBuffer(this.infoUbo.currentBuffer(), false, true);){
|
|
Iterator<InputTexture> builder = Std140Builder.intoBuffer(view.data());
|
|
((Std140Builder)((Object)builder)).putVec2(outputTarget.width, outputTarget.height);
|
|
for (InputTexture input : inputTextures) {
|
|
((Std140Builder)((Object)builder)).putVec2(input.view.getWidth(0), input.view.getHeight(0));
|
|
}
|
|
}
|
|
try (RenderPass renderPass = commandEncoder.createRenderPass(() -> "Post pass " + this.name, outputTarget.getColorTextureView(), OptionalInt.empty(), outputTarget.useDepth ? outputTarget.getDepthTextureView() : null, OptionalDouble.empty());){
|
|
renderPass.setPipeline(this.pipeline);
|
|
RenderSystem.bindDefaultUniforms(renderPass);
|
|
renderPass.setUniform("SamplerInfo", this.infoUbo.currentBuffer());
|
|
for (Map.Entry entry : this.customUniforms.entrySet()) {
|
|
renderPass.setUniform((String)entry.getKey(), (GpuBuffer)entry.getValue());
|
|
}
|
|
for (InputTexture inputTexture : inputTextures) {
|
|
renderPass.bindTexture(inputTexture.samplerName() + "Sampler", inputTexture.view(), inputTexture.sampler());
|
|
}
|
|
renderPass.draw(0, 3);
|
|
}
|
|
this.infoUbo.rotate();
|
|
RenderSystem.restoreProjectionMatrix();
|
|
for (Input input : this.inputs) {
|
|
input.cleanup(targets);
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void close() {
|
|
for (GpuBuffer buffer : this.customUniforms.values()) {
|
|
buffer.close();
|
|
}
|
|
this.infoUbo.close();
|
|
}
|
|
|
|
public static interface Input {
|
|
public void addToPass(FramePass var1, Map<Identifier, ResourceHandle<RenderTarget>> var2);
|
|
|
|
default public void cleanup(Map<Identifier, ResourceHandle<RenderTarget>> targets) {
|
|
}
|
|
|
|
public GpuTextureView texture(Map<Identifier, ResourceHandle<RenderTarget>> var1);
|
|
|
|
public String samplerName();
|
|
|
|
public boolean bilinear();
|
|
}
|
|
|
|
record InputTexture(String samplerName, GpuTextureView view, GpuSampler sampler) {
|
|
}
|
|
|
|
public record TargetInput(String samplerName, Identifier targetId, boolean depthBuffer, boolean bilinear) implements Input
|
|
{
|
|
private ResourceHandle<RenderTarget> getHandle(Map<Identifier, ResourceHandle<RenderTarget>> targets) {
|
|
ResourceHandle<RenderTarget> handle = targets.get(this.targetId);
|
|
if (handle == null) {
|
|
throw new IllegalStateException("Missing handle for target " + String.valueOf(this.targetId));
|
|
}
|
|
return handle;
|
|
}
|
|
|
|
@Override
|
|
public void addToPass(FramePass pass, Map<Identifier, ResourceHandle<RenderTarget>> targets) {
|
|
pass.reads(this.getHandle(targets));
|
|
}
|
|
|
|
@Override
|
|
public GpuTextureView texture(Map<Identifier, ResourceHandle<RenderTarget>> targets) {
|
|
GpuTextureView textureView;
|
|
ResourceHandle<RenderTarget> handle = this.getHandle(targets);
|
|
RenderTarget target = handle.get();
|
|
GpuTextureView gpuTextureView = textureView = this.depthBuffer ? target.getDepthTextureView() : target.getColorTextureView();
|
|
if (textureView == null) {
|
|
throw new IllegalStateException("Missing " + (this.depthBuffer ? "depth" : "color") + "texture for target " + String.valueOf(this.targetId));
|
|
}
|
|
return textureView;
|
|
}
|
|
}
|
|
|
|
public record TextureInput(String samplerName, AbstractTexture texture, int width, int height, boolean bilinear) implements Input
|
|
{
|
|
@Override
|
|
public void addToPass(FramePass pass, Map<Identifier, ResourceHandle<RenderTarget>> targets) {
|
|
}
|
|
|
|
@Override
|
|
public GpuTextureView texture(Map<Identifier, ResourceHandle<RenderTarget>> targets) {
|
|
return this.texture.getTextureView();
|
|
}
|
|
}
|
|
}
|
|
|