Skip to content

Commit

Permalink
Full screen rendering now uses a large triangle
Browse files Browse the repository at this point in the history
  • Loading branch information
Ocelot5836 committed Jan 12, 2025
1 parent a32e20f commit 4cebe57
Show file tree
Hide file tree
Showing 17 changed files with 172 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public final class VeilRenderSystem {
private static final BooleanSupplier SPARSE_BUFFERS_SUPPORTED = glCapability(caps -> caps.OpenGL44 || caps.GL_ARB_sparse_buffer);
private static final BooleanSupplier DIRECT_STATE_ACCESS_SUPPORTED = glCapability(caps -> caps.OpenGL45 || caps.GL_ARB_direct_state_access);
private static final BooleanSupplier CLEAR_TEXTURE_SUPPORTED = glCapability(caps -> caps.OpenGL44 || caps.GL_ARB_clear_texture);
private static final BooleanSupplier COPY_IMAGE_SUPPORTED = glCapability(caps -> caps.OpenGL43 || caps.GL_ARB_copy_image);
private static final BooleanSupplier SHADER_STORAGE_BLOCK_SUPPORTED = VeilRenderSystem.glCapability(caps -> caps.OpenGL43 || caps.GL_ARB_shader_storage_buffer_object);
private static final BooleanSupplier PROGRAM_INTERFACE_QUERY_SUPPORTED = VeilRenderSystem.glCapability(caps -> caps.OpenGL43 || caps.GL_ARB_program_interface_query);
private static final IntSupplier MAX_COMBINED_TEXTURE_IMAGE_UNITS = VeilRenderSystem.glGetter(() -> glGetInteger(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS));
Expand Down Expand Up @@ -217,7 +218,6 @@ public final class VeilRenderSystem {

private static VeilRenderer renderer;
private static ResourceLocation shaderLocation;
private static VertexArray screenQuad;

private VeilRenderSystem() {
}
Expand Down Expand Up @@ -302,16 +302,6 @@ public static void init() {

renderer = new VeilRenderer(resourceManager, client.getWindow());
VeilImGuiImpl.init(client.getWindow().getWindow());

BufferBuilder bufferBuilder = RenderSystem.renderThreadTesselator().begin(VertexFormat.Mode.TRIANGLE_STRIP, DefaultVertexFormat.POSITION);
bufferBuilder.addVertex(-1, 1, 0);
bufferBuilder.addVertex(-1, -1, 0);
bufferBuilder.addVertex(1, 1, 0);
bufferBuilder.addVertex(1, -1, 0);

screenQuad = VertexArray.create();
screenQuad.upload(bufferBuilder.buildOrThrow(), VertexArray.DrawUsage.STATIC);
VertexBuffer.unbind();
}

/**
Expand All @@ -334,15 +324,6 @@ public static void bindTextures(int first, int... textures) {
VeilTextureMultiBind.get().bindTextures(first, textures);
}

/**
* Draws a quad onto the full screen using {@link DefaultVertexFormat#POSITION}.
*/
public static void drawScreenQuad() {
screenQuad.bind();
screenQuad.draw(GL_TRIANGLE_STRIP);
VertexBuffer.unbind();
}

/**
* Sets the shader instance to be a reference to the shader manager.
*
Expand Down Expand Up @@ -525,6 +506,13 @@ public static boolean clearTextureSupported() {
return VeilRenderSystem.CLEAR_TEXTURE_SUPPORTED.getAsBoolean();
}

/**
* @return Whether {@link ARBCopyImage} is supported
*/
public static boolean copyImageSupported() {
return VeilRenderSystem.COPY_IMAGE_SUPPORTED.getAsBoolean();
}

/**
* @return Whether {@link ARBShaderStorageBufferObject} is supported
*/
Expand Down Expand Up @@ -910,7 +898,6 @@ public static void close() {
if (renderer != null) {
renderer.free();
}
screenQuad.close();
SHADER_BUFFER_CACHE.free();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
import java.util.Map;
import java.util.Optional;

import static org.lwjgl.opengl.GL11C.GL_TRIANGLE_STRIP;
import static org.lwjgl.opengl.GL11C.glDrawArrays;

/**
* A basic stage that draws a quad to the output using a specified shader.
*
Expand Down Expand Up @@ -82,7 +85,7 @@ public void apply(Context context) {
for (Map.Entry<String, UniformValue> entry : this.uniforms.entrySet()) {
entry.getValue().apply(entry.getKey(), shader);
}
VeilRenderSystem.drawScreenQuad();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
context.clearSamplers(shader);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,18 @@ private VeilShaders() {
}

public static final ResourceLocation PARTICLE = quasar("particle");
public static final ResourceLocation PARTICLE_ADD = quasar("particle_add");

public static final ResourceLocation LIGHT_AMBIENT = light("ambient");
public static final ResourceLocation LIGHT_DIRECTIONAL = light("directional");
public static final ResourceLocation LIGHT_POINT = light("point");
public static final ResourceLocation LIGHT_AREA = light("area");
public static final ResourceLocation LIGHT_VANILLA_LIGHTMAP = light("vanilla_lightmap");
public static final ResourceLocation LIGHT_SKY = light("sky");
public static final ResourceLocation LIGHT_INDIRECT_SPHERE = light("indirect_sphere");

public static final ResourceLocation SKINNED_MESH = necromancer("skinned_mesh");

public static final ResourceLocation DEBUG_CUBEMAP = debug("cubemap");

public static final ResourceLocation BLIT_SCREEN = Veil.veilPath("blit_screen");

private static ResourceLocation quasar(String name) {
return Veil.veilPath("quasar/" + name);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package foundry.veil.ext;

import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Internal
public interface PerformanceRenderTargetExtension {

void veil$clearColorBuffer(boolean clearError);
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ private void renderOpenGL() {
flagText("inspector.veil.device_info.opengl.feature_flag.sparse_buffers", VeilRenderSystem.sparseBuffersSupported(), "Whether sparse buffers can be used");
flagText("inspector.veil.device_info.opengl.feature_flag.direct_state_access", VeilRenderSystem.directStateAccessSupported(), "Whether direct state accesss can be used");
flagText("inspector.veil.device_info.opengl.feature_flag.clear_texture", VeilRenderSystem.clearTextureSupported(), "Whether glClearTexImage can be used");
flagText("inspector.veil.device_info.opengl.feature_flag.copy_image", VeilRenderSystem.copyImageSupported(), "Whether glCopyImageSubData can be used");
flagText("inspector.veil.device_info.opengl.feature_flag.shader_storage_buffers", VeilRenderSystem.shaderStorageBufferSupported(), "Whether shader storage buffers can be used");
flagText("inspector.veil.device_info.opengl.feature_flag.program_interface_query", VeilRenderSystem.programInterfaceQuerySupported(), "Whether the new style program interface query can be used");
ImGui.separator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ public void render() {
if (ImGui.collapsingHeader(SAMPLERS.getString(), ImGuiTreeNodeFlags.DefaultOpen) && !invalid) {
ImGui.indent();
for (CharSequence sampler : this.uniformCache.getSamplers()) {
ImGui.selectable(sampler.toString());
ImGui.selectable(sampler + ": " + glGetUniformi(program, Objects.requireNonNull(this.uniformCache.getUniform(sampler)).location()));
}
ImGui.unindent();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ public void render(int width, int height) {
this.fbo.clear();
glBindTexture(GL_TEXTURE_CUBE_MAP, this.texture);
shaderProgram.bind();
VeilRenderSystem.drawScreenQuad();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
AdvancedFbo.unbind();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package foundry.veil.mixin.performance.client;

import com.mojang.blaze3d.pipeline.RenderTarget;
import foundry.veil.ext.PerformanceRenderTargetExtension;
import net.minecraft.client.renderer.LevelRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(LevelRenderer.class)
public class LevelRendererMixin {

@Redirect(method = "renderLevel", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/pipeline/RenderTarget;clear(Z)V", ordinal = 0))
public void clearItemEntityDepth(RenderTarget instance, boolean clearError) {
((PerformanceRenderTargetExtension) instance).veil$clearColorBuffer(clearError);
}

@Redirect(method = "renderLevel", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/pipeline/RenderTarget;clear(Z)V", ordinal = 3))
public void clearTranslucentDepth(RenderTarget instance, boolean clearError) {
((PerformanceRenderTargetExtension) instance).veil$clearColorBuffer(clearError);
}

@Redirect(method = "renderLevel", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/pipeline/RenderTarget;clear(Z)V", ordinal = 4))
public void clearParticlesDepth(RenderTarget instance, boolean clearError) {
((PerformanceRenderTargetExtension) instance).veil$clearColorBuffer(clearError);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import static org.lwjgl.opengl.GL11C.GL_TRIANGLE_STRIP;
import static org.lwjgl.opengl.GL11C.glDrawArrays;
import static org.lwjgl.opengl.GL13C.GL_TEXTURE0;

@Mixin(ScreenEffectRenderer.class)
Expand Down Expand Up @@ -70,7 +72,7 @@ private static void renderTex(TextureAtlasSprite texture, PoseStack poseStack, C
minecraft.getTextureManager().bindForSetup(texture.atlasLocation());

shader.bind();
VeilRenderSystem.drawScreenQuad();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
ShaderProgram.unbind();

RenderSystem.activeTexture(activeTexture);
Expand Down Expand Up @@ -111,7 +113,7 @@ private static void renderWater(Minecraft minecraft, PoseStack poseStack, Callba

RenderSystem.enableBlend();
shader.bind();
VeilRenderSystem.drawScreenQuad();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
ShaderProgram.unbind();
RenderSystem.disableBlend();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package foundry.veil.mixin.performance.client;

import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import foundry.veil.api.client.render.VeilRenderSystem;
import foundry.veil.api.client.render.shader.VeilShaders;
import foundry.veil.api.client.render.shader.program.ShaderProgram;
import foundry.veil.ext.PerformanceRenderTargetExtension;
import foundry.veil.ext.RenderTargetExtension;
import org.lwjgl.system.MemoryStack;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -11,12 +17,13 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import static org.lwjgl.opengl.ARBClearTexture.glClearTexImage;
import static org.lwjgl.opengl.ARBCopyImage.glCopyImageSubData;
import static org.lwjgl.opengl.ARBDirectStateAccess.glBlitNamedFramebuffer;
import static org.lwjgl.opengl.ARBDirectStateAccess.glClearNamedFramebufferfv;
import static org.lwjgl.opengl.GL11C.*;

@Mixin(RenderTarget.class)
public abstract class RenderTargetMixin {
public abstract class RenderTargetMixin implements PerformanceRenderTargetExtension {

@Shadow
public int frameBufferId;
Expand All @@ -41,26 +48,37 @@ public abstract class RenderTargetMixin {
@Shadow
public abstract int getDepthTextureId();

@Shadow
public abstract void bindWrite(boolean setViewport);

@Shadow
public abstract void unbindWrite();

@Inject(method = "copyDepthFrom", at = @At("HEAD"), cancellable = true)
public void copyDepthFrom(RenderTarget otherTarget, CallbackInfo ci) {
if (!VeilRenderSystem.directStateAccessSupported()) {
if (!this.useDepth || !otherTarget.useDepth) {
ci.cancel();
return;
}

ci.cancel();
glBlitNamedFramebuffer(otherTarget.frameBufferId, this.frameBufferId, 0, 0, otherTarget.width, otherTarget.height, 0, 0, this.width, this.height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
if (VeilRenderSystem.copyImageSupported() && this.width == otherTarget.width && this.height == otherTarget.height) {
ci.cancel();
glCopyImageSubData(otherTarget.getDepthTextureId(), GL_TEXTURE_2D, 0, 0, 0, 0, this.getDepthTextureId(), GL_TEXTURE_2D, 0, 0, 0, 0, this.width, this.height, 1);
} else if (VeilRenderSystem.directStateAccessSupported()) {
ci.cancel();
glBlitNamedFramebuffer(otherTarget.frameBufferId, this.frameBufferId, 0, 0, otherTarget.width, otherTarget.height, 0, 0, this.width, this.height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
}
}

@Inject(method = "clear", at = @At("HEAD"), cancellable = true)
public void clear(boolean clearError, CallbackInfo ci) {
if (!VeilRenderSystem.directStateAccessSupported()) {
boolean clearTex = VeilRenderSystem.clearTextureSupported();
if (!clearTex && !VeilRenderSystem.directStateAccessSupported()) {
return;
}

ci.cancel();
try (MemoryStack stack = MemoryStack.stackPush()) {
boolean clearTex = VeilRenderSystem.clearTextureSupported();

if (clearTex) {
glClearTexImage(this.getColorTextureId(), 0, GL_RGBA, GL_FLOAT, this.clearChannels);
} else {
Expand All @@ -80,4 +98,59 @@ public void clear(boolean clearError, CallbackInfo ci) {
glGetError();
}
}

@Inject(method = "_blitToScreen", at = @At("HEAD"), cancellable = true)
private void _blitToScreen(int width, int height, boolean disableBlend, CallbackInfo ci) {
if (disableBlend && VeilRenderSystem.directStateAccessSupported()) {
ci.cancel();
RenderSystem.assertOnRenderThread();
GlStateManager._viewport(0, 0, width, height);
GlStateManager._colorMask(true, true, true, false);
int frameBufferId = ((RenderTargetExtension) this).veil$getFramebuffer();
glBlitNamedFramebuffer(frameBufferId, 0, 0, 0, this.width, this.height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
GlStateManager._colorMask(true, true, true, true);
} else {
ShaderProgram shader = VeilRenderSystem.setShader(VeilShaders.BLIT_SCREEN);
if (shader == null) {
return;
}

ci.cancel();
RenderSystem.assertOnRenderThread();
GlStateManager._viewport(0, 0, width, height);
GlStateManager._colorMask(true, true, true, false);
GlStateManager._depthMask(false);
GlStateManager._disableDepthTest();
if (disableBlend) {
GlStateManager._disableBlend();
}

VeilRenderSystem.bindTextures(0, this.getColorTextureId());
shader.bind();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
ShaderProgram.unbind();

GlStateManager._colorMask(true, true, true, true);
GlStateManager._depthMask(true);
}
}

@Override
public void veil$clearColorBuffer(boolean clearError) {
RenderSystem.assertOnRenderThreadOrInit();
if (VeilRenderSystem.clearTextureSupported()) {
glClearTexImage(this.getColorTextureId(), 0, GL_RGBA, GL_FLOAT, this.clearChannels);
} else if (VeilRenderSystem.directStateAccessSupported()) {
glClearNamedFramebufferfv(this.getColorTextureId(), GL_COLOR, 0, this.clearChannels);
} else {
this.bindWrite(true);
GlStateManager._clearColor(this.clearChannels[0], this.clearChannels[1], this.clearChannels[2], this.clearChannels[3]);
GlStateManager._clear(GL_COLOR_BUFFER_BIT, clearError);
this.unbindWrite();
}

if (clearError) {
glGetError();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ public abstract class PipelineRenderTargetMixin implements RenderTargetExtension
@Shadow
public int viewHeight;

@Shadow
public abstract void bindWrite(boolean setViewport);

@Unique
private AdvancedFbo veil$wrapper;

Expand Down
1 change: 1 addition & 0 deletions common/src/main/resources/assets/veil/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"inspector.veil.device_info.opengl.feature_flag.sparse_buffers": "Sparse Buffers? %s",
"inspector.veil.device_info.opengl.feature_flag.direct_state_access": "Direct State Access? %s",
"inspector.veil.device_info.opengl.feature_flag.clear_texture": "Clear Texture? %s",
"inspector.veil.device_info.opengl.feature_flag.copy_image": "Copy Image? %s",
"inspector.veil.device_info.opengl.feature_flag.shader_storage_buffers": "Shader Storage Buffers? %s",
"inspector.veil.device_info.opengl.feature_flag.program_interface_query": "Program Interface Query? %s",

Expand Down
Loading

0 comments on commit 4cebe57

Please sign in to comment.