minecraft-src/com/mojang/blaze3d/opengl/GlCommandEncoder.java
2025-07-04 03:45:38 +03:00

712 lines
28 KiB
Java

package com.mojang.blaze3d.opengl;
import com.mojang.blaze3d.buffers.BufferType;
import com.mojang.blaze3d.buffers.GpuBuffer;
import com.mojang.blaze3d.pipeline.BlendFunction;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.platform.DepthTestFunction;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.platform.Window;
import com.mojang.blaze3d.systems.CommandEncoder;
import com.mojang.blaze3d.systems.RenderPass;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.textures.GpuTexture;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.logging.LogUtils;
import it.unimi.dsi.fastutil.ints.IntList;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Collection;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.function.Consumer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ARGB;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.opengl.GL11;
import org.slf4j.Logger;
@Environment(EnvType.CLIENT)
public class GlCommandEncoder implements CommandEncoder {
private static final Logger LOGGER = LogUtils.getLogger();
private final GlDevice device;
private final int readFbo;
private final int drawFbo;
@Nullable
private RenderPipeline lastPipeline;
private boolean inRenderPass;
@Nullable
private GlProgram lastProgram;
protected GlCommandEncoder(GlDevice device) {
this.device = device;
this.readFbo = device.directStateAccess().createFrameBufferObject();
this.drawFbo = device.directStateAccess().createFrameBufferObject();
}
@Override
public RenderPass createRenderPass(GpuTexture gpuTexture, OptionalInt optionalInt) {
return this.createRenderPass(gpuTexture, optionalInt, null, OptionalDouble.empty());
}
@Override
public RenderPass createRenderPass(GpuTexture gpuTexture, OptionalInt optionalInt, @Nullable GpuTexture gpuTexture2, OptionalDouble optionalDouble) {
if (this.inRenderPass) {
throw new IllegalStateException("Close the existing render pass before creating a new one!");
} else {
if (optionalDouble.isPresent() && gpuTexture2 == null) {
LOGGER.warn("Depth clear value was provided but no depth texture is being used");
}
if (gpuTexture.isClosed()) {
throw new IllegalStateException("Color texture is closed");
} else if (gpuTexture2 != null && gpuTexture2.isClosed()) {
throw new IllegalStateException("Depth texture is closed");
} else {
this.inRenderPass = true;
int i = ((GlTexture)gpuTexture).getFbo(this.device.directStateAccess(), gpuTexture2);
GlStateManager._glBindFramebuffer(36160, i);
int j = 0;
if (optionalInt.isPresent()) {
int k = optionalInt.getAsInt();
GL11.glClearColor(ARGB.redFloat(k), ARGB.greenFloat(k), ARGB.blueFloat(k), ARGB.alphaFloat(k));
j |= 16384;
}
if (gpuTexture2 != null && optionalDouble.isPresent()) {
GL11.glClearDepth(optionalDouble.getAsDouble());
j |= 256;
}
if (j != 0) {
GlStateManager._disableScissorTest();
GlStateManager._depthMask(true);
GlStateManager._colorMask(true, true, true, true);
GlStateManager._clear(j);
}
GlStateManager._viewport(0, 0, gpuTexture.getWidth(0), gpuTexture.getHeight(0));
this.lastPipeline = null;
return new GlRenderPass(this, gpuTexture2 != null);
}
}
}
@Override
public void clearColorTexture(GpuTexture gpuTexture, int i) {
if (this.inRenderPass) {
throw new IllegalStateException("Close the existing render pass before creating a new one!");
} else if (!gpuTexture.getFormat().hasColorAspect()) {
throw new IllegalStateException("Trying to clear a non-color texture as color");
} else if (gpuTexture.isClosed()) {
throw new IllegalStateException("Color texture is closed");
} else {
this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, ((GlTexture)gpuTexture).id, 0, 0, 36160);
GL11.glClearColor(ARGB.redFloat(i), ARGB.greenFloat(i), ARGB.blueFloat(i), ARGB.alphaFloat(i));
GlStateManager._disableScissorTest();
GlStateManager._colorMask(true, true, true, true);
GlStateManager._clear(16384);
GlStateManager._glFramebufferTexture2D(36160, 36064, 3553, 0, 0);
GlStateManager._glBindFramebuffer(36160, 0);
}
}
@Override
public void clearColorAndDepthTextures(GpuTexture gpuTexture, int i, GpuTexture gpuTexture2, double d) {
if (this.inRenderPass) {
throw new IllegalStateException("Close the existing render pass before creating a new one!");
} else if (!gpuTexture.getFormat().hasColorAspect()) {
throw new IllegalStateException("Trying to clear a non-color texture as color");
} else if (!gpuTexture2.getFormat().hasDepthAspect()) {
throw new IllegalStateException("Trying to clear a non-depth texture as depth");
} else if (gpuTexture.isClosed()) {
throw new IllegalStateException("Color texture is closed");
} else if (gpuTexture2.isClosed()) {
throw new IllegalStateException("Depth texture is closed");
} else {
int j = ((GlTexture)gpuTexture).getFbo(this.device.directStateAccess(), gpuTexture2);
GlStateManager._glBindFramebuffer(36160, j);
GlStateManager._disableScissorTest();
GL11.glClearDepth(d);
GL11.glClearColor(ARGB.redFloat(i), ARGB.greenFloat(i), ARGB.blueFloat(i), ARGB.alphaFloat(i));
GlStateManager._depthMask(true);
GlStateManager._colorMask(true, true, true, true);
GlStateManager._clear(16640);
GlStateManager._glBindFramebuffer(36160, 0);
}
}
@Override
public void clearDepthTexture(GpuTexture gpuTexture, double d) {
if (this.inRenderPass) {
throw new IllegalStateException("Close the existing render pass before creating a new one!");
} else if (!gpuTexture.getFormat().hasDepthAspect()) {
throw new IllegalStateException("Trying to clear a non-depth texture as depth");
} else if (gpuTexture.isClosed()) {
throw new IllegalStateException("Depth texture is closed");
} else {
this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)gpuTexture).id, 0, 36160);
GL11.glDrawBuffer(0);
GL11.glClearDepth(d);
GlStateManager._depthMask(true);
GlStateManager._disableScissorTest();
GlStateManager._clear(256);
GL11.glDrawBuffer(36064);
GlStateManager._glFramebufferTexture2D(36160, 36096, 3553, 0, 0);
GlStateManager._glBindFramebuffer(36160, 0);
}
}
@Override
public void writeToBuffer(GpuBuffer gpuBuffer, ByteBuffer byteBuffer, int i) {
if (this.inRenderPass) {
throw new IllegalStateException("Close the existing render pass before performing additional commands");
} else {
GlBuffer glBuffer = (GlBuffer)gpuBuffer;
if (glBuffer.closed) {
throw new IllegalStateException("Buffer already closed");
} else if (!glBuffer.usage().isWritable()) {
throw new IllegalStateException("Buffer is not writable");
} else {
int j = byteBuffer.remaining();
if (j + i > glBuffer.size) {
throw new IllegalArgumentException(
"Cannot write more data than this buffer can hold (attempting to write " + j + " bytes at offset " + i + " to " + glBuffer.size + " size buffer)"
);
} else {
GlStateManager._glBindBuffer(GlConst.toGl(glBuffer.type()), glBuffer.handle);
if (glBuffer.initialized) {
GlStateManager._glBufferSubData(GlConst.toGl(glBuffer.type()), i, byteBuffer);
} else if (i == 0 && j == glBuffer.size) {
GlStateManager._glBufferData(GlConst.toGl(glBuffer.type()), byteBuffer, GlConst.toGl(glBuffer.usage()));
GlBuffer.MEMORY_POOl.malloc(glBuffer.handle, glBuffer.size);
glBuffer.initialized = true;
this.device.debugLabels().applyLabel(glBuffer);
} else {
GlStateManager._glBufferData(GlConst.toGl(glBuffer.type()), glBuffer.size, GlConst.toGl(glBuffer.usage()));
GlStateManager._glBufferSubData(GlConst.toGl(glBuffer.type()), i, byteBuffer);
GlBuffer.MEMORY_POOl.malloc(glBuffer.handle, glBuffer.size);
glBuffer.initialized = true;
this.device.debugLabels().applyLabel(glBuffer);
}
}
}
}
}
@Override
public GpuBuffer.ReadView readBuffer(GpuBuffer gpuBuffer) {
return this.readBuffer(gpuBuffer, 0, gpuBuffer.size());
}
@Override
public GpuBuffer.ReadView readBuffer(GpuBuffer gpuBuffer, int i, int j) {
if (this.inRenderPass) {
throw new IllegalStateException("Close the existing render pass before performing additional commands");
} else {
GlBuffer glBuffer = (GlBuffer)gpuBuffer;
if (glBuffer.closed) {
throw new IllegalStateException("Buffer already closed");
} else if (!glBuffer.usage().isReadable()) {
throw new IllegalStateException("Buffer is not readable");
} else if (i + j > glBuffer.size) {
throw new IllegalArgumentException(
"Cannot read more data than this buffer can hold (attempting to read " + j + " bytes at offset " + i + " from " + glBuffer.size + " size buffer)"
);
} else {
GlStateManager.clearGlErrors();
GlStateManager._glBindBuffer(GlConst.toGl(glBuffer.type()), glBuffer.handle);
ByteBuffer byteBuffer = GlStateManager._glMapBufferRange(GlConst.toGl(glBuffer.type()), i, j, 1);
if (byteBuffer == null) {
throw new IllegalStateException("Can't read buffer, opengl error " + GlStateManager._getError());
} else {
return new GlBuffer.ReadView(GlConst.toGl(glBuffer.type()), byteBuffer);
}
}
}
}
@Override
public void writeToTexture(GpuTexture gpuTexture, NativeImage nativeImage) {
int i = gpuTexture.getWidth(0);
int j = gpuTexture.getHeight(0);
if (nativeImage.getWidth() != i || nativeImage.getHeight() != j) {
throw new IllegalArgumentException(
"Cannot replace texture of size " + i + "x" + j + " with image of size " + nativeImage.getWidth() + "x" + nativeImage.getHeight()
);
} else if (gpuTexture.isClosed()) {
throw new IllegalStateException("Destination texture is closed");
} else {
this.writeToTexture(gpuTexture, nativeImage, 0, 0, 0, i, j, 0, 0);
}
}
@Override
public void writeToTexture(GpuTexture gpuTexture, NativeImage nativeImage, int i, int j, int k, int l, int m, int n, int o) {
if (this.inRenderPass) {
throw new IllegalStateException("Close the existing render pass before performing additional commands");
} else if (i >= 0 && i < gpuTexture.getMipLevels()) {
if (n + l > nativeImage.getWidth() || o + m > nativeImage.getHeight()) {
throw new IllegalArgumentException(
"Copy source ("
+ nativeImage.getWidth()
+ "x"
+ nativeImage.getHeight()
+ ") is not large enough to read a rectangle of "
+ l
+ "x"
+ m
+ " from "
+ n
+ "x"
+ o
);
} else if (j + l > gpuTexture.getWidth(i) || k + m > gpuTexture.getHeight(i)) {
throw new IllegalArgumentException(
"Dest texture (" + l + "x" + m + ") is not large enough to write a rectangle of " + l + "x" + m + " at " + j + "x" + k + " (at mip level " + i + ")"
);
} else if (gpuTexture.isClosed()) {
throw new IllegalStateException("Destination texture is closed");
} else {
GlStateManager._bindTexture(((GlTexture)gpuTexture).id);
GlStateManager._pixelStore(3314, nativeImage.getWidth());
GlStateManager._pixelStore(3316, n);
GlStateManager._pixelStore(3315, o);
GlStateManager._pixelStore(3317, nativeImage.format().components());
GlStateManager._texSubImage2D(3553, i, j, k, l, m, GlConst.toGl(nativeImage.format()), 5121, nativeImage.getPointer());
}
} else {
throw new IllegalArgumentException("Invalid mipLevel " + i + ", must be >= 0 and < " + gpuTexture.getMipLevels());
}
}
@Override
public void writeToTexture(GpuTexture gpuTexture, IntBuffer intBuffer, NativeImage.Format format, int i, int j, int k, int l, int m) {
if (this.inRenderPass) {
throw new IllegalStateException("Close the existing render pass before performing additional commands");
} else if (i >= 0 && i < gpuTexture.getMipLevels()) {
if (l * m > intBuffer.remaining()) {
throw new IllegalArgumentException(
"Copy would overrun the source buffer (remaining length of " + intBuffer.remaining() + ", but copy is " + l + "x" + m + ")"
);
} else if (j + l > gpuTexture.getWidth(i) || k + m > gpuTexture.getHeight(i)) {
throw new IllegalArgumentException(
"Dest texture ("
+ gpuTexture.getWidth(i)
+ "x"
+ gpuTexture.getHeight(i)
+ ") is not large enough to write a rectangle of "
+ l
+ "x"
+ m
+ " at "
+ j
+ "x"
+ k
);
} else if (gpuTexture.isClosed()) {
throw new IllegalStateException("Destination texture is closed");
} else {
GlStateManager._bindTexture(((GlTexture)gpuTexture).id);
GlStateManager._pixelStore(3314, l);
GlStateManager._pixelStore(3316, 0);
GlStateManager._pixelStore(3315, 0);
GlStateManager._pixelStore(3317, format.components());
GlStateManager._texSubImage2D(3553, i, j, k, l, m, GlConst.toGl(format), 5121, intBuffer);
}
} else {
throw new IllegalArgumentException("Invalid mipLevel, must be >= 0 and < " + gpuTexture.getMipLevels());
}
}
@Override
public void copyTextureToBuffer(GpuTexture gpuTexture, GpuBuffer gpuBuffer, int i, Runnable runnable, int j) {
if (this.inRenderPass) {
throw new IllegalStateException("Close the existing render pass before performing additional commands");
} else {
this.copyTextureToBuffer(gpuTexture, gpuBuffer, i, runnable, j, 0, 0, gpuTexture.getWidth(j), gpuTexture.getHeight(j));
}
}
@Override
public void copyTextureToBuffer(GpuTexture gpuTexture, GpuBuffer gpuBuffer, int i, Runnable runnable, int j, int k, int l, int m, int n) {
if (this.inRenderPass) {
throw new IllegalStateException("Close the existing render pass before performing additional commands");
} else if (j >= 0 && j < gpuTexture.getMipLevels()) {
if (gpuTexture.getWidth(j) * gpuTexture.getHeight(j) * gpuTexture.getFormat().pixelSize() + i > gpuBuffer.size()) {
throw new IllegalArgumentException(
"Buffer of size "
+ gpuBuffer.size()
+ " is not large enough to hold "
+ m
+ "x"
+ n
+ " pixels ("
+ gpuTexture.getFormat().pixelSize()
+ " bytes each) starting from offset "
+ i
);
} else if (gpuBuffer.type() != BufferType.PIXEL_PACK) {
throw new IllegalArgumentException("Buffer of type " + gpuBuffer.type() + " cannot be used to retrieve a texture");
} else if (k + m > gpuTexture.getWidth(j) || l + n > gpuTexture.getHeight(j)) {
throw new IllegalArgumentException(
"Copy source texture ("
+ gpuTexture.getWidth(j)
+ "x"
+ gpuTexture.getHeight(j)
+ ") is not large enough to read a rectangle of "
+ m
+ "x"
+ n
+ " from "
+ k
+ ","
+ l
);
} else if (gpuTexture.isClosed()) {
throw new IllegalStateException("Source texture is closed");
} else if (gpuBuffer.isClosed()) {
throw new IllegalStateException("Destination buffer is closed");
} else {
GlStateManager.clearGlErrors();
this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, ((GlTexture)gpuTexture).glId(), 0, j, 36008);
GlStateManager._glBindBuffer(GlConst.toGl(gpuBuffer.type()), ((GlBuffer)gpuBuffer).handle);
GlStateManager._pixelStore(3330, m);
GlStateManager._readPixels(k, l, m, n, GlConst.toGlExternalId(gpuTexture.getFormat()), GlConst.toGlType(gpuTexture.getFormat()), i);
RenderSystem.queueFencedTask(runnable);
GlStateManager._glFramebufferTexture2D(36008, 36064, 3553, 0, j);
GlStateManager._glBindFramebuffer(36008, 0);
GlStateManager._glBindBuffer(GlConst.toGl(gpuBuffer.type()), 0);
int o = GlStateManager._getError();
if (o != 0) {
throw new IllegalStateException("Couldn't perform copyTobuffer for texture " + gpuTexture.getLabel() + ": GL error " + o);
}
}
} else {
throw new IllegalArgumentException("Invalid mipLevel " + j + ", must be >= 0 and < " + gpuTexture.getMipLevels());
}
}
@Override
public void copyTextureToTexture(GpuTexture gpuTexture, GpuTexture gpuTexture2, int i, int j, int k, int l, int m, int n, int o) {
if (this.inRenderPass) {
throw new IllegalStateException("Close the existing render pass before performing additional commands");
} else if (i >= 0 && i < gpuTexture.getMipLevels() && i < gpuTexture2.getMipLevels()) {
if (j + n > gpuTexture2.getWidth(i) || k + o > gpuTexture2.getHeight(i)) {
throw new IllegalArgumentException(
"Dest texture ("
+ gpuTexture2.getWidth(i)
+ "x"
+ gpuTexture2.getHeight(i)
+ ") is not large enough to write a rectangle of "
+ n
+ "x"
+ o
+ " at "
+ j
+ "x"
+ k
);
} else if (l + n > gpuTexture.getWidth(i) || m + o > gpuTexture.getHeight(i)) {
throw new IllegalArgumentException(
"Source texture ("
+ gpuTexture.getWidth(i)
+ "x"
+ gpuTexture.getHeight(i)
+ ") is not large enough to read a rectangle of "
+ n
+ "x"
+ o
+ " at "
+ l
+ "x"
+ m
);
} else if (gpuTexture.isClosed()) {
throw new IllegalStateException("Source texture is closed");
} else if (gpuTexture2.isClosed()) {
throw new IllegalStateException("Destination texture is closed");
} else {
GlStateManager.clearGlErrors();
GlStateManager._disableScissorTest();
boolean bl = gpuTexture.getFormat().hasDepthAspect();
int p = ((GlTexture)gpuTexture).glId();
int q = ((GlTexture)gpuTexture2).glId();
this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, bl ? 0 : p, bl ? p : 0, 0, 0);
this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, bl ? 0 : q, bl ? q : 0, 0, 0);
this.device.directStateAccess().blitFrameBuffers(this.readFbo, this.drawFbo, l, m, n, o, j, k, n, o, bl ? 256 : 16384, 9728);
int r = GlStateManager._getError();
if (r != 0) {
throw new IllegalStateException(
"Couldn't perform copyToTexture for texture " + gpuTexture.getLabel() + " to " + gpuTexture2.getLabel() + ": GL error " + r
);
}
}
} else {
throw new IllegalArgumentException("Invalid mipLevel " + i + ", must be >= 0 and < " + gpuTexture.getMipLevels() + " and < " + gpuTexture2.getMipLevels());
}
}
@Override
public void presentTexture(GpuTexture gpuTexture) {
if (this.inRenderPass) {
throw new IllegalStateException("Close the existing render pass before performing additional commands");
} else if (!gpuTexture.getFormat().hasColorAspect()) {
throw new IllegalStateException("Cannot present a non-color texture!");
} else {
GlStateManager._disableScissorTest();
GlStateManager._viewport(0, 0, gpuTexture.getWidth(0), gpuTexture.getHeight(0));
GlStateManager._depthMask(true);
GlStateManager._colorMask(true, true, true, true);
this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, ((GlTexture)gpuTexture).glId(), 0, 0, 0);
this.device
.directStateAccess()
.blitFrameBuffers(
this.drawFbo, 0, 0, 0, gpuTexture.getWidth(0), gpuTexture.getHeight(0), 0, 0, gpuTexture.getWidth(0), gpuTexture.getHeight(0), 16384, 9728
);
}
}
protected void executeDrawMultiple(
GlRenderPass renderPass, Collection<RenderPass.Draw> draws, @Nullable GpuBuffer buffer, @Nullable VertexFormat.IndexType indexType
) {
if (this.trySetup(renderPass)) {
if (indexType == null) {
indexType = VertexFormat.IndexType.SHORT;
}
for (RenderPass.Draw draw : draws) {
VertexFormat.IndexType indexType2 = draw.indexType() == null ? indexType : draw.indexType();
renderPass.setIndexBuffer(draw.indexBuffer() == null ? buffer : draw.indexBuffer(), indexType2);
renderPass.setVertexBuffer(draw.slot(), draw.vertexBuffer());
if (GlRenderPass.VALIDATION) {
if (renderPass.indexBuffer == null) {
throw new IllegalStateException("Missing index buffer");
}
if (renderPass.indexBuffer.isClosed()) {
throw new IllegalStateException("Index buffer has been closed!");
}
if (renderPass.vertexBuffers[0] == null) {
throw new IllegalStateException("Missing vertex buffer at slot 0");
}
if (renderPass.vertexBuffers[0].isClosed()) {
throw new IllegalStateException("Vertex buffer at slot 0 has been closed!");
}
}
Consumer<RenderPass.UniformUploader> consumer = draw.uniformUploaderConsumer();
if (consumer != null) {
consumer.accept((RenderPass.UniformUploader)(string, fs) -> {
Uniform uniform = renderPass.pipeline.program().getUniform(string);
if (uniform != null) {
uniform.set(fs);
uniform.upload();
}
});
}
this.drawFromBuffers(renderPass, draw.firstIndex(), draw.indexCount(), indexType2, renderPass.pipeline);
}
}
}
protected void executeDraw(GlRenderPass renderPass, int firstIndex, int indexCount, @Nullable VertexFormat.IndexType indexType) {
if (this.trySetup(renderPass)) {
if (GlRenderPass.VALIDATION) {
if (indexType != null) {
if (renderPass.indexBuffer == null) {
throw new IllegalStateException("Missing index buffer");
}
if (renderPass.indexBuffer.isClosed()) {
throw new IllegalStateException("Index buffer has been closed!");
}
}
if (renderPass.vertexBuffers[0] == null) {
throw new IllegalStateException("Missing vertex buffer at slot 0");
}
if (renderPass.vertexBuffers[0].isClosed()) {
throw new IllegalStateException("Vertex buffer at slot 0 has been closed!");
}
}
this.drawFromBuffers(renderPass, firstIndex, indexCount, indexType, renderPass.pipeline);
}
}
private void drawFromBuffers(GlRenderPass renderPass, int firstIndex, int indexCount, @Nullable VertexFormat.IndexType indexType, GlRenderPipeline pipeline) {
this.device.vertexArrayCache().bindVertexArray(pipeline.info().getVertexFormat(), (GlBuffer)renderPass.vertexBuffers[0]);
if (indexType != null) {
GlStateManager._glBindBuffer(34963, ((GlBuffer)renderPass.indexBuffer).handle);
GlStateManager._drawElements(GlConst.toGl(pipeline.info().getVertexFormatMode()), indexCount, GlConst.toGl(indexType), (long)firstIndex * indexType.bytes);
} else {
GlStateManager._drawArrays(GlConst.toGl(pipeline.info().getVertexFormatMode()), firstIndex, indexCount);
}
}
private boolean trySetup(GlRenderPass renderPass) {
if (GlRenderPass.VALIDATION) {
if (renderPass.pipeline == null) {
throw new IllegalStateException("Can't draw without a render pipeline");
}
if (renderPass.pipeline.program() == GlProgram.INVALID_PROGRAM) {
throw new IllegalStateException("Pipeline contains invalid shader program");
}
for (RenderPipeline.UniformDescription uniformDescription : renderPass.pipeline.info().getUniforms()) {
Object object = renderPass.uniforms.get(uniformDescription.name());
if (object == null && !GlProgram.BUILT_IN_UNIFORMS.contains(uniformDescription.name())) {
throw new IllegalStateException("Missing uniform " + uniformDescription.name() + " (should be " + uniformDescription.type() + ")");
}
}
for (String string : renderPass.pipeline.program().getSamplers()) {
if (!renderPass.samplers.containsKey(string)) {
throw new IllegalStateException("Missing sampler " + string);
}
if (((GpuTexture)renderPass.samplers.get(string)).isClosed()) {
throw new IllegalStateException("Sampler " + string + " has been closed!");
}
}
if (renderPass.pipeline.info().wantsDepthTexture() && !renderPass.hasDepthTexture()) {
LOGGER.warn("Render pipeline {} wants a depth texture but none was provided - this is probably a bug", renderPass.pipeline.info().getLocation());
}
} else if (renderPass.pipeline == null || renderPass.pipeline.program() == GlProgram.INVALID_PROGRAM) {
return false;
}
RenderPipeline renderPipeline = renderPass.pipeline.info();
GlProgram glProgram = renderPass.pipeline.program();
for (Uniform uniform : glProgram.getUniforms()) {
if (renderPass.dirtyUniforms.contains(uniform.getName())) {
Object object2 = renderPass.uniforms.get(uniform.getName());
if (object2 instanceof int[]) {
glProgram.safeGetUniform(uniform.getName()).set((int[])object2);
} else if (object2 instanceof float[]) {
glProgram.safeGetUniform(uniform.getName()).set((float[])object2);
} else if (object2 != null) {
throw new IllegalStateException("Unknown uniform type - expected " + uniform.getType() + ", found " + object2);
}
}
}
renderPass.dirtyUniforms.clear();
this.applyPipelineState(renderPipeline);
boolean bl = this.lastProgram != glProgram;
if (bl) {
GlStateManager._glUseProgram(glProgram.getProgramId());
this.lastProgram = glProgram;
}
IntList intList = glProgram.getSamplerLocations();
for (int i = 0; i < glProgram.getSamplers().size(); i++) {
String string2 = (String)glProgram.getSamplers().get(i);
GlTexture glTexture = (GlTexture)renderPass.samplers.get(string2);
if (glTexture != null) {
if (bl || renderPass.dirtySamplers.contains(string2)) {
int j = intList.getInt(i);
Uniform.uploadInteger(j, i);
GlStateManager._activeTexture(33984 + i);
}
GlStateManager._bindTexture(glTexture.glId());
glTexture.flushModeChanges();
}
}
Window window = Minecraft.getInstance() == null ? null : Minecraft.getInstance().getWindow();
glProgram.setDefaultUniforms(
renderPipeline.getVertexFormatMode(),
RenderSystem.getModelViewMatrix(),
RenderSystem.getProjectionMatrix(),
window == null ? 0.0F : window.getWidth(),
window == null ? 0.0F : window.getHeight()
);
for (Uniform uniform2 : glProgram.getUniforms()) {
uniform2.upload();
}
if (renderPass.scissorState.isEnabled()) {
GlStateManager._enableScissorTest();
GlStateManager._scissorBox(
renderPass.scissorState.getX(), renderPass.scissorState.getY(), renderPass.scissorState.getWidth(), renderPass.scissorState.getHeight()
);
} else {
GlStateManager._disableScissorTest();
}
return true;
}
private void applyPipelineState(RenderPipeline pipeline) {
if (this.lastPipeline != pipeline) {
this.lastPipeline = pipeline;
if (pipeline.getDepthTestFunction() != DepthTestFunction.NO_DEPTH_TEST) {
GlStateManager._enableDepthTest();
GlStateManager._depthFunc(GlConst.toGl(pipeline.getDepthTestFunction()));
} else {
GlStateManager._disableDepthTest();
}
if (pipeline.isCull()) {
GlStateManager._enableCull();
} else {
GlStateManager._disableCull();
}
if (pipeline.getBlendFunction().isPresent()) {
GlStateManager._enableBlend();
BlendFunction blendFunction = (BlendFunction)pipeline.getBlendFunction().get();
GlStateManager._blendFuncSeparate(
GlConst.toGl(blendFunction.sourceColor()),
GlConst.toGl(blendFunction.destColor()),
GlConst.toGl(blendFunction.sourceAlpha()),
GlConst.toGl(blendFunction.destAlpha())
);
} else {
GlStateManager._disableBlend();
}
GlStateManager._polygonMode(1032, GlConst.toGl(pipeline.getPolygonMode()));
GlStateManager._depthMask(pipeline.isWriteDepth());
GlStateManager._colorMask(pipeline.isWriteColor(), pipeline.isWriteColor(), pipeline.isWriteColor(), pipeline.isWriteAlpha());
if (pipeline.getDepthBiasConstant() == 0.0F && pipeline.getDepthBiasScaleFactor() == 0.0F) {
GlStateManager._disablePolygonOffset();
} else {
GlStateManager._polygonOffset(pipeline.getDepthBiasScaleFactor(), pipeline.getDepthBiasConstant());
GlStateManager._enablePolygonOffset();
}
switch (pipeline.getColorLogic()) {
case NONE:
GlStateManager._disableColorLogicOp();
break;
case OR_REVERSE:
GlStateManager._enableColorLogicOp();
GlStateManager._logicOp(5387);
}
}
}
public void finishRenderPass() {
this.inRenderPass = false;
GlStateManager._glBindFramebuffer(36160, 0);
}
protected GlDevice getDevice() {
return this.device;
}
}