GlCommandEncoder.java

com.mojang.blaze3d.opengl.GlCommandEncoder

信息

  • 全限定名:com.mojang.blaze3d.opengl.GlCommandEncoder
  • 类型:package-private class
  • 包:com.mojang.blaze3d.opengl
  • 源码路径:src/main/java/com/mojang/blaze3d/opengl/GlCommandEncoder.java
  • 起始行号:L44
  • 实现:CommandEncoderBackend
  • 职责:

    TODO

字段/常量

  • LOGGER

    • 类型: Logger
    • 修饰符: private static final
    • 源码定位: L45
    • 说明:

      TODO

  • device

    • 类型: GlDevice
    • 修饰符: private final
    • 源码定位: L46
    • 说明:

      TODO

  • readFbo

    • 类型: int
    • 修饰符: private final
    • 源码定位: L47
    • 说明:

      TODO

  • drawFbo

    • 类型: int
    • 修饰符: private final
    • 源码定位: L48
    • 说明:

      TODO

  • lastPipeline

    • 类型: RenderPipeline
    • 修饰符: private
    • 源码定位: L49
    • 说明:

      TODO

  • inRenderPass

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L50
    • 说明:

      TODO

  • lastProgram

    • 类型: GlProgram
    • 修饰符: private
    • 源码定位: L51
    • 说明:

      TODO

  • activeTimerQuery

    • 类型: GlTimerQuery
    • 修饰符: private
    • 源码定位: L52
    • 说明:

      TODO

内部类/嵌套类型

构造器

protected GlCommandEncoder(GlDevice device) @ L54

  • 构造器名:GlCommandEncoder
  • 源码定位:L54
  • 修饰符:protected

参数:

  • device: GlDevice

说明:

TODO

方法

下面的方法块按源码顺序生成。

public RenderPassBackend createRenderPass(Supplier<String> label, GpuTextureView colorTexture, OptionalInt clearColor) @ L60

  • 方法名:createRenderPass
  • 源码定位:L60
  • 返回类型:RenderPassBackend
  • 修饰符:public

参数:

  • label: Supplier
  • colorTexture: GpuTextureView
  • clearColor: OptionalInt

说明:

TODO

public RenderPassBackend createRenderPass(Supplier<String> label, GpuTextureView colorTexture, OptionalInt clearColor, GpuTextureView depthTexture, OptionalDouble clearDepth) @ L65

  • 方法名:createRenderPass
  • 源码定位:L65
  • 返回类型:RenderPassBackend
  • 修饰符:public

参数:

  • label: Supplier
  • colorTexture: GpuTextureView
  • clearColor: OptionalInt
  • depthTexture: GpuTextureView
  • clearDepth: OptionalDouble

说明:

TODO

public boolean isInRenderPass() @ L97

  • 方法名:isInRenderPass
  • 源码定位:L97
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

public void clearColorTexture(GpuTexture colorTexture, int clearColor) @ L102

  • 方法名:clearColorTexture
  • 源码定位:L102
  • 返回类型:void
  • 修饰符:public

参数:

  • colorTexture: GpuTexture
  • clearColor: int

说明:

TODO

public void clearColorAndDepthTextures(GpuTexture colorTexture, int clearColor, GpuTexture depthTexture, double clearDepth) @ L113

  • 方法名:clearColorAndDepthTextures
  • 源码定位:L113
  • 返回类型:void
  • 修饰符:public

参数:

  • colorTexture: GpuTexture
  • clearColor: int
  • depthTexture: GpuTexture
  • clearDepth: double

说明:

TODO

public void clearColorAndDepthTextures(GpuTexture colorTexture, int clearColor, GpuTexture depthTexture, double clearDepth, int regionX, int regionY, int regionWidth, int regionHeight) @ L126

  • 方法名:clearColorAndDepthTextures
  • 源码定位:L126
  • 返回类型:void
  • 修饰符:public

参数:

  • colorTexture: GpuTexture
  • clearColor: int
  • depthTexture: GpuTexture
  • clearDepth: double
  • regionX: int
  • regionY: int
  • regionWidth: int
  • regionHeight: int

说明:

TODO

public void clearDepthTexture(GpuTexture depthTexture, double clearDepth) @ L142

  • 方法名:clearDepthTexture
  • 源码定位:L142
  • 返回类型:void
  • 修饰符:public

参数:

  • depthTexture: GpuTexture
  • clearDepth: double

说明:

TODO

public void writeToBuffer(GpuBufferSlice slice, ByteBuffer data) @ L155

  • 方法名:writeToBuffer
  • 源码定位:L155
  • 返回类型:void
  • 修饰符:public

参数:

  • slice: GpuBufferSlice
  • data: ByteBuffer

说明:

TODO

public GpuBuffer.MappedView mapBuffer(GpuBufferSlice slice, boolean read, boolean write) @ L184

  • 方法名:mapBuffer
  • 源码定位:L184
  • 返回类型:GpuBuffer.MappedView
  • 修饰符:public

参数:

  • slice: GpuBufferSlice
  • read: boolean
  • write: boolean

说明:

TODO

public void copyToBuffer(GpuBufferSlice source, GpuBufferSlice target) @ L199

  • 方法名:copyToBuffer
  • 源码定位:L199
  • 返回类型:void
  • 修饰符:public

参数:

  • source: GpuBufferSlice
  • target: GpuBufferSlice

说明:

TODO

public void writeToTexture(GpuTexture destination, NativeImage source, int mipLevel, int depthOrLayer, int destX, int destY, int width, int height, int sourceX, int sourceY) @ L206

  • 方法名:writeToTexture
  • 源码定位:L206
  • 返回类型:void
  • 修饰符:public

参数:

  • destination: GpuTexture
  • source: NativeImage
  • mipLevel: int
  • depthOrLayer: int
  • destX: int
  • destY: int
  • width: int
  • height: int
  • sourceX: int
  • sourceY: int

说明:

TODO

public void writeToTexture(GpuTexture destination, ByteBuffer source, NativeImage.Format format, int mipLevel, int depthOrLayer, int destX, int destY, int width, int height) @ L226

  • 方法名:writeToTexture
  • 源码定位:L226
  • 返回类型:void
  • 修饰符:public

参数:

  • destination: GpuTexture
  • source: ByteBuffer
  • format: NativeImage.Format
  • mipLevel: int
  • depthOrLayer: int
  • destX: int
  • destY: int
  • width: int
  • height: int

说明:

TODO

public void copyTextureToBuffer(GpuTexture source, GpuBuffer destination, long offset, Runnable callback, int mipLevel) @ L246

  • 方法名:copyTextureToBuffer
  • 源码定位:L246
  • 返回类型:void
  • 修饰符:public

参数:

  • source: GpuTexture
  • destination: GpuBuffer
  • offset: long
  • callback: Runnable
  • mipLevel: int

说明:

TODO

public void copyTextureToBuffer(GpuTexture source, GpuBuffer destination, long offset, Runnable callback, int mipLevel, int x, int y, int width, int height) @ L251

  • 方法名:copyTextureToBuffer
  • 源码定位:L251
  • 返回类型:void
  • 修饰符:public

参数:

  • source: GpuTexture
  • destination: GpuBuffer
  • offset: long
  • callback: Runnable
  • mipLevel: int
  • x: int
  • y: int
  • width: int
  • height: int

说明:

TODO

public void copyTextureToTexture(GpuTexture source, GpuTexture destination, int mipLevel, int destX, int destY, int sourceX, int sourceY, int width, int height) @ L268

  • 方法名:copyTextureToTexture
  • 源码定位:L268
  • 返回类型:void
  • 修饰符:public

参数:

  • source: GpuTexture
  • destination: GpuTexture
  • mipLevel: int
  • destX: int
  • destY: int
  • sourceX: int
  • sourceY: int
  • width: int
  • height: int

说明:

TODO

public void presentTexture(GpuTextureView textureView) @ L290

  • 方法名:presentTexture
  • 源码定位:L290
  • 返回类型:void
  • 修饰符:public

参数:

  • textureView: GpuTextureView

说明:

TODO

public GpuFence createFence() @ L304

  • 方法名:createFence
  • 源码定位:L304
  • 返回类型:GpuFence
  • 修饰符:public

参数:

说明:

TODO

protected <T> void executeDrawMultiple(GlRenderPass renderPass, Collection<RenderPass.Draw<T>> draws, GpuBuffer defaultIndexBuffer, VertexFormat.IndexType defaultIndexType, Collection<String> dynamicUniforms, T uniformArgument) @ L309

  • 方法名:executeDrawMultiple
  • 源码定位:L309
  • 返回类型: void
  • 修饰符:protected

参数:

  • renderPass: GlRenderPass
  • draws: Collection<RenderPass.Draw>
  • defaultIndexBuffer: GpuBuffer
  • defaultIndexType: VertexFormat.IndexType
  • dynamicUniforms: Collection
  • uniformArgument: T

说明:

TODO

protected void executeDraw(GlRenderPass renderPass, int baseVertex, int firstIndex, int drawCount, VertexFormat.IndexType indexType, int instanceCount) @ L361

  • 方法名:executeDraw
  • 源码定位:L361
  • 返回类型:void
  • 修饰符:protected

参数:

  • renderPass: GlRenderPass
  • baseVertex: int
  • firstIndex: int
  • drawCount: int
  • indexType: VertexFormat.IndexType
  • instanceCount: int

说明:

TODO

private void drawFromBuffers(GlRenderPass renderPass, int baseVertex, int firstIndex, int drawCount, VertexFormat.IndexType indexType, GlRenderPipeline pipeline, int instanceCount) @ L398

  • 方法名:drawFromBuffers
  • 源码定位:L398
  • 返回类型:void
  • 修饰符:private

参数:

  • renderPass: GlRenderPass
  • baseVertex: int
  • firstIndex: int
  • drawCount: int
  • indexType: VertexFormat.IndexType
  • pipeline: GlRenderPipeline
  • instanceCount: int

说明:

TODO

private boolean trySetup(GlRenderPass renderPass, Collection<String> dynamicUniforms) @ L445

  • 方法名:trySetup
  • 源码定位:L445
  • 返回类型:boolean
  • 修饰符:private

参数:

  • renderPass: GlRenderPass
  • dynamicUniforms: Collection

说明:

TODO

private void applyPipelineState(RenderPipeline pipeline) @ L610

  • 方法名:applyPipelineState
  • 源码定位:L610
  • 返回类型:void
  • 修饰符:private

参数:

  • pipeline: RenderPipeline

说明:

TODO

public void finishRenderPass() @ L654

  • 方法名:finishRenderPass
  • 源码定位:L654
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public GpuQuery timerQueryBegin() @ L660

  • 方法名:timerQueryBegin
  • 源码定位:L660
  • 返回类型:GpuQuery
  • 修饰符:public

参数:

说明:

TODO

public void timerQueryEnd(GpuQuery query) @ L673

  • 方法名:timerQueryEnd
  • 源码定位:L673
  • 返回类型:void
  • 修饰符:public

参数:

  • query: GpuQuery

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
class GlCommandEncoder implements CommandEncoderBackend {
    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 RenderPassBackend createRenderPass(Supplier<String> label, GpuTextureView colorTexture, OptionalInt clearColor) {
        return this.createRenderPass(label, colorTexture, clearColor, null, OptionalDouble.empty());
    }
 
    @Override
    public RenderPassBackend createRenderPass(
        Supplier<String> label, GpuTextureView colorTexture, OptionalInt clearColor, @Nullable GpuTextureView depthTexture, OptionalDouble clearDepth
    ) {
        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(ARGB.redFloat(argb), ARGB.greenFloat(argb), ARGB.blueFloat(argb), ARGB.alphaFloat(argb));
            clearMask |= 16384;
        }
 
        if (depthTexture != null && clearDepth.isPresent()) {
            GL11.glClearDepth(clearDepth.getAsDouble());
            clearMask |= 256;
        }
 
        if (clearMask != 0) {
            GlStateManager._disableScissorTest();
            GlStateManager._depthMask(true);
            GlStateManager._colorMask(15);
            GlStateManager._clear(clearMask);
        }
 
        GlStateManager._viewport(0, 0, colorTexture.getWidth(0), colorTexture.getHeight(0));
        this.lastPipeline = null;
        return new GlRenderPass(this, this.device, depthTexture != null);
    }
 
    @Override
    public boolean isInRenderPass() {
        return this.inRenderPass;
    }
 
    @Override
    public void clearColorTexture(GpuTexture colorTexture, int clearColor) {
        this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, ((GlTexture)colorTexture).id, 0, 0, 36160);
        GL11.glClearColor(ARGB.redFloat(clearColor), ARGB.greenFloat(clearColor), ARGB.blueFloat(clearColor), ARGB.alphaFloat(clearColor));
        GlStateManager._disableScissorTest();
        GlStateManager._colorMask(15);
        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) {
        int fbo = ((GlTexture)colorTexture).getFbo(this.device.directStateAccess(), depthTexture);
        GlStateManager._glBindFramebuffer(36160, fbo);
        GlStateManager._disableScissorTest();
        GL11.glClearDepth(clearDepth);
        GL11.glClearColor(ARGB.redFloat(clearColor), ARGB.greenFloat(clearColor), ARGB.blueFloat(clearColor), ARGB.alphaFloat(clearColor));
        GlStateManager._depthMask(true);
        GlStateManager._colorMask(15);
        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
    ) {
        int fbo = ((GlTexture)colorTexture).getFbo(this.device.directStateAccess(), depthTexture);
        GlStateManager._glBindFramebuffer(36160, fbo);
        GlStateManager._scissorBox(regionX, regionY, regionWidth, regionHeight);
        GlStateManager._enableScissorTest();
        GL11.glClearDepth(clearDepth);
        GL11.glClearColor(ARGB.redFloat(clearColor), ARGB.greenFloat(clearColor), ARGB.blueFloat(clearColor), ARGB.alphaFloat(clearColor));
        GlStateManager._depthMask(true);
        GlStateManager._colorMask(15);
        GlStateManager._clear(16640);
        GlStateManager._glBindFramebuffer(36160, 0);
    }
 
    @Override
    public void clearDepthTexture(GpuTexture depthTexture, double clearDepth) {
        this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)depthTexture).id, 0, 36160);
        GL11.glDrawBuffer(0);
        GL11.glClearDepth(clearDepth);
        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(GpuBufferSlice slice, ByteBuffer data) {
        GlBuffer buffer = (GlBuffer)slice.buffer();
        if (buffer.closed) {
            throw new IllegalStateException("Buffer already closed");
        } else if ((buffer.usage() & 8) == 0) {
            throw new IllegalStateException("Buffer needs USAGE_COPY_DST to be a destination for a copy");
        } else {
            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() + ")"
                );
            } else 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)"
                );
            } else {
                this.device.directStateAccess().bufferSubData(buffer.handle, slice.offset(), data, buffer.usage());
            }
        }
    }
 
    @Override
    public GpuBuffer.MappedView mapBuffer(GpuBufferSlice slice, boolean read, boolean write) {
        GlBuffer buffer = (GlBuffer)slice.buffer();
        int flags = 0;
        if (read) {
            flags |= 1;
        }
 
        if (write) {
            flags |= 34;
        }
 
        return this.device.getBufferStorage().mapBuffer(this.device.directStateAccess(), buffer, slice.offset(), slice.length(), flags);
    }
 
    @Override
    public void copyToBuffer(GpuBufferSlice source, GpuBufferSlice target) {
        GlBuffer sourceBuffer = (GlBuffer)source.buffer();
        GlBuffer targetBuffer = (GlBuffer)target.buffer();
        this.device.directStateAccess().copyBufferSubData(sourceBuffer.handle, targetBuffer.handle, source.offset(), target.offset(), source.length());
    }
 
    @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 ((destination.usage() & 16) != 0) {
            target = GlConst.CUBEMAP_TARGETS[depthOrLayer % 6];
            GL11.glBindTexture(34067, ((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 ((destination.usage() & 16) != 0) {
            target = GlConst.CUBEMAP_TARGETS[depthOrLayer % 6];
            GL11.glBindTexture(34067, ((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, long offset, Runnable callback, int mipLevel) {
        this.copyTextureToBuffer(source, destination, offset, callback, mipLevel, 0, 0, source.getWidth(mipLevel), source.getHeight(mipLevel));
    }
 
    @Override
    public void copyTextureToBuffer(GpuTexture source, GpuBuffer destination, long offset, Runnable callback, int mipLevel, int x, int y, int width, int height) {
        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
    ) {
        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) {
        GlStateManager._disableScissorTest();
        GlStateManager._viewport(0, 0, textureView.getWidth(0), textureView.getHeight(0));
        GlStateManager._depthMask(true);
        GlStateManager._colorMask(15);
        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() {
        return new GlFence();
    }
 
    protected <T> void executeDrawMultiple(
        GlRenderPass renderPass,
        Collection<RenderPass.Draw<T>> draws,
        @Nullable GpuBuffer defaultIndexBuffer,
        VertexFormat.@Nullable IndexType defaultIndexType,
        Collection<String> dynamicUniforms,
        T uniformArgument
    ) {
        if (this.trySetup(renderPass, dynamicUniforms)) {
            if (defaultIndexType == null) {
                defaultIndexType = VertexFormat.IndexType.SHORT;
            }
 
            for (RenderPass.Draw<T> draw : draws) {
                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!");
                    }
                }
 
                BiConsumer<T, RenderPass.UniformUploader> uniformUploaderConsumer = draw.uniformUploaderConsumer();
                if (uniformUploaderConsumer != null) {
                    uniformUploaderConsumer.accept(uniformArgument, (name, buffer) -> {
                        if (renderPass.pipeline.program().getUniform(name) instanceof Uniform.Ubo(int var9x)) {
                            int patt2$temp = var9x;
                            if (true) {
                                GL32.glBindBufferRange(35345, patt2$temp, ((GlBuffer)buffer.buffer()).handle, buffer.offset(), buffer.length());
                            }
                        }
                    });
                }
 
                this.drawFromBuffers(renderPass, draw.baseVertex(), draw.firstIndex(), draw.indexCount(), indexType, renderPass.pipeline, 1);
            }
        }
    }
 
    protected void executeDraw(
        GlRenderPass renderPass, int baseVertex, int firstIndex, int drawCount, VertexFormat.@Nullable IndexType indexType, int instanceCount
    ) {
        if (this.trySetup(renderPass, Collections.emptyList())) {
            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() & 64) == 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() & 32) == 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,
        VertexFormat.@Nullable 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(
                        GlConst.toGl(pipeline.info().getVertexFormatMode()),
                        drawCount,
                        GlConst.toGl(indexType),
                        (long)firstIndex * indexType.bytes,
                        instanceCount,
                        baseVertex
                    );
                } else {
                    GL31.glDrawElementsInstanced(
                        GlConst.toGl(pipeline.info().getVertexFormatMode()),
                        drawCount,
                        GlConst.toGl(indexType),
                        (long)firstIndex * indexType.bytes,
                        instanceCount
                    );
                }
            } else if (baseVertex > 0) {
                GL32.glDrawElementsBaseVertex(
                    GlConst.toGl(pipeline.info().getVertexFormatMode()), drawCount, GlConst.toGl(indexType), (long)firstIndex * indexType.bytes, baseVertex
                );
            } else {
                GlStateManager._drawElements(
                    GlConst.toGl(pipeline.info().getVertexFormatMode()), drawCount, GlConst.toGl(indexType), (long)firstIndex * indexType.bytes
                );
            }
        } else if (instanceCount > 1) {
            GL31.glDrawArraysInstanced(GlConst.toGl(pipeline.info().getVertexFormatMode()), baseVertex, drawCount, instanceCount);
        } else {
            GlStateManager._drawArrays(GlConst.toGl(pipeline.info().getVertexFormatMode()), baseVertex, drawCount);
        }
    }
 
    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()) {
                GpuBufferSlice value = renderPass.uniforms.get(uniform.name());
                if (!dynamicUniforms.contains(uniform.name())) {
                    if (value == null) {
                        throw new IllegalStateException("Missing uniform " + uniform.name() + " (should be " + 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) {
                        if (value.offset() != 0L || 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) {
                            throw new IllegalStateException("Invalid uniform texel buffer " + uniform.name() + " (missing a texture format)");
                        }
                    }
                }
            }
 
            for (Entry<String, Uniform> entry : renderPass.pipeline.program().getUniforms().entrySet()) {
                if (entry.getValue() instanceof Uniform.Sampler) {
                    String name = entry.getKey();
                    GlRenderPass.TextureViewAndSampler viewAndSampler = renderPass.samplers.get(name);
                    if (viewAndSampler == null) {
                        throw new IllegalStateException("Missing sampler " + name);
                    }
 
                    GlTextureView 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()) {
                        throw new IllegalStateException("Sampler for " + name + " (" + textureView.texture().getLabel() + ") 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 pipeline = renderPass.pipeline.info();
        GlProgram glProgram = renderPass.pipeline.program();
        this.applyPipelineState(pipeline);
        boolean differentProgram = this.lastProgram != glProgram;
        if (differentProgram) {
            GlStateManager._glUseProgram(glProgram.getProgramId());
            this.lastProgram = glProgram;
        }
 
        label200:
        for (Entry<String, Uniform> entryx : glProgram.getUniforms().entrySet()) {
            String namex = entryx.getKey();
            boolean isDirty = renderPass.dirtyUniforms.contains(namex);
            Uniform var10000 = entryx.getValue();
            Objects.requireNonNull(var10000);
            Uniform var10 = var10000;
            byte var11 = 0;
 
            {
                switch (var10) {
                    case Uniform.Ubo var12:
                        int var63;
                        Uniform.Ubo var62 = var12;
 
                        try {
                            var63 = var62.blockBinding();
                        } catch (Throwable var32) {
                            throw new MatchException(var32.toString(), var32);
                        }
 
                        int var41 = var63;
                        if (true) {
                            if (isDirty) {
                                GpuBufferSlice bufferView = renderPass.uniforms.get(namex);
                                GL32.glBindBufferRange(35345, var41, ((GlBuffer)bufferView.buffer()).handle, bufferView.offset(), bufferView.length());
                            }
                            continue label200;
                        }
 
                        var11 = 1;
                        break;
                    case Uniform.Utb(int location, int samplerIdx, TextureFormat var45, int var43):
                                    if (differentProgram || isDirty) {
                                        GlStateManager._glUniform1i(location, samplerIdx);
                                    }
 
                                    GlStateManager._activeTexture(33984 + samplerIdx);
                                    GL11C.glBindTexture(35882, var43);
                                    if (isDirty) {
                                        GpuBufferSlice bufferViewx = renderPass.uniforms.get(namex);
                                        GL31.glTexBuffer(35882, GlConst.toGlInternalId(var45), ((GlBuffer)bufferViewx.buffer()).handle);
                                    }
                                    continue label200;
                    case Uniform.Sampler(int location, int samplerIndex):
                                GlRenderPass.TextureViewAndSampler viewAndSamplerxx = renderPass.samplers.get(namex);
                                if (viewAndSamplerxx == null) {
                                    continue label200;
                                }
 
                                GlTextureView textureViewx = viewAndSamplerxx.view();
                                if (differentProgram || isDirty) {
                                    GlStateManager._glUniform1i(location, samplerIndex);
                                }
 
                                GlStateManager._activeTexture(33984 + samplerIndex);
                                GlTexture texture = textureViewx.texture();
                                int target;
                                if ((texture.usage() & 16) != 0) {
                                    target = 34067;
                                    GL11.glBindTexture(34067, texture.id);
                                } else {
                                    target = 3553;
                                    GlStateManager._bindTexture(texture.id);
                                }
 
                                GL33C.glBindSampler(samplerIndex, viewAndSamplerxx.sampler().getId());
                                GlStateManager._texParameter(target, 33084, textureViewx.baseMipLevel());
                                GlStateManager._texParameter(target, 33085, textureViewx.baseMipLevel() + textureViewx.mipLevels() - 1);
                                continue label200;
                    default:
                        throw new MatchException(null, null);
                }
            }
        }
 
        renderPass.dirtyUniforms.clear();
        if (renderPass.isScissorEnabled()) {
            GlStateManager._enableScissorTest();
            GlStateManager._scissorBox(renderPass.getScissorX(), renderPass.getScissorY(), renderPass.getScissorWidth(), renderPass.getScissorHeight());
        } else {
            GlStateManager._disableScissorTest();
        }
 
        return true;
    }
 
    private void applyPipelineState(RenderPipeline pipeline) {
        if (this.lastPipeline != pipeline) {
            this.lastPipeline = pipeline;
            DepthStencilState depthStencilState = pipeline.getDepthStencilState();
            if (depthStencilState != null) {
                GlStateManager._enableDepthTest();
                GlStateManager._depthFunc(GlConst.toGl(depthStencilState.depthTest()));
                GlStateManager._depthMask(depthStencilState.writeDepth());
                if (depthStencilState.depthBiasConstant() == 0.0F && depthStencilState.depthBiasScaleFactor() == 0.0F) {
                    GlStateManager._disablePolygonOffset();
                } else {
                    GlStateManager._polygonOffset(depthStencilState.depthBiasScaleFactor(), depthStencilState.depthBiasConstant());
                    GlStateManager._enablePolygonOffset();
                }
            } else {
                GlStateManager._disableDepthTest();
                GlStateManager._depthMask(false);
                GlStateManager._disablePolygonOffset();
            }
 
            if (pipeline.isCull()) {
                GlStateManager._enableCull();
            } else {
                GlStateManager._disableCull();
            }
 
            if (pipeline.getColorTargetState().blendFunction().isPresent()) {
                GlStateManager._enableBlend();
                BlendFunction blendFunction = pipeline.getColorTargetState().blendFunction().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._colorMask(pipeline.getColorTargetState().writeMask());
        }
    }
 
    public void finishRenderPass() {
        this.inRenderPass = false;
        GlStateManager._glBindFramebuffer(36160, 0);
        this.device.debugLabels().popDebugGroup();
    }
 
    @Override
    public GpuQuery timerQueryBegin() {
        RenderSystem.assertOnRenderThread();
        if (this.activeTimerQuery != null) {
            throw new IllegalStateException("A GL_TIME_ELAPSED query is already active");
        } else {
            int queryId = GL32C.glGenQueries();
            GL32C.glBeginQuery(35007, 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");
        } else {
            GL32C.glEndQuery(35007);
            this.activeTimerQuery = null;
        }
    }
}

引用的其他类

  • GpuBuffer

    • 引用位置: 参数/返回值
  • GpuBufferSlice

    • 引用位置: 参数
  • GpuFence

    • 引用位置: 返回值
  • GlConst

    • 引用位置: 方法调用
    • 关联成员: GlConst.toGl(), GlConst.toGlExternalId(), GlConst.toGlInternalId(), GlConst.toGlType()
  • GlDevice

    • 引用位置: 参数/字段
  • GlFence

    • 引用位置: 构造调用
    • 关联成员: GlFence()
  • GlProgram

    • 引用位置: 字段
  • GlRenderPass

    • 引用位置: 参数/构造调用
    • 关联成员: GlRenderPass()
  • GlRenderPipeline

    • 引用位置: 参数
  • GlStateManager

    • 引用位置: 方法调用
    • 关联成员: GlStateManager._activeTexture(), GlStateManager._bindTexture(), GlStateManager._blendFuncSeparate(), GlStateManager._clear(), GlStateManager._colorMask(), GlStateManager._depthFunc(), GlStateManager._depthMask(), GlStateManager._disableBlend(), GlStateManager._disableCull(), GlStateManager._disableDepthTest(), GlStateManager._disablePolygonOffset(), GlStateManager._disableScissorTest(), GlStateManager._drawArrays(), GlStateManager._drawElements(), GlStateManager._enableBlend(), GlStateManager._enableCull(), GlStateManager._enableDepthTest(), GlStateManager._enablePolygonOffset(), GlStateManager._enableScissorTest(), GlStateManager._getError(), GlStateManager._glBindBuffer(), GlStateManager._glBindFramebuffer(), GlStateManager._glFramebufferTexture2D(), GlStateManager._glUniform1i(), GlStateManager._glUseProgram(), GlStateManager._pixelStore(), GlStateManager._polygonMode(), GlStateManager._polygonOffset(), GlStateManager._readPixels(), GlStateManager._scissorBox(), GlStateManager._texParameter(), GlStateManager._texSubImage2D(), GlStateManager._viewport(), GlStateManager.clearGlErrors()
  • GlTimerQuery

    • 引用位置: 字段/构造调用
    • 关联成员: GlTimerQuery()
  • Uniform

    • 引用位置: 方法调用
    • 关联成员: Uniform.Sampler(), Uniform.Ubo(), Uniform.Utb()
  • RenderPipeline

    • 引用位置: 参数/字段
  • NativeImage

    • 引用位置: 参数
  • CommandEncoderBackend

    • 引用位置: 实现
  • GpuQuery

    • 引用位置: 参数/返回值
  • RenderPass

    • 引用位置: 参数
  • RenderPassBackend

    • 引用位置: 返回值
  • RenderSystem

    • 引用位置: 方法调用
    • 关联成员: RenderSystem.assertOnRenderThread(), RenderSystem.queueFencedTask()
  • GpuTexture

    • 引用位置: 参数
  • GpuTextureView

    • 引用位置: 参数
  • VertexFormat

    • 引用位置: 参数
  • ARGB

    • 引用位置: 方法调用
    • 关联成员: ARGB.alphaFloat(), ARGB.blueFloat(), ARGB.greenFloat(), ARGB.redFloat()