883 lines
47 KiB
Java
883 lines
47 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.mojang.logging.LogUtils
|
|
* org.jspecify.annotations.Nullable
|
|
* org.lwjgl.opengl.GL11
|
|
* org.lwjgl.opengl.GL11C
|
|
* org.lwjgl.opengl.GL31
|
|
* org.lwjgl.opengl.GL32
|
|
* org.lwjgl.opengl.GL32C
|
|
* org.lwjgl.opengl.GL33C
|
|
* org.slf4j.Logger
|
|
*/
|
|
package com.mojang.blaze3d.opengl;
|
|
|
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
|
import com.mojang.blaze3d.buffers.GpuFence;
|
|
import com.mojang.blaze3d.opengl.GlBuffer;
|
|
import com.mojang.blaze3d.opengl.GlConst;
|
|
import com.mojang.blaze3d.opengl.GlDevice;
|
|
import com.mojang.blaze3d.opengl.GlFence;
|
|
import com.mojang.blaze3d.opengl.GlProgram;
|
|
import com.mojang.blaze3d.opengl.GlRenderPass;
|
|
import com.mojang.blaze3d.opengl.GlRenderPipeline;
|
|
import com.mojang.blaze3d.opengl.GlStateManager;
|
|
import com.mojang.blaze3d.opengl.GlTexture;
|
|
import com.mojang.blaze3d.opengl.GlTextureView;
|
|
import com.mojang.blaze3d.opengl.GlTimerQuery;
|
|
import com.mojang.blaze3d.opengl.Uniform;
|
|
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.shaders.UniformType;
|
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
|
import com.mojang.blaze3d.systems.GpuQuery;
|
|
import com.mojang.blaze3d.systems.RenderPass;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import com.mojang.blaze3d.textures.GpuTexture;
|
|
import com.mojang.blaze3d.textures.GpuTextureView;
|
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
|
import com.mojang.logging.LogUtils;
|
|
import java.lang.runtime.SwitchBootstraps;
|
|
import java.nio.ByteBuffer;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.OptionalDouble;
|
|
import java.util.OptionalInt;
|
|
import java.util.function.BiConsumer;
|
|
import java.util.function.Supplier;
|
|
import net.minecraft.util.ARGB;
|
|
import org.jspecify.annotations.Nullable;
|
|
import org.lwjgl.opengl.GL11;
|
|
import org.lwjgl.opengl.GL11C;
|
|
import org.lwjgl.opengl.GL31;
|
|
import org.lwjgl.opengl.GL32;
|
|
import org.lwjgl.opengl.GL32C;
|
|
import org.lwjgl.opengl.GL33C;
|
|
import org.slf4j.Logger;
|
|
|
|
public class GlCommandEncoder
|
|
implements CommandEncoder {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private final GlDevice device;
|
|
private final int readFbo;
|
|
private final int drawFbo;
|
|
private @Nullable RenderPipeline lastPipeline;
|
|
private boolean inRenderPass;
|
|
private @Nullable GlProgram lastProgram;
|
|
private @Nullable GlTimerQuery activeTimerQuery;
|
|
|
|
protected GlCommandEncoder(GlDevice device) {
|
|
this.device = device;
|
|
this.readFbo = device.directStateAccess().createFrameBufferObject();
|
|
this.drawFbo = device.directStateAccess().createFrameBufferObject();
|
|
}
|
|
|
|
@Override
|
|
public RenderPass createRenderPass(Supplier<String> label, GpuTextureView colorTexture, OptionalInt clearColor) {
|
|
return this.createRenderPass(label, colorTexture, clearColor, null, OptionalDouble.empty());
|
|
}
|
|
|
|
@Override
|
|
public RenderPass createRenderPass(Supplier<String> label, GpuTextureView colorTexture, OptionalInt clearColor, @Nullable GpuTextureView depthTexture, OptionalDouble clearDepth) {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before creating a new one!");
|
|
}
|
|
if (clearDepth.isPresent() && depthTexture == null) {
|
|
LOGGER.warn("Depth clear value was provided but no depth texture is being used");
|
|
}
|
|
if (colorTexture.isClosed()) {
|
|
throw new IllegalStateException("Color texture is closed");
|
|
}
|
|
if ((colorTexture.texture().usage() & 8) == 0) {
|
|
throw new IllegalStateException("Color texture must have USAGE_RENDER_ATTACHMENT");
|
|
}
|
|
if (colorTexture.texture().getDepthOrLayers() > 1) {
|
|
throw new UnsupportedOperationException("Textures with multiple depths or layers are not yet supported as an attachment");
|
|
}
|
|
if (depthTexture != null) {
|
|
if (depthTexture.isClosed()) {
|
|
throw new IllegalStateException("Depth texture is closed");
|
|
}
|
|
if ((depthTexture.texture().usage() & 8) == 0) {
|
|
throw new IllegalStateException("Depth texture must have USAGE_RENDER_ATTACHMENT");
|
|
}
|
|
if (depthTexture.texture().getDepthOrLayers() > 1) {
|
|
throw new UnsupportedOperationException("Textures with multiple depths or layers are not yet supported as an attachment");
|
|
}
|
|
}
|
|
this.inRenderPass = true;
|
|
this.device.debugLabels().pushDebugGroup(label);
|
|
int fbo = ((GlTextureView)colorTexture).getFbo(this.device.directStateAccess(), depthTexture == null ? null : depthTexture.texture());
|
|
GlStateManager._glBindFramebuffer(36160, fbo);
|
|
int clearMask = 0;
|
|
if (clearColor.isPresent()) {
|
|
int argb = clearColor.getAsInt();
|
|
GL11.glClearColor((float)ARGB.redFloat(argb), (float)ARGB.greenFloat(argb), (float)ARGB.blueFloat(argb), (float)ARGB.alphaFloat(argb));
|
|
clearMask |= 0x4000;
|
|
}
|
|
if (depthTexture != null && clearDepth.isPresent()) {
|
|
GL11.glClearDepth((double)clearDepth.getAsDouble());
|
|
clearMask |= 0x100;
|
|
}
|
|
if (clearMask != 0) {
|
|
GlStateManager._disableScissorTest();
|
|
GlStateManager._depthMask(true);
|
|
GlStateManager._colorMask(true, true, true, true);
|
|
GlStateManager._clear(clearMask);
|
|
}
|
|
GlStateManager._viewport(0, 0, colorTexture.getWidth(0), colorTexture.getHeight(0));
|
|
this.lastPipeline = null;
|
|
return new GlRenderPass(this, depthTexture != null);
|
|
}
|
|
|
|
@Override
|
|
public void clearColorTexture(GpuTexture colorTexture, int clearColor) {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before creating a new one!");
|
|
}
|
|
this.verifyColorTexture(colorTexture);
|
|
this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, ((GlTexture)colorTexture).id, 0, 0, 36160);
|
|
GL11.glClearColor((float)ARGB.redFloat(clearColor), (float)ARGB.greenFloat(clearColor), (float)ARGB.blueFloat(clearColor), (float)ARGB.alphaFloat(clearColor));
|
|
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 colorTexture, int clearColor, GpuTexture depthTexture, double clearDepth) {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before creating a new one!");
|
|
}
|
|
this.verifyColorTexture(colorTexture);
|
|
this.verifyDepthTexture(depthTexture);
|
|
int fbo = ((GlTexture)colorTexture).getFbo(this.device.directStateAccess(), depthTexture);
|
|
GlStateManager._glBindFramebuffer(36160, fbo);
|
|
GlStateManager._disableScissorTest();
|
|
GL11.glClearDepth((double)clearDepth);
|
|
GL11.glClearColor((float)ARGB.redFloat(clearColor), (float)ARGB.greenFloat(clearColor), (float)ARGB.blueFloat(clearColor), (float)ARGB.alphaFloat(clearColor));
|
|
GlStateManager._depthMask(true);
|
|
GlStateManager._colorMask(true, true, true, true);
|
|
GlStateManager._clear(16640);
|
|
GlStateManager._glBindFramebuffer(36160, 0);
|
|
}
|
|
|
|
@Override
|
|
public void clearColorAndDepthTextures(GpuTexture colorTexture, int clearColor, GpuTexture depthTexture, double clearDepth, int regionX, int regionY, int regionWidth, int regionHeight) {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before creating a new one!");
|
|
}
|
|
this.verifyColorTexture(colorTexture);
|
|
this.verifyDepthTexture(depthTexture);
|
|
this.verifyRegion(colorTexture, regionX, regionY, regionWidth, regionHeight);
|
|
int fbo = ((GlTexture)colorTexture).getFbo(this.device.directStateAccess(), depthTexture);
|
|
GlStateManager._glBindFramebuffer(36160, fbo);
|
|
GlStateManager._scissorBox(regionX, regionY, regionWidth, regionHeight);
|
|
GlStateManager._enableScissorTest();
|
|
GL11.glClearDepth((double)clearDepth);
|
|
GL11.glClearColor((float)ARGB.redFloat(clearColor), (float)ARGB.greenFloat(clearColor), (float)ARGB.blueFloat(clearColor), (float)ARGB.alphaFloat(clearColor));
|
|
GlStateManager._depthMask(true);
|
|
GlStateManager._colorMask(true, true, true, true);
|
|
GlStateManager._clear(16640);
|
|
GlStateManager._glBindFramebuffer(36160, 0);
|
|
}
|
|
|
|
private void verifyRegion(GpuTexture colorTexture, int regionX, int regionY, int regionWidth, int regionHeight) {
|
|
if (regionX < 0 || regionX >= colorTexture.getWidth(0)) {
|
|
throw new IllegalArgumentException("regionX should not be outside of the texture");
|
|
}
|
|
if (regionY < 0 || regionY >= colorTexture.getHeight(0)) {
|
|
throw new IllegalArgumentException("regionY should not be outside of the texture");
|
|
}
|
|
if (regionWidth <= 0) {
|
|
throw new IllegalArgumentException("regionWidth should be greater than 0");
|
|
}
|
|
if (regionX + regionWidth > colorTexture.getWidth(0)) {
|
|
throw new IllegalArgumentException("regionWidth + regionX should be less than the texture width");
|
|
}
|
|
if (regionHeight <= 0) {
|
|
throw new IllegalArgumentException("regionHeight should be greater than 0");
|
|
}
|
|
if (regionY + regionHeight > colorTexture.getHeight(0)) {
|
|
throw new IllegalArgumentException("regionWidth + regionX should be less than the texture height");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void clearDepthTexture(GpuTexture depthTexture, double clearDepth) {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before creating a new one!");
|
|
}
|
|
this.verifyDepthTexture(depthTexture);
|
|
this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)depthTexture).id, 0, 36160);
|
|
GL11.glDrawBuffer((int)0);
|
|
GL11.glClearDepth((double)clearDepth);
|
|
GlStateManager._depthMask(true);
|
|
GlStateManager._disableScissorTest();
|
|
GlStateManager._clear(256);
|
|
GL11.glDrawBuffer((int)36064);
|
|
GlStateManager._glFramebufferTexture2D(36160, 36096, 3553, 0, 0);
|
|
GlStateManager._glBindFramebuffer(36160, 0);
|
|
}
|
|
|
|
private void verifyColorTexture(GpuTexture colorTexture) {
|
|
if (!colorTexture.getFormat().hasColorAspect()) {
|
|
throw new IllegalStateException("Trying to clear a non-color texture as color");
|
|
}
|
|
if (colorTexture.isClosed()) {
|
|
throw new IllegalStateException("Color texture is closed");
|
|
}
|
|
if ((colorTexture.usage() & 8) == 0) {
|
|
throw new IllegalStateException("Color texture must have USAGE_RENDER_ATTACHMENT");
|
|
}
|
|
if (colorTexture.getDepthOrLayers() > 1) {
|
|
throw new UnsupportedOperationException("Clearing a texture with multiple layers or depths is not yet supported");
|
|
}
|
|
}
|
|
|
|
private void verifyDepthTexture(GpuTexture depthTexture) {
|
|
if (!depthTexture.getFormat().hasDepthAspect()) {
|
|
throw new IllegalStateException("Trying to clear a non-depth texture as depth");
|
|
}
|
|
if (depthTexture.isClosed()) {
|
|
throw new IllegalStateException("Depth texture is closed");
|
|
}
|
|
if ((depthTexture.usage() & 8) == 0) {
|
|
throw new IllegalStateException("Depth texture must have USAGE_RENDER_ATTACHMENT");
|
|
}
|
|
if (depthTexture.getDepthOrLayers() > 1) {
|
|
throw new UnsupportedOperationException("Clearing a texture with multiple layers or depths is not yet supported");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void writeToBuffer(GpuBufferSlice slice, ByteBuffer data) {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before performing additional commands");
|
|
}
|
|
GlBuffer buffer = (GlBuffer)slice.buffer();
|
|
if (buffer.closed) {
|
|
throw new IllegalStateException("Buffer already closed");
|
|
}
|
|
if ((buffer.usage() & 8) == 0) {
|
|
throw new IllegalStateException("Buffer needs USAGE_COPY_DST to be a destination for a copy");
|
|
}
|
|
int length = data.remaining();
|
|
if (length > slice.length()) {
|
|
throw new IllegalArgumentException("Cannot write more data than the slice allows (attempting to write " + length + " bytes into a slice of length " + slice.length() + ")");
|
|
}
|
|
if (slice.length() + slice.offset() > buffer.size()) {
|
|
throw new IllegalArgumentException("Cannot write more data than this buffer can hold (attempting to write " + length + " bytes at offset " + slice.offset() + " to " + buffer.size() + " size buffer)");
|
|
}
|
|
this.device.directStateAccess().bufferSubData(buffer.handle, slice.offset(), data, buffer.usage());
|
|
}
|
|
|
|
@Override
|
|
public GpuBuffer.MappedView mapBuffer(GpuBuffer buffer, boolean read, boolean write) {
|
|
return this.mapBuffer(buffer.slice(), read, write);
|
|
}
|
|
|
|
@Override
|
|
public GpuBuffer.MappedView mapBuffer(GpuBufferSlice slice, boolean read, boolean write) {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before performing additional commands");
|
|
}
|
|
GlBuffer buffer = (GlBuffer)slice.buffer();
|
|
if (buffer.closed) {
|
|
throw new IllegalStateException("Buffer already closed");
|
|
}
|
|
if (!read && !write) {
|
|
throw new IllegalArgumentException("At least read or write must be true");
|
|
}
|
|
if (read && (buffer.usage() & 1) == 0) {
|
|
throw new IllegalStateException("Buffer is not readable");
|
|
}
|
|
if (write && (buffer.usage() & 2) == 0) {
|
|
throw new IllegalStateException("Buffer is not writable");
|
|
}
|
|
if (slice.offset() + slice.length() > buffer.size()) {
|
|
throw new IllegalArgumentException("Cannot map more data than this buffer can hold (attempting to map " + slice.length() + " bytes at offset " + slice.offset() + " from " + buffer.size() + " size buffer)");
|
|
}
|
|
int flags = 0;
|
|
if (read) {
|
|
flags |= 1;
|
|
}
|
|
if (write) {
|
|
flags |= 0x22;
|
|
}
|
|
return this.device.getBufferStorage().mapBuffer(this.device.directStateAccess(), buffer, slice.offset(), slice.length(), flags);
|
|
}
|
|
|
|
@Override
|
|
public void copyToBuffer(GpuBufferSlice source, GpuBufferSlice target) {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before performing additional commands");
|
|
}
|
|
GlBuffer sourceBuffer = (GlBuffer)source.buffer();
|
|
if (sourceBuffer.closed) {
|
|
throw new IllegalStateException("Source buffer already closed");
|
|
}
|
|
if ((sourceBuffer.usage() & 0x10) == 0) {
|
|
throw new IllegalStateException("Source buffer needs USAGE_COPY_SRC to be a source for a copy");
|
|
}
|
|
GlBuffer targetBuffer = (GlBuffer)target.buffer();
|
|
if (targetBuffer.closed) {
|
|
throw new IllegalStateException("Target buffer already closed");
|
|
}
|
|
if ((targetBuffer.usage() & 8) == 0) {
|
|
throw new IllegalStateException("Target buffer needs USAGE_COPY_DST to be a destination for a copy");
|
|
}
|
|
if (source.length() != target.length()) {
|
|
throw new IllegalArgumentException("Cannot copy from slice of size " + source.length() + " to slice of size " + target.length() + ", they must be equal");
|
|
}
|
|
if (source.offset() + source.length() > sourceBuffer.size()) {
|
|
throw new IllegalArgumentException("Cannot copy more data than the source buffer holds (attempting to copy " + source.length() + " bytes at offset " + source.offset() + " from " + sourceBuffer.size() + " size buffer)");
|
|
}
|
|
if (target.offset() + target.length() > targetBuffer.size()) {
|
|
throw new IllegalArgumentException("Cannot copy more data than the target buffer can hold (attempting to copy " + target.length() + " bytes at offset " + target.offset() + " to " + targetBuffer.size() + " size buffer)");
|
|
}
|
|
this.device.directStateAccess().copyBufferSubData(sourceBuffer.handle, targetBuffer.handle, source.offset(), target.offset(), source.length());
|
|
}
|
|
|
|
@Override
|
|
public void writeToTexture(GpuTexture destination, NativeImage source) {
|
|
int width = destination.getWidth(0);
|
|
int height = destination.getHeight(0);
|
|
if (source.getWidth() != width || source.getHeight() != height) {
|
|
throw new IllegalArgumentException("Cannot replace texture of size " + width + "x" + height + " with image of size " + source.getWidth() + "x" + source.getHeight());
|
|
}
|
|
if (destination.isClosed()) {
|
|
throw new IllegalStateException("Destination texture is closed");
|
|
}
|
|
if ((destination.usage() & 1) == 0) {
|
|
throw new IllegalStateException("Color texture must have USAGE_COPY_DST to be a destination for a write");
|
|
}
|
|
this.writeToTexture(destination, source, 0, 0, 0, 0, width, height, 0, 0);
|
|
}
|
|
|
|
@Override
|
|
public void writeToTexture(GpuTexture destination, NativeImage source, int mipLevel, int depthOrLayer, int destX, int destY, int width, int height, int sourceX, int sourceY) {
|
|
int target;
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before performing additional commands");
|
|
}
|
|
if (mipLevel < 0 || mipLevel >= destination.getMipLevels()) {
|
|
throw new IllegalArgumentException("Invalid mipLevel " + mipLevel + ", must be >= 0 and < " + destination.getMipLevels());
|
|
}
|
|
if (sourceX + width > source.getWidth() || sourceY + height > source.getHeight()) {
|
|
throw new IllegalArgumentException("Copy source (" + source.getWidth() + "x" + source.getHeight() + ") is not large enough to read a rectangle of " + width + "x" + height + " from " + sourceX + "x" + sourceY);
|
|
}
|
|
if (destX + width > destination.getWidth(mipLevel) || destY + height > destination.getHeight(mipLevel)) {
|
|
throw new IllegalArgumentException("Dest texture (" + width + "x" + height + ") is not large enough to write a rectangle of " + width + "x" + height + " at " + destX + "x" + destY + " (at mip level " + mipLevel + ")");
|
|
}
|
|
if (destination.isClosed()) {
|
|
throw new IllegalStateException("Destination texture is closed");
|
|
}
|
|
if ((destination.usage() & 1) == 0) {
|
|
throw new IllegalStateException("Color texture must have USAGE_COPY_DST to be a destination for a write");
|
|
}
|
|
if (depthOrLayer >= destination.getDepthOrLayers()) {
|
|
throw new UnsupportedOperationException("Depth or layer is out of range, must be >= 0 and < " + destination.getDepthOrLayers());
|
|
}
|
|
if ((destination.usage() & 0x10) != 0) {
|
|
target = GlConst.CUBEMAP_TARGETS[depthOrLayer % 6];
|
|
GL11.glBindTexture((int)34067, (int)((GlTexture)destination).id);
|
|
} else {
|
|
target = 3553;
|
|
GlStateManager._bindTexture(((GlTexture)destination).id);
|
|
}
|
|
GlStateManager._pixelStore(3314, source.getWidth());
|
|
GlStateManager._pixelStore(3316, sourceX);
|
|
GlStateManager._pixelStore(3315, sourceY);
|
|
GlStateManager._pixelStore(3317, source.format().components());
|
|
GlStateManager._texSubImage2D(target, mipLevel, destX, destY, width, height, GlConst.toGl(source.format()), 5121, source.getPointer());
|
|
}
|
|
|
|
@Override
|
|
public void writeToTexture(GpuTexture destination, ByteBuffer source, NativeImage.Format format, int mipLevel, int depthOrLayer, int destX, int destY, int width, int height) {
|
|
int target;
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before performing additional commands");
|
|
}
|
|
if (mipLevel < 0 || mipLevel >= destination.getMipLevels()) {
|
|
throw new IllegalArgumentException("Invalid mipLevel, must be >= 0 and < " + destination.getMipLevels());
|
|
}
|
|
if (width * height * format.components() > source.remaining()) {
|
|
throw new IllegalArgumentException("Copy would overrun the source buffer (remaining length of " + source.remaining() + ", but copy is " + width + "x" + height + " of format " + String.valueOf((Object)format) + ")");
|
|
}
|
|
if (destX + width > destination.getWidth(mipLevel) || destY + height > destination.getHeight(mipLevel)) {
|
|
throw new IllegalArgumentException("Dest texture (" + destination.getWidth(mipLevel) + "x" + destination.getHeight(mipLevel) + ") is not large enough to write a rectangle of " + width + "x" + height + " at " + destX + "x" + destY);
|
|
}
|
|
if (destination.isClosed()) {
|
|
throw new IllegalStateException("Destination texture is closed");
|
|
}
|
|
if ((destination.usage() & 1) == 0) {
|
|
throw new IllegalStateException("Color texture must have USAGE_COPY_DST to be a destination for a write");
|
|
}
|
|
if (depthOrLayer >= destination.getDepthOrLayers()) {
|
|
throw new UnsupportedOperationException("Depth or layer is out of range, must be >= 0 and < " + destination.getDepthOrLayers());
|
|
}
|
|
if ((destination.usage() & 0x10) != 0) {
|
|
target = GlConst.CUBEMAP_TARGETS[depthOrLayer % 6];
|
|
GL11.glBindTexture((int)34067, (int)((GlTexture)destination).id);
|
|
} else {
|
|
target = 3553;
|
|
GlStateManager._bindTexture(((GlTexture)destination).id);
|
|
}
|
|
GlStateManager._pixelStore(3314, width);
|
|
GlStateManager._pixelStore(3316, 0);
|
|
GlStateManager._pixelStore(3315, 0);
|
|
GlStateManager._pixelStore(3317, format.components());
|
|
GlStateManager._texSubImage2D(target, mipLevel, destX, destY, width, height, GlConst.toGl(format), 5121, source);
|
|
}
|
|
|
|
@Override
|
|
public void copyTextureToBuffer(GpuTexture source, GpuBuffer destination, int offset, Runnable callback, int mipLevel) {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before performing additional commands");
|
|
}
|
|
this.copyTextureToBuffer(source, destination, offset, callback, mipLevel, 0, 0, source.getWidth(mipLevel), source.getHeight(mipLevel));
|
|
}
|
|
|
|
@Override
|
|
public void copyTextureToBuffer(GpuTexture source, GpuBuffer destination, int offset, Runnable callback, int mipLevel, int x, int y, int width, int height) {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before performing additional commands");
|
|
}
|
|
if (mipLevel < 0 || mipLevel >= source.getMipLevels()) {
|
|
throw new IllegalArgumentException("Invalid mipLevel " + mipLevel + ", must be >= 0 and < " + source.getMipLevels());
|
|
}
|
|
if (source.getWidth(mipLevel) * source.getHeight(mipLevel) * source.getFormat().pixelSize() + offset > destination.size()) {
|
|
throw new IllegalArgumentException("Buffer of size " + destination.size() + " is not large enough to hold " + width + "x" + height + " pixels (" + source.getFormat().pixelSize() + " bytes each) starting from offset " + offset);
|
|
}
|
|
if ((source.usage() & 2) == 0) {
|
|
throw new IllegalArgumentException("Texture needs USAGE_COPY_SRC to be a source for a copy");
|
|
}
|
|
if ((destination.usage() & 8) == 0) {
|
|
throw new IllegalArgumentException("Buffer needs USAGE_COPY_DST to be a destination for a copy");
|
|
}
|
|
if (x + width > source.getWidth(mipLevel) || y + height > source.getHeight(mipLevel)) {
|
|
throw new IllegalArgumentException("Copy source texture (" + source.getWidth(mipLevel) + "x" + source.getHeight(mipLevel) + ") is not large enough to read a rectangle of " + width + "x" + height + " from " + x + "," + y);
|
|
}
|
|
if (source.isClosed()) {
|
|
throw new IllegalStateException("Source texture is closed");
|
|
}
|
|
if (destination.isClosed()) {
|
|
throw new IllegalStateException("Destination buffer is closed");
|
|
}
|
|
if (source.getDepthOrLayers() > 1) {
|
|
throw new UnsupportedOperationException("Textures with multiple depths or layers are not yet supported for copying");
|
|
}
|
|
GlStateManager.clearGlErrors();
|
|
this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, ((GlTexture)source).glId(), 0, mipLevel, 36008);
|
|
GlStateManager._glBindBuffer(35051, ((GlBuffer)destination).handle);
|
|
GlStateManager._pixelStore(3330, width);
|
|
GlStateManager._readPixels(x, y, width, height, GlConst.toGlExternalId(source.getFormat()), GlConst.toGlType(source.getFormat()), offset);
|
|
RenderSystem.queueFencedTask(callback);
|
|
GlStateManager._glFramebufferTexture2D(36008, 36064, 3553, 0, mipLevel);
|
|
GlStateManager._glBindFramebuffer(36008, 0);
|
|
GlStateManager._glBindBuffer(35051, 0);
|
|
int error = GlStateManager._getError();
|
|
if (error != 0) {
|
|
throw new IllegalStateException("Couldn't perform copyTobuffer for texture " + source.getLabel() + ": GL error " + error);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void copyTextureToTexture(GpuTexture source, GpuTexture destination, int mipLevel, int destX, int destY, int sourceX, int sourceY, int width, int height) {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before performing additional commands");
|
|
}
|
|
if (mipLevel < 0 || mipLevel >= source.getMipLevels() || mipLevel >= destination.getMipLevels()) {
|
|
throw new IllegalArgumentException("Invalid mipLevel " + mipLevel + ", must be >= 0 and < " + source.getMipLevels() + " and < " + destination.getMipLevels());
|
|
}
|
|
if (destX + width > destination.getWidth(mipLevel) || destY + height > destination.getHeight(mipLevel)) {
|
|
throw new IllegalArgumentException("Dest texture (" + destination.getWidth(mipLevel) + "x" + destination.getHeight(mipLevel) + ") is not large enough to write a rectangle of " + width + "x" + height + " at " + destX + "x" + destY);
|
|
}
|
|
if (sourceX + width > source.getWidth(mipLevel) || sourceY + height > source.getHeight(mipLevel)) {
|
|
throw new IllegalArgumentException("Source texture (" + source.getWidth(mipLevel) + "x" + source.getHeight(mipLevel) + ") is not large enough to read a rectangle of " + width + "x" + height + " at " + sourceX + "x" + sourceY);
|
|
}
|
|
if (source.isClosed()) {
|
|
throw new IllegalStateException("Source texture is closed");
|
|
}
|
|
if (destination.isClosed()) {
|
|
throw new IllegalStateException("Destination texture is closed");
|
|
}
|
|
if ((source.usage() & 2) == 0) {
|
|
throw new IllegalArgumentException("Texture needs USAGE_COPY_SRC to be a source for a copy");
|
|
}
|
|
if ((destination.usage() & 1) == 0) {
|
|
throw new IllegalArgumentException("Texture needs USAGE_COPY_DST to be a destination for a copy");
|
|
}
|
|
if (source.getDepthOrLayers() > 1) {
|
|
throw new UnsupportedOperationException("Textures with multiple depths or layers are not yet supported for copying");
|
|
}
|
|
if (destination.getDepthOrLayers() > 1) {
|
|
throw new UnsupportedOperationException("Textures with multiple depths or layers are not yet supported for copying");
|
|
}
|
|
GlStateManager.clearGlErrors();
|
|
GlStateManager._disableScissorTest();
|
|
boolean isDepth = source.getFormat().hasDepthAspect();
|
|
int sourceId = ((GlTexture)source).glId();
|
|
int destId = ((GlTexture)destination).glId();
|
|
this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, isDepth ? 0 : sourceId, isDepth ? sourceId : 0, 0, 0);
|
|
this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, isDepth ? 0 : destId, isDepth ? destId : 0, 0, 0);
|
|
this.device.directStateAccess().blitFrameBuffers(this.readFbo, this.drawFbo, sourceX, sourceY, width, height, destX, destY, width, height, isDepth ? 256 : 16384, 9728);
|
|
int error = GlStateManager._getError();
|
|
if (error != 0) {
|
|
throw new IllegalStateException("Couldn't perform copyToTexture for texture " + source.getLabel() + " to " + destination.getLabel() + ": GL error " + error);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void presentTexture(GpuTextureView textureView) {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before performing additional commands");
|
|
}
|
|
if (!textureView.texture().getFormat().hasColorAspect()) {
|
|
throw new IllegalStateException("Cannot present a non-color texture!");
|
|
}
|
|
if ((textureView.texture().usage() & 8) == 0) {
|
|
throw new IllegalStateException("Color texture must have USAGE_RENDER_ATTACHMENT to presented to the screen");
|
|
}
|
|
if (textureView.texture().getDepthOrLayers() > 1) {
|
|
throw new UnsupportedOperationException("Textures with multiple depths or layers are not yet supported for presentation");
|
|
}
|
|
GlStateManager._disableScissorTest();
|
|
GlStateManager._viewport(0, 0, textureView.getWidth(0), textureView.getHeight(0));
|
|
GlStateManager._depthMask(true);
|
|
GlStateManager._colorMask(true, true, true, true);
|
|
this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, ((GlTexture)textureView.texture()).glId(), 0, 0, 0);
|
|
this.device.directStateAccess().blitFrameBuffers(this.drawFbo, 0, 0, 0, textureView.getWidth(0), textureView.getHeight(0), 0, 0, textureView.getWidth(0), textureView.getHeight(0), 16384, 9728);
|
|
}
|
|
|
|
@Override
|
|
public GpuFence createFence() {
|
|
if (this.inRenderPass) {
|
|
throw new IllegalStateException("Close the existing render pass before performing additional commands");
|
|
}
|
|
return new GlFence();
|
|
}
|
|
|
|
protected <T> void executeDrawMultiple(GlRenderPass renderPass, Collection<RenderPass.Draw<T>> draws, @Nullable GpuBuffer defaultIndexBuffer, @Nullable VertexFormat.IndexType defaultIndexType, Collection<String> dynamicUniforms, T uniformArgument) {
|
|
if (!this.trySetup(renderPass, dynamicUniforms)) {
|
|
return;
|
|
}
|
|
if (defaultIndexType == null) {
|
|
defaultIndexType = VertexFormat.IndexType.SHORT;
|
|
}
|
|
for (RenderPass.Draw<T> draw : draws) {
|
|
BiConsumer<T, RenderPass.UniformUploader> uniformUploaderConsumer;
|
|
VertexFormat.IndexType indexType = draw.indexType() == null ? defaultIndexType : draw.indexType();
|
|
renderPass.setIndexBuffer(draw.indexBuffer() == null ? defaultIndexBuffer : draw.indexBuffer(), indexType);
|
|
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!");
|
|
}
|
|
}
|
|
if ((uniformUploaderConsumer = draw.uniformUploaderConsumer()) != null) {
|
|
uniformUploaderConsumer.accept(uniformArgument, (name, buffer) -> {
|
|
Uniform patt1$temp = renderPass.pipeline.program().getUniform(name);
|
|
if (patt1$temp instanceof Uniform.Ubo) {
|
|
int blockBinding;
|
|
Uniform.Ubo $b$0 = (Uniform.Ubo)patt1$temp;
|
|
try {
|
|
int patt2$temp;
|
|
blockBinding = patt2$temp = $b$0.blockBinding();
|
|
}
|
|
catch (Throwable throwable) {
|
|
throw new MatchException(throwable.toString(), throwable);
|
|
}
|
|
GL32.glBindBufferRange((int)35345, (int)blockBinding, (int)((GlBuffer)buffer.buffer()).handle, (long)buffer.offset(), (long)buffer.length());
|
|
}
|
|
});
|
|
}
|
|
this.drawFromBuffers(renderPass, 0, draw.firstIndex(), draw.indexCount(), indexType, renderPass.pipeline, 1);
|
|
}
|
|
}
|
|
|
|
protected void executeDraw(GlRenderPass renderPass, int baseVertex, int firstIndex, int drawCount, @Nullable VertexFormat.IndexType indexType, int instanceCount) {
|
|
if (!this.trySetup(renderPass, Collections.emptyList())) {
|
|
return;
|
|
}
|
|
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.indexBuffer.usage() & 0x40) == 0) {
|
|
throw new IllegalStateException("Index buffer must have GpuBuffer.USAGE_INDEX!");
|
|
}
|
|
}
|
|
GlRenderPipeline pipeline = renderPass.pipeline;
|
|
if (renderPass.vertexBuffers[0] == null && pipeline != null && !pipeline.info().getVertexFormat().getElements().isEmpty()) {
|
|
throw new IllegalStateException("Vertex format contains elements but vertex buffer at slot 0 is null");
|
|
}
|
|
if (renderPass.vertexBuffers[0] != null && renderPass.vertexBuffers[0].isClosed()) {
|
|
throw new IllegalStateException("Vertex buffer at slot 0 has been closed!");
|
|
}
|
|
if (renderPass.vertexBuffers[0] != null && (renderPass.vertexBuffers[0].usage() & 0x20) == 0) {
|
|
throw new IllegalStateException("Vertex buffer must have GpuBuffer.USAGE_VERTEX!");
|
|
}
|
|
}
|
|
this.drawFromBuffers(renderPass, baseVertex, firstIndex, drawCount, indexType, renderPass.pipeline, instanceCount);
|
|
}
|
|
|
|
private void drawFromBuffers(GlRenderPass renderPass, int baseVertex, int firstIndex, int drawCount, @Nullable VertexFormat.IndexType indexType, GlRenderPipeline pipeline, int instanceCount) {
|
|
this.device.vertexArrayCache().bindVertexArray(pipeline.info().getVertexFormat(), (GlBuffer)renderPass.vertexBuffers[0]);
|
|
if (indexType != null) {
|
|
GlStateManager._glBindBuffer(34963, ((GlBuffer)renderPass.indexBuffer).handle);
|
|
if (instanceCount > 1) {
|
|
if (baseVertex > 0) {
|
|
GL32.glDrawElementsInstancedBaseVertex((int)GlConst.toGl(pipeline.info().getVertexFormatMode()), (int)drawCount, (int)GlConst.toGl(indexType), (long)((long)firstIndex * (long)indexType.bytes), (int)instanceCount, (int)baseVertex);
|
|
} else {
|
|
GL31.glDrawElementsInstanced((int)GlConst.toGl(pipeline.info().getVertexFormatMode()), (int)drawCount, (int)GlConst.toGl(indexType), (long)((long)firstIndex * (long)indexType.bytes), (int)instanceCount);
|
|
}
|
|
} else if (baseVertex > 0) {
|
|
GL32.glDrawElementsBaseVertex((int)GlConst.toGl(pipeline.info().getVertexFormatMode()), (int)drawCount, (int)GlConst.toGl(indexType), (long)((long)firstIndex * (long)indexType.bytes), (int)baseVertex);
|
|
} else {
|
|
GlStateManager._drawElements(GlConst.toGl(pipeline.info().getVertexFormatMode()), drawCount, GlConst.toGl(indexType), (long)firstIndex * (long)indexType.bytes);
|
|
}
|
|
} else if (instanceCount > 1) {
|
|
GL31.glDrawArraysInstanced((int)GlConst.toGl(pipeline.info().getVertexFormatMode()), (int)baseVertex, (int)drawCount, (int)instanceCount);
|
|
} else {
|
|
GlStateManager._drawArrays(GlConst.toGl(pipeline.info().getVertexFormatMode()), baseVertex, drawCount);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Could not resolve type clashes
|
|
* Unable to fully structure code
|
|
*/
|
|
private boolean trySetup(GlRenderPass renderPass, Collection<String> dynamicUniforms) {
|
|
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 uniform : renderPass.pipeline.info().getUniforms()) {
|
|
value = renderPass.uniforms.get(uniform.name());
|
|
if (dynamicUniforms.contains(uniform.name())) continue;
|
|
if (value == null) {
|
|
throw new IllegalStateException("Missing uniform " + uniform.name() + " (should be " + String.valueOf((Object)uniform.type()) + ")");
|
|
}
|
|
if (uniform.type() == UniformType.UNIFORM_BUFFER) {
|
|
if (value.buffer().isClosed()) {
|
|
throw new IllegalStateException("Uniform buffer " + uniform.name() + " is already closed");
|
|
}
|
|
if ((value.buffer().usage() & 128) == 0) {
|
|
throw new IllegalStateException("Uniform buffer " + uniform.name() + " must have GpuBuffer.USAGE_UNIFORM");
|
|
}
|
|
}
|
|
if (uniform.type() != UniformType.TEXEL_BUFFER) continue;
|
|
if (value.offset() != 0 || value.length() != value.buffer().size()) {
|
|
throw new IllegalStateException("Uniform texel buffers do not support a slice of a buffer, must be entire buffer");
|
|
}
|
|
if (uniform.textureFormat() != null) continue;
|
|
throw new IllegalStateException("Invalid uniform texel buffer " + uniform.name() + " (missing a texture format)");
|
|
}
|
|
for (Map.Entry entry : renderPass.pipeline.program().getUniforms().entrySet()) {
|
|
if (!(entry.getValue() instanceof Uniform.Sampler)) continue;
|
|
name = (String)entry.getKey();
|
|
viewAndSampler = renderPass.samplers.get(name);
|
|
if (viewAndSampler == null) {
|
|
throw new IllegalStateException("Missing sampler " + name);
|
|
}
|
|
textureView = viewAndSampler.view();
|
|
if (textureView.isClosed()) {
|
|
throw new IllegalStateException("Texture view " + name + " (" + textureView.texture().getLabel() + ") has been closed!");
|
|
}
|
|
if ((textureView.texture().usage() & 4) == 0) {
|
|
throw new IllegalStateException("Texture view " + name + " (" + textureView.texture().getLabel() + ") must have USAGE_TEXTURE_BINDING!");
|
|
}
|
|
if (!viewAndSampler.sampler().isClosed()) continue;
|
|
throw new IllegalStateException("Sampler for " + name + " (" + textureView.texture().getLabel() + ") has been closed!");
|
|
}
|
|
if (renderPass.pipeline.info().wantsDepthTexture() && !renderPass.hasDepthTexture()) {
|
|
GlCommandEncoder.LOGGER.warn("Render pipeline {} wants a depth texture but none was provided - this is probably a bug", (Object)renderPass.pipeline.info().getLocation());
|
|
}
|
|
} else if (renderPass.pipeline == null || renderPass.pipeline.program() == GlProgram.INVALID_PROGRAM) {
|
|
return false;
|
|
}
|
|
pipeline = renderPass.pipeline.info();
|
|
glProgram = renderPass.pipeline.program();
|
|
this.applyPipelineState(pipeline);
|
|
v0 = differentProgram = this.lastProgram != glProgram;
|
|
if (differentProgram) {
|
|
GlStateManager._glUseProgram(glProgram.getProgramId());
|
|
this.lastProgram = glProgram;
|
|
}
|
|
block15: for (Map.Entry<String, Uniform> entry : glProgram.getUniforms().entrySet()) {
|
|
block35: {
|
|
name = entry.getKey();
|
|
isDirty = renderPass.dirtyUniforms.contains(name);
|
|
Objects.requireNonNull(entry.getValue());
|
|
var11_13 = 0;
|
|
switch (SwitchBootstraps.typeSwitch("typeSwitch", new Object[]{Uniform.Ubo.class, Uniform.Utb.class, Uniform.Sampler.class}, (Object)var10_12, var11_13)) {
|
|
default: {
|
|
throw new MatchException(null, null);
|
|
}
|
|
case 0: {
|
|
var12_14 = (Uniform.Ubo)var10_12;
|
|
blockBinding = var14_16 = var12_14.blockBinding();
|
|
if (!isDirty) continue block15;
|
|
bufferView = renderPass.uniforms.get(name);
|
|
GL32.glBindBufferRange((int)35345, (int)blockBinding, (int)((GlBuffer)bufferView.buffer()).handle, (long)bufferView.offset(), (long)bufferView.length());
|
|
continue block15;
|
|
}
|
|
case 1: {
|
|
var14_18 = (Uniform.Utb)var10_12;
|
|
location = var19_23 = var14_18.location();
|
|
samplerIndex = var19_23 = var14_18.samplerIndex();
|
|
format = var19_24 = var14_18.format();
|
|
texture = var19_25 = var14_18.texture();
|
|
if (!differentProgram && !isDirty) ** GOTO lbl75
|
|
GlStateManager._glUniform1i(location, samplerIndex);
|
|
lbl75:
|
|
// 2 sources
|
|
|
|
GlStateManager._activeTexture(33984 + samplerIndex);
|
|
GL11C.glBindTexture((int)35882, (int)texture);
|
|
if (!isDirty) continue block15;
|
|
bufferView = renderPass.uniforms.get(name);
|
|
GL31.glTexBuffer((int)35882, (int)GlConst.toGlInternalId(format), (int)((GlBuffer)bufferView.buffer()).handle);
|
|
continue block15;
|
|
}
|
|
case 2:
|
|
}
|
|
var19_27 = (Uniform.Sampler)var10_12;
|
|
location = var22_31 = var19_27.location();
|
|
samplerIndex = var22_31 = var19_27.samplerIndex();
|
|
viewAndSampler = renderPass.samplers.get(name);
|
|
if (viewAndSampler == null) continue;
|
|
textureView = viewAndSampler.view();
|
|
if (!differentProgram && !isDirty) break block35;
|
|
GlStateManager._glUniform1i(location, samplerIndex);
|
|
}
|
|
GlStateManager._activeTexture(33984 + samplerIndex);
|
|
texture = textureView.texture();
|
|
if ((texture.usage() & 16) != 0) {
|
|
target = 34067;
|
|
GL11.glBindTexture((int)34067, (int)texture.id);
|
|
} else {
|
|
target = 3553;
|
|
GlStateManager._bindTexture(texture.id);
|
|
}
|
|
GL33C.glBindSampler((int)samplerIndex, (int)viewAndSampler.sampler().getId());
|
|
GlStateManager._texParameter(target, 33084, textureView.baseMipLevel());
|
|
GlStateManager._texParameter(target, 33085, textureView.baseMipLevel() + textureView.mipLevels() - 1);
|
|
}
|
|
renderPass.dirtyUniforms.clear();
|
|
if (renderPass.isScissorEnabled()) {
|
|
GlStateManager._enableScissorTest();
|
|
GlStateManager._scissorBox(renderPass.getScissorX(), renderPass.getScissorY(), renderPass.getScissorWidth(), renderPass.getScissorHeight());
|
|
} else {
|
|
GlStateManager._disableScissorTest();
|
|
}
|
|
return true;
|
|
catch (Throwable var6_8) {
|
|
throw new MatchException(var6_8.toString(), var6_8);
|
|
}
|
|
}
|
|
|
|
private void applyPipelineState(RenderPipeline pipeline) {
|
|
if (this.lastPipeline == pipeline) {
|
|
return;
|
|
}
|
|
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 = 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._polygonOffset(pipeline.getDepthBiasScaleFactor(), pipeline.getDepthBiasConstant());
|
|
GlStateManager._enablePolygonOffset();
|
|
} else {
|
|
GlStateManager._disablePolygonOffset();
|
|
}
|
|
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);
|
|
this.device.debugLabels().popDebugGroup();
|
|
}
|
|
|
|
protected GlDevice getDevice() {
|
|
return this.device;
|
|
}
|
|
|
|
@Override
|
|
public GpuQuery timerQueryBegin() {
|
|
RenderSystem.assertOnRenderThread();
|
|
if (this.activeTimerQuery != null) {
|
|
throw new IllegalStateException("A GL_TIME_ELAPSED query is already active");
|
|
}
|
|
int queryId = GL32C.glGenQueries();
|
|
GL32C.glBeginQuery((int)35007, (int)queryId);
|
|
this.activeTimerQuery = new GlTimerQuery(queryId);
|
|
return this.activeTimerQuery;
|
|
}
|
|
|
|
@Override
|
|
public void timerQueryEnd(GpuQuery query) {
|
|
RenderSystem.assertOnRenderThread();
|
|
if (query != this.activeTimerQuery) {
|
|
throw new IllegalStateException("Mismatched or duplicate GpuQuery when ending timerQuery");
|
|
}
|
|
GL32C.glEndQuery((int)35007);
|
|
this.activeTimerQuery = null;
|
|
}
|
|
}
|
|
|