2025-11-24 22:52:51 +03:00

438 lines
17 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* org.jspecify.annotations.Nullable
*/
package com.mojang.blaze3d.pipeline;
import com.mojang.blaze3d.pipeline.BlendFunction;
import com.mojang.blaze3d.platform.DepthTestFunction;
import com.mojang.blaze3d.platform.LogicOp;
import com.mojang.blaze3d.platform.PolygonMode;
import com.mojang.blaze3d.shaders.UniformType;
import com.mojang.blaze3d.textures.TextureFormat;
import com.mojang.blaze3d.vertex.VertexFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import net.minecraft.SharedConstants;
import net.minecraft.client.renderer.ShaderDefines;
import net.minecraft.resources.Identifier;
import org.jspecify.annotations.Nullable;
public class RenderPipeline {
private final Identifier location;
private final Identifier vertexShader;
private final Identifier fragmentShader;
private final ShaderDefines shaderDefines;
private final List<String> samplers;
private final List<UniformDescription> uniforms;
private final DepthTestFunction depthTestFunction;
private final PolygonMode polygonMode;
private final boolean cull;
private final LogicOp colorLogic;
private final Optional<BlendFunction> blendFunction;
private final boolean writeColor;
private final boolean writeAlpha;
private final boolean writeDepth;
private final VertexFormat vertexFormat;
private final VertexFormat.Mode vertexFormatMode;
private final float depthBiasScaleFactor;
private final float depthBiasConstant;
private final int sortKey;
private static int sortKeySeed;
protected RenderPipeline(Identifier location, Identifier vertexShader, Identifier fragmentShader, ShaderDefines shaderDefines, List<String> samplers, List<UniformDescription> uniforms, Optional<BlendFunction> blendFunction, DepthTestFunction depthTestFunction, PolygonMode polygonMode, boolean cull, boolean writeColor, boolean writeAlpha, boolean writeDepth, LogicOp colorLogic, VertexFormat vertexFormat, VertexFormat.Mode vertexFormatMode, float depthBiasScaleFactor, float depthBiasConstant, int sortKey) {
this.location = location;
this.vertexShader = vertexShader;
this.fragmentShader = fragmentShader;
this.shaderDefines = shaderDefines;
this.samplers = samplers;
this.uniforms = uniforms;
this.depthTestFunction = depthTestFunction;
this.polygonMode = polygonMode;
this.cull = cull;
this.blendFunction = blendFunction;
this.writeColor = writeColor;
this.writeAlpha = writeAlpha;
this.writeDepth = writeDepth;
this.colorLogic = colorLogic;
this.vertexFormat = vertexFormat;
this.vertexFormatMode = vertexFormatMode;
this.depthBiasScaleFactor = depthBiasScaleFactor;
this.depthBiasConstant = depthBiasConstant;
this.sortKey = sortKey;
}
public int getSortKey() {
return SharedConstants.DEBUG_SHUFFLE_UI_RENDERING_ORDER ? super.hashCode() * (sortKeySeed + 1) : this.sortKey;
}
public static void updateSortKeySeed() {
sortKeySeed = Math.round(100000.0f * (float)Math.random());
}
public String toString() {
return this.location.toString();
}
public DepthTestFunction getDepthTestFunction() {
return this.depthTestFunction;
}
public PolygonMode getPolygonMode() {
return this.polygonMode;
}
public boolean isCull() {
return this.cull;
}
public LogicOp getColorLogic() {
return this.colorLogic;
}
public Optional<BlendFunction> getBlendFunction() {
return this.blendFunction;
}
public boolean isWriteColor() {
return this.writeColor;
}
public boolean isWriteAlpha() {
return this.writeAlpha;
}
public boolean isWriteDepth() {
return this.writeDepth;
}
public float getDepthBiasScaleFactor() {
return this.depthBiasScaleFactor;
}
public float getDepthBiasConstant() {
return this.depthBiasConstant;
}
public Identifier getLocation() {
return this.location;
}
public VertexFormat getVertexFormat() {
return this.vertexFormat;
}
public VertexFormat.Mode getVertexFormatMode() {
return this.vertexFormatMode;
}
public Identifier getVertexShader() {
return this.vertexShader;
}
public Identifier getFragmentShader() {
return this.fragmentShader;
}
public ShaderDefines getShaderDefines() {
return this.shaderDefines;
}
public List<String> getSamplers() {
return this.samplers;
}
public List<UniformDescription> getUniforms() {
return this.uniforms;
}
public boolean wantsDepthTexture() {
return this.depthTestFunction != DepthTestFunction.NO_DEPTH_TEST || this.depthBiasConstant != 0.0f || this.depthBiasScaleFactor != 0.0f || this.writeDepth;
}
public static Builder builder(Snippet ... snippets) {
Builder builder = new Builder();
for (Snippet snippet : snippets) {
builder.withSnippet(snippet);
}
return builder;
}
public static class Builder {
private static int nextPipelineSortKey;
private Optional<Identifier> location = Optional.empty();
private Optional<Identifier> fragmentShader = Optional.empty();
private Optional<Identifier> vertexShader = Optional.empty();
private Optional<ShaderDefines.Builder> definesBuilder = Optional.empty();
private Optional<List<String>> samplers = Optional.empty();
private Optional<List<UniformDescription>> uniforms = Optional.empty();
private Optional<DepthTestFunction> depthTestFunction = Optional.empty();
private Optional<PolygonMode> polygonMode = Optional.empty();
private Optional<Boolean> cull = Optional.empty();
private Optional<Boolean> writeColor = Optional.empty();
private Optional<Boolean> writeAlpha = Optional.empty();
private Optional<Boolean> writeDepth = Optional.empty();
private Optional<LogicOp> colorLogic = Optional.empty();
private Optional<BlendFunction> blendFunction = Optional.empty();
private Optional<VertexFormat> vertexFormat = Optional.empty();
private Optional<VertexFormat.Mode> vertexFormatMode = Optional.empty();
private float depthBiasScaleFactor;
private float depthBiasConstant;
private Builder() {
}
public Builder withLocation(String location) {
this.location = Optional.of(Identifier.withDefaultNamespace(location));
return this;
}
public Builder withLocation(Identifier location) {
this.location = Optional.of(location);
return this;
}
public Builder withFragmentShader(String fragmentShader) {
this.fragmentShader = Optional.of(Identifier.withDefaultNamespace(fragmentShader));
return this;
}
public Builder withFragmentShader(Identifier fragmentShader) {
this.fragmentShader = Optional.of(fragmentShader);
return this;
}
public Builder withVertexShader(String vertexShader) {
this.vertexShader = Optional.of(Identifier.withDefaultNamespace(vertexShader));
return this;
}
public Builder withVertexShader(Identifier vertexShader) {
this.vertexShader = Optional.of(vertexShader);
return this;
}
public Builder withShaderDefine(String key) {
if (this.definesBuilder.isEmpty()) {
this.definesBuilder = Optional.of(ShaderDefines.builder());
}
this.definesBuilder.get().define(key);
return this;
}
public Builder withShaderDefine(String key, int value) {
if (this.definesBuilder.isEmpty()) {
this.definesBuilder = Optional.of(ShaderDefines.builder());
}
this.definesBuilder.get().define(key, value);
return this;
}
public Builder withShaderDefine(String key, float value) {
if (this.definesBuilder.isEmpty()) {
this.definesBuilder = Optional.of(ShaderDefines.builder());
}
this.definesBuilder.get().define(key, value);
return this;
}
public Builder withSampler(String sampler) {
if (this.samplers.isEmpty()) {
this.samplers = Optional.of(new ArrayList());
}
this.samplers.get().add(sampler);
return this;
}
public Builder withUniform(String name, UniformType type) {
if (this.uniforms.isEmpty()) {
this.uniforms = Optional.of(new ArrayList());
}
if (type == UniformType.TEXEL_BUFFER) {
throw new IllegalArgumentException("Cannot use texel buffer without specifying texture format");
}
this.uniforms.get().add(new UniformDescription(name, type));
return this;
}
public Builder withUniform(String name, UniformType type, TextureFormat format) {
if (this.uniforms.isEmpty()) {
this.uniforms = Optional.of(new ArrayList());
}
if (type != UniformType.TEXEL_BUFFER) {
throw new IllegalArgumentException("Only texel buffer can specify texture format");
}
this.uniforms.get().add(new UniformDescription(name, format));
return this;
}
public Builder withDepthTestFunction(DepthTestFunction depthTestFunction) {
this.depthTestFunction = Optional.of(depthTestFunction);
return this;
}
public Builder withPolygonMode(PolygonMode polygonMode) {
this.polygonMode = Optional.of(polygonMode);
return this;
}
public Builder withCull(boolean cull) {
this.cull = Optional.of(cull);
return this;
}
public Builder withBlend(BlendFunction blendFunction) {
this.blendFunction = Optional.of(blendFunction);
return this;
}
public Builder withoutBlend() {
this.blendFunction = Optional.empty();
return this;
}
public Builder withColorWrite(boolean writeColor) {
this.writeColor = Optional.of(writeColor);
this.writeAlpha = Optional.of(writeColor);
return this;
}
public Builder withColorWrite(boolean writeColor, boolean writeAlpha) {
this.writeColor = Optional.of(writeColor);
this.writeAlpha = Optional.of(writeAlpha);
return this;
}
public Builder withDepthWrite(boolean writeDepth) {
this.writeDepth = Optional.of(writeDepth);
return this;
}
@Deprecated
public Builder withColorLogic(LogicOp colorLogic) {
this.colorLogic = Optional.of(colorLogic);
return this;
}
public Builder withVertexFormat(VertexFormat vertexFormat, VertexFormat.Mode vertexFormatMode) {
this.vertexFormat = Optional.of(vertexFormat);
this.vertexFormatMode = Optional.of(vertexFormatMode);
return this;
}
public Builder withDepthBias(float scaleFactor, float constant) {
this.depthBiasScaleFactor = scaleFactor;
this.depthBiasConstant = constant;
return this;
}
private void withSnippet(Snippet snippet) {
if (snippet.vertexShader.isPresent()) {
this.vertexShader = snippet.vertexShader;
}
if (snippet.fragmentShader.isPresent()) {
this.fragmentShader = snippet.fragmentShader;
}
if (snippet.shaderDefines.isPresent()) {
if (this.definesBuilder.isEmpty()) {
this.definesBuilder = Optional.of(ShaderDefines.builder());
}
ShaderDefines snippetDefines = snippet.shaderDefines.get();
for (Map.Entry<String, String> snippetValue : snippetDefines.values().entrySet()) {
this.definesBuilder.get().define(snippetValue.getKey(), snippetValue.getValue());
}
for (String flag : snippetDefines.flags()) {
this.definesBuilder.get().define(flag);
}
}
snippet.samplers.ifPresent(builderSamplers -> {
if (this.samplers.isPresent()) {
this.samplers.get().addAll((Collection<String>)builderSamplers);
} else {
this.samplers = Optional.of(new ArrayList(builderSamplers));
}
});
snippet.uniforms.ifPresent(builderUniforms -> {
if (this.uniforms.isPresent()) {
this.uniforms.get().addAll((Collection<UniformDescription>)builderUniforms);
} else {
this.uniforms = Optional.of(new ArrayList(builderUniforms));
}
});
if (snippet.depthTestFunction.isPresent()) {
this.depthTestFunction = snippet.depthTestFunction;
}
if (snippet.cull.isPresent()) {
this.cull = snippet.cull;
}
if (snippet.writeColor.isPresent()) {
this.writeColor = snippet.writeColor;
}
if (snippet.writeAlpha.isPresent()) {
this.writeAlpha = snippet.writeAlpha;
}
if (snippet.writeDepth.isPresent()) {
this.writeDepth = snippet.writeDepth;
}
if (snippet.colorLogic.isPresent()) {
this.colorLogic = snippet.colorLogic;
}
if (snippet.blendFunction.isPresent()) {
this.blendFunction = snippet.blendFunction;
}
if (snippet.vertexFormat.isPresent()) {
this.vertexFormat = snippet.vertexFormat;
}
if (snippet.vertexFormatMode.isPresent()) {
this.vertexFormatMode = snippet.vertexFormatMode;
}
}
public Snippet buildSnippet() {
return new Snippet(this.vertexShader, this.fragmentShader, this.definesBuilder.map(ShaderDefines.Builder::build), this.samplers.map(Collections::unmodifiableList), this.uniforms.map(Collections::unmodifiableList), this.blendFunction, this.depthTestFunction, this.polygonMode, this.cull, this.writeColor, this.writeAlpha, this.writeDepth, this.colorLogic, this.vertexFormat, this.vertexFormatMode);
}
public RenderPipeline build() {
if (this.location.isEmpty()) {
throw new IllegalStateException("Missing location");
}
if (this.vertexShader.isEmpty()) {
throw new IllegalStateException("Missing vertex shader");
}
if (this.fragmentShader.isEmpty()) {
throw new IllegalStateException("Missing fragment shader");
}
if (this.vertexFormat.isEmpty()) {
throw new IllegalStateException("Missing vertex buffer format");
}
if (this.vertexFormatMode.isEmpty()) {
throw new IllegalStateException("Missing vertex mode");
}
return new RenderPipeline(this.location.get(), this.vertexShader.get(), this.fragmentShader.get(), this.definesBuilder.orElse(ShaderDefines.builder()).build(), List.copyOf(this.samplers.orElse(new ArrayList())), this.uniforms.orElse(Collections.emptyList()), this.blendFunction, this.depthTestFunction.orElse(DepthTestFunction.LEQUAL_DEPTH_TEST), this.polygonMode.orElse(PolygonMode.FILL), this.cull.orElse(true), this.writeColor.orElse(true), this.writeAlpha.orElse(true), this.writeDepth.orElse(true), this.colorLogic.orElse(LogicOp.NONE), this.vertexFormat.get(), this.vertexFormatMode.get(), this.depthBiasScaleFactor, this.depthBiasConstant, nextPipelineSortKey++);
}
}
public record Snippet(Optional<Identifier> vertexShader, Optional<Identifier> fragmentShader, Optional<ShaderDefines> shaderDefines, Optional<List<String>> samplers, Optional<List<UniformDescription>> uniforms, Optional<BlendFunction> blendFunction, Optional<DepthTestFunction> depthTestFunction, Optional<PolygonMode> polygonMode, Optional<Boolean> cull, Optional<Boolean> writeColor, Optional<Boolean> writeAlpha, Optional<Boolean> writeDepth, Optional<LogicOp> colorLogic, Optional<VertexFormat> vertexFormat, Optional<VertexFormat.Mode> vertexFormatMode) {
}
public record UniformDescription(String name, UniformType type, @Nullable TextureFormat textureFormat) {
public UniformDescription(String name, UniformType type) {
this(name, type, null);
if (type == UniformType.TEXEL_BUFFER) {
throw new IllegalArgumentException("Texel buffer needs a texture format");
}
}
public UniformDescription(String name, TextureFormat textureFormat) {
this(name, UniformType.TEXEL_BUFFER, textureFormat);
}
}
}