diff --git a/patches/com/mojang/blaze3d/resource/RenderTargetDescriptor.java.patch b/patches/com/mojang/blaze3d/resource/RenderTargetDescriptor.java.patch new file mode 100644 index 0000000000..f1e8f6f2c8 --- /dev/null +++ b/patches/com/mojang/blaze3d/resource/RenderTargetDescriptor.java.patch @@ -0,0 +1,23 @@ +--- a/com/mojang/blaze3d/resource/RenderTargetDescriptor.java ++++ b/com/mojang/blaze3d/resource/RenderTargetDescriptor.java +@@ -20,14 +_,18 @@ + } + + public void prepare(RenderTarget resource) { +- if (this.color != null && this.depth != null && this.color.clearColor != null && this.depth.clearColor != null) { ++ if (this.color != null && this.depth != null && this.color.clearColor != null && this.depth.clearColor != null && this.depth.format.hasDepthAspect()) { + RenderSystem.getDevice() + .createCommandEncoder() + .clearColorAndDepthTextures(resource.getColorTexture(), this.color.clearColor, resource.getDepthTexture(), this.depth.clearColor.x()); + } else if (this.color != null && this.color.clearColor != null) { + RenderSystem.getDevice().createCommandEncoder().clearColorTexture(resource.getColorTexture(), this.color.clearColor); +- } else if (this.depth != null && this.depth.clearColor != null) { ++ } else if (this.depth != null && this.depth.clearColor != null && this.depth.format.hasDepthAspect()) { + RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(resource.getDepthTexture(), this.depth.clearColor.x()); ++ } ++ if (this.depth != null && this.depth.clearColor != null && this.depth.format.hasStencilAspect()) { ++ int value = (int) (this.depth.format.hasDepthAspect() ? this.depth.clearColor.y() : this.depth.clearColor.x()); ++ RenderSystem.getDevice().createCommandEncoder().clearStencilTexture(resource.getDepthTexture(), value); + } + } + diff --git a/patches/com/mojang/renderpearl/backend/opengl/DirectStateAccess.java.patch b/patches/com/mojang/renderpearl/backend/opengl/DirectStateAccess.java.patch index eb9b067c3b..7bad71af45 100644 --- a/patches/com/mojang/renderpearl/backend/opengl/DirectStateAccess.java.patch +++ b/patches/com/mojang/renderpearl/backend/opengl/DirectStateAccess.java.patch @@ -5,38 +5,34 @@ public abstract int createFrameBufferObject(); - public abstract void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot); -+ public abstract void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot, boolean useStencil); ++ public abstract void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot, int stencil, int stencilMipLevel); + + public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot) { -+ this.bindFrameBufferTextures(fbo, color, colorMipLevels, depth, depthMipLevel, bindSlot, false); ++ this.bindFrameBufferTextures(fbo, color, colorMipLevels, depth, depthMipLevel, bindSlot, 0, 0); + } public void bindFrameBufferTextures(int fbo, int color, int depth, int mipLevel, int bindSlot) { - this.bindFrameBufferTextures(fbo, new int[]{color}, new int[]{mipLevel}, depth, mipLevel, bindSlot); -+ this.bindFrameBufferTextures(fbo, color, depth, mipLevel, bindSlot, false); ++ this.bindFrameBufferTextures(fbo, color, depth, mipLevel, bindSlot, 0, 0); + } + -+ public void bindFrameBufferTextures(int fbo, int color, int depth, int mipLevel, int bindSlot, boolean useStencil) { -+ this.bindFrameBufferTextures(fbo, new int[]{color}, new int[]{mipLevel}, depth, mipLevel, bindSlot, useStencil); ++ public void bindFrameBufferTextures(int fbo, int color, int depth, int mipLevel, int bindSlot, int stencil, int stencilMipLevel) { ++ this.bindFrameBufferTextures(fbo, new int[]{color}, new int[]{mipLevel}, depth, mipLevel, bindSlot, stencil, stencilMipLevel); } public abstract void blitFrameBuffers( -@@ -102,12 +_,17 @@ +@@ -102,12 +_,13 @@ } @Override - public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot) { -+ public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot, boolean useStencil) { ++ public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot, int stencil, int stencilMipLevel) { for (int i = 0; i < color.length; i++) { ARBDirectStateAccess.glNamedFramebufferTexture(fbo, 36064 + i, color[i], colorMipLevels[i]); } ARBDirectStateAccess.glNamedFramebufferTexture(fbo, 36096, depth, depthMipLevel); -+ if (useStencil) { -+ ARBDirectStateAccess.glNamedFramebufferTexture(fbo, GL33C.GL_STENCIL_ATTACHMENT, depth, depthMipLevel); -+ } else { -+ ARBDirectStateAccess.glNamedFramebufferTexture(fbo, GL33C.GL_STENCIL_ATTACHMENT, 0, 0); -+ } ++ ARBDirectStateAccess.glNamedFramebufferTexture(fbo, GL33C.GL_STENCIL_ATTACHMENT, stencil, stencilMipLevel); if (bindSlot != 0) { GlStateManager._glBindFramebuffer(bindSlot, fbo); } @@ -45,19 +41,15 @@ @Override - public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot) { -+ public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot, boolean useStencil) { ++ public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot, int stencil, int stencilMipLevel) { int tempBindSlot = bindSlot == 0 ? 36009 : bindSlot; int oldFbo = GlStateManager.getFrameBuffer(tempBindSlot); GlStateManager._glBindFramebuffer(tempBindSlot, fbo); -@@ -227,6 +_,11 @@ +@@ -227,6 +_,7 @@ } GlStateManager._glFramebufferTexture2D(tempBindSlot, 36096, 3553, depth, depthMipLevel); -+ if (useStencil) { -+ GlStateManager._glFramebufferTexture2D(tempBindSlot, GL33C.GL_STENCIL_ATTACHMENT, 3553, depth, depthMipLevel); -+ } else { -+ GlStateManager._glFramebufferTexture2D(tempBindSlot, GL33C.GL_STENCIL_ATTACHMENT, 3553, 0, 0); -+ } ++ GlStateManager._glFramebufferTexture2D(tempBindSlot, GL33C.GL_STENCIL_ATTACHMENT, 3553, stencil, stencilMipLevel); if (bindSlot == 0) { GlStateManager._glBindFramebuffer(tempBindSlot, oldFbo); } diff --git a/patches/com/mojang/renderpearl/backend/opengl/FrameBufferCache.java.patch b/patches/com/mojang/renderpearl/backend/opengl/FrameBufferCache.java.patch index 629d523e80..4911b76422 100644 --- a/patches/com/mojang/renderpearl/backend/opengl/FrameBufferCache.java.patch +++ b/patches/com/mojang/renderpearl/backend/opengl/FrameBufferCache.java.patch @@ -1,11 +1,10 @@ --- a/com/mojang/renderpearl/backend/opengl/FrameBufferCache.java +++ b/com/mojang/renderpearl/backend/opengl/FrameBufferCache.java -@@ -51,7 +_,7 @@ - } +@@ -52,6 +_,7 @@ dsa.bindFrameBufferTextures( -- fbo, colorIds, mipLevels, depthAttachment == null ? 0 : depthAttachment.glId(), depthAttachment == null ? 0 : depthAttachment.fboMipLevel(), 0 -+ fbo, colorIds, mipLevels, depthAttachment == null ? 0 : depthAttachment.glId(), depthAttachment == null ? 0 : depthAttachment.fboMipLevel(), 0, depthAttachment != null && depthAttachment.hasStencilAspect() + fbo, colorIds, mipLevels, depthAttachment == null ? 0 : depthAttachment.glId(), depthAttachment == null ? 0 : depthAttachment.fboMipLevel(), 0 ++ , depthAttachment != null && depthAttachment.hasStencilAspect() ? depthAttachment.glId() : 0, depthAttachment != null && depthAttachment.hasStencilAspect() ? depthAttachment.fboMipLevel() : 0 ); return fbo; } diff --git a/patches/com/mojang/renderpearl/backend/opengl/GlCommandEncoder.java.patch b/patches/com/mojang/renderpearl/backend/opengl/GlCommandEncoder.java.patch index 91870e12e1..f5ecc0f256 100644 --- a/patches/com/mojang/renderpearl/backend/opengl/GlCommandEncoder.java.patch +++ b/patches/com/mojang/renderpearl/backend/opengl/GlCommandEncoder.java.patch @@ -1,27 +1,23 @@ --- a/com/mojang/renderpearl/backend/opengl/GlCommandEncoder.java +++ b/com/mojang/renderpearl/backend/opengl/GlCommandEncoder.java -@@ -262,8 +_,9 @@ - GlStateManager._depthMask(true); - GlStateManager._disableScissorTest(); - -+ boolean hasStencil = depthTexture.getFormat().hasStencilAspect(); - for (int i = 0; i < depthTexture.getMipLevels(); i++) { -- this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)depthTexture).id, i, 36160); -+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)depthTexture).id, i, 36160, hasStencil); - GL33C.glDrawBuffer(0); - GlStateManager._clear(256); - } -@@ -274,6 +_,17 @@ +@@ -274,6 +_,24 @@ } @Override + public void clearStencilTexture(GpuTexture texture, int value) { -+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)texture).id, 0, GlConst.GL_FRAMEBUFFER, true); -+ GL33C.glDrawBuffer(GlConst.GL_NONE); + GL33C.glClearStencil(value); ++ GlStateManager._stencilMask(-1); + GlStateManager._depthMask(true); -+ GlStateManager._clear(GL33C.GL_STENCIL_BUFFER_BIT); ++ GlStateManager._disableScissorTest(); ++ ++ for (int i = 0; i < texture.getMipLevels(); i++) { ++ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, 0, 0, GlConst.GL_FRAMEBUFFER, ((GlTexture)texture).id, i); ++ GL33C.glDrawBuffer(GlConst.GL_NONE); ++ GlStateManager._clear(GL33C.GL_STENCIL_BUFFER_BIT); ++ } ++ + GL33C.glDrawBuffer(GlConst.GL_COLOR_ATTACHMENT0); ++ GlStateManager._glFramebufferTexture2D(GlConst.GL_FRAMEBUFFER, GL33C.GL_STENCIL_ATTACHMENT, GlConst.GL_TEXTURE_2D, 0, 0); + GlStateManager._glBindFramebuffer(GlConst.GL_FRAMEBUFFER, 0); + } + @@ -36,8 +32,8 @@ - this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, isDepth ? 0 : sourceId, isDepth ? sourceId : 0, mipLevel, 0); - this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, isDepth ? 0 : destId, isDepth ? destId : 0, mipLevel, 0); + boolean hasStencil = source.getFormat().hasStencilAspect(); -+ this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, isDepth ? 0 : sourceId, isDepth ? sourceId : 0, 0, 0, hasStencil); -+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, isDepth ? 0 : destId, isDepth ? destId : 0, 0, 0, hasStencil); ++ this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, (isDepth || hasStencil) ? 0 : sourceId, isDepth ? sourceId : 0, 0, 0, hasStencil ? sourceId : 0, 0); ++ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, (isDepth || hasStencil) ? 0 : destId, isDepth ? destId : 0, 0, 0, hasStencil ? destId : 0, 0); + int bufferMask = 0; + if (source.getFormat().hasColorAspect()) { + bufferMask |= GlConst.GL_COLOR_BUFFER_BIT; diff --git a/patches/com/mojang/renderpearl/backend/vulkan/VulkanCommandEncoder.java.patch b/patches/com/mojang/renderpearl/backend/vulkan/VulkanCommandEncoder.java.patch index 84e8c758db..6bb775a312 100644 --- a/patches/com/mojang/renderpearl/backend/vulkan/VulkanCommandEncoder.java.patch +++ b/patches/com/mojang/renderpearl/backend/vulkan/VulkanCommandEncoder.java.patch @@ -1,8 +1,10 @@ --- a/com/mojang/renderpearl/backend/vulkan/VulkanCommandEncoder.java +++ b/com/mojang/renderpearl/backend/vulkan/VulkanCommandEncoder.java -@@ -320,11 +_,21 @@ +@@ -319,12 +_,24 @@ + depthAttachmentInfo.loadOp(0); } ++ if (depthAttachment.textureView().texture().getFormat().hasDepthAspect()) renderingInfo.pDepthAttachment(depthAttachmentInfo); + + if (vulkanDepthAttachment.texture().getFormat().hasStencilAspect()) { @@ -16,10 +18,11 @@ } KHRDynamicRendering.vkCmdBeginRenderingKHR(this.commandBuffer(), renderingInfo); ++ boolean hasDepth = depthAttachment != null && depthAttachment.textureView().texture().getFormat().hasDepthAspect(); + boolean hasStencil = depthAttachment != null && depthAttachment.textureView().texture().getFormat().hasStencilAspect(); this.currentRenderPass = new VulkanRenderPass( - this.device, this, this.commandBuffer(), this.checkpointStorage, renderArea, width, height, depthAttachment != null, descriptor.label() -+ this.device, this, this.commandBuffer(), this.checkpointStorage, renderArea, width, height, depthAttachment != null, hasStencil, descriptor.label() ++ this.device, this, this.commandBuffer(), this.checkpointStorage, renderArea, width, height, hasDepth, hasStencil, descriptor.label() ); } diff --git a/patches/com/mojang/renderpearl/backend/vulkan/VulkanGpuTexture.java.patch b/patches/com/mojang/renderpearl/backend/vulkan/VulkanGpuTexture.java.patch new file mode 100644 index 0000000000..01a5c30d9f --- /dev/null +++ b/patches/com/mojang/renderpearl/backend/vulkan/VulkanGpuTexture.java.patch @@ -0,0 +1,12 @@ +--- a/com/mojang/renderpearl/backend/vulkan/VulkanGpuTexture.java ++++ b/com/mojang/renderpearl/backend/vulkan/VulkanGpuTexture.java +@@ -63,7 +_,8 @@ + barrier.dstQueueFamilyIndex(-1); + barrier.image(this.vkImage); + VkImageSubresourceRange subresourceRange = barrier.subresourceRange(); +- subresourceRange.aspectMask(this.getFormat().hasColorAspect() ? 1 : 2); ++ // Neo: respect stencil aspect in aspect mask ++ subresourceRange.aspectMask(VulkanConst.formatAspectMask(this.getFormat())); + subresourceRange.baseMipLevel(0); + subresourceRange.levelCount(this.getMipLevels()); + subresourceRange.baseArrayLayer(0); diff --git a/patches/com/mojang/renderpearl/backend/vulkan/VulkanGpuTextureView.java.patch b/patches/com/mojang/renderpearl/backend/vulkan/VulkanGpuTextureView.java.patch new file mode 100644 index 0000000000..3a9de7daa2 --- /dev/null +++ b/patches/com/mojang/renderpearl/backend/vulkan/VulkanGpuTextureView.java.patch @@ -0,0 +1,12 @@ +--- a/com/mojang/renderpearl/backend/vulkan/VulkanGpuTextureView.java ++++ b/com/mojang/renderpearl/backend/vulkan/VulkanGpuTextureView.java +@@ -26,7 +_,8 @@ + imageViewCreateInfo.viewType(isCubemap ? 3 : 1); + imageViewCreateInfo.format(VulkanConst.toVk(texture.getFormat())); + VkImageSubresourceRange subresourceRange = imageViewCreateInfo.subresourceRange(); +- subresourceRange.aspectMask(texture.getFormat().hasColorAspect() ? 1 : 2); ++ // Neo: respect stencil aspect in aspect mask ++ subresourceRange.aspectMask(VulkanConst.formatAspectMask(texture.getFormat())); + subresourceRange.baseMipLevel(baseMipLevel); + subresourceRange.levelCount(mipLevels); + subresourceRange.baseArrayLayer(0); diff --git a/patches/com/mojang/renderpearl/backend/vulkan/VulkanRenderPass.java.patch b/patches/com/mojang/renderpearl/backend/vulkan/VulkanRenderPass.java.patch index fa2eabe926..150b81c030 100644 --- a/patches/com/mojang/renderpearl/backend/vulkan/VulkanRenderPass.java.patch +++ b/patches/com/mojang/renderpearl/backend/vulkan/VulkanRenderPass.java.patch @@ -29,7 +29,7 @@ this.uniforms.clear(); this.uniforms.size(vulkanRenderPipeline.uniforms().size()); + if (this.hasStencil) { -+ VK12.vkCmdBindPipeline(this.commandBuffer(), VK12.VK_PIPELINE_BIND_POINT_GRAPHICS, this.pipeline.withDepthStencilPipeline()); ++ VK12.vkCmdBindPipeline(this.commandBuffer(), VK12.VK_PIPELINE_BIND_POINT_GRAPHICS, this.hasDepth ? this.pipeline.withDepthStencilPipeline() : this.pipeline.withStencilPipeline()); + return; + } VK12.vkCmdBindPipeline(this.commandBuffer(), 0, this.hasDepth ? this.pipeline.withDepthPipeline() : this.pipeline.withoutDepthPipeline()); diff --git a/patches/com/mojang/renderpearl/backend/vulkan/VulkanRenderPipeline.java.patch b/patches/com/mojang/renderpearl/backend/vulkan/VulkanRenderPipeline.java.patch index 3a7c2d9584..4db2f4bc03 100644 --- a/patches/com/mojang/renderpearl/backend/vulkan/VulkanRenderPipeline.java.patch +++ b/patches/com/mojang/renderpearl/backend/vulkan/VulkanRenderPipeline.java.patch @@ -1,25 +1,28 @@ --- a/com/mojang/renderpearl/backend/vulkan/VulkanRenderPipeline.java +++ b/com/mojang/renderpearl/backend/vulkan/VulkanRenderPipeline.java -@@ -41,6 +_,7 @@ +@@ -41,6 +_,8 @@ @OnlyIn(Dist.CLIENT) public final class VulkanRenderPipeline implements BackendRenderPipeline, Destroyable { private final VulkanDevice device; ++ private final long withStencilPipeline; + private final long withDepthStencilPipeline; private final long withDepthPipeline; private final long withoutDepthPipeline; private final long pipelineLayout; -@@ -51,6 +_,7 @@ +@@ -51,6 +_,8 @@ public VulkanRenderPipeline( VulkanDevice device, ++ long withStencilPipeline, + long withDepthStencilPipeline, long withDepthPipeline, long withoutDepthPipeline, long pipelineLayout, -@@ -59,6 +_,7 @@ +@@ -59,6 +_,8 @@ List uniforms ) { this.device = device; ++ this.withStencilPipeline = withStencilPipeline; + this.withDepthStencilPipeline = withDepthStencilPipeline; this.withDepthPipeline = withDepthPipeline; this.withoutDepthPipeline = withoutDepthPipeline; @@ -52,40 +55,47 @@ } List colorTargetStates = pipelineCreateInfo.colorTargetStates(); -@@ -289,6 +_,7 @@ +@@ -289,7 +_,7 @@ long withDepthPipeline = pointer.get(0); device.instance().debug().setObjectName(device.vkDevice(), 19, withDepthPipeline, () -> "Pipeline " + pipelineCreateInfo.name()); long withoutDepthPipeline; -+ long withDepthStencilPipeline = 0L; - if (depthStencilState == null) { +- if (depthStencilState == null) { ++ if (true) { renderingInfo.depthAttachmentFormat(0); VulkanUtils.crashIfFailure( -@@ -300,10 +_,18 @@ - device.instance().debug().setObjectName(device.vkDevice(), 19, withoutDepthPipeline, () -> "Pipeline " + pipelineCreateInfo.name()); - } else { + device, +@@ -302,8 +_,20 @@ withoutDepthPipeline = 0L; -+ -+ if (depthStencilState.stencilTest() != null) { -+ renderingInfo.depthAttachmentFormat(VK12.VK_FORMAT_D32_SFLOAT_S8_UINT); -+ renderingInfo.stencilAttachmentFormat(VK12.VK_FORMAT_D32_SFLOAT_S8_UINT); -+ VulkanUtils.crashIfFailure(device, VK12.vkCreateGraphicsPipelines(device.vkDevice(), 0L, createInfo, null, pointer), "Can't compile pipeline " + pipelineCreateInfo.name()); -+ withDepthStencilPipeline = pointer.get(0); -+ device.instance().debug().setObjectName(device.vkDevice(), VK12.VK_OBJECT_TYPE_PIPELINE, withDepthStencilPipeline, () -> "Pipeline " + pipelineCreateInfo.name()); -+ } } ++ renderingInfo.depthAttachmentFormat(VK12.VK_FORMAT_D32_SFLOAT_S8_UINT); ++ renderingInfo.stencilAttachmentFormat(VK12.VK_FORMAT_D32_SFLOAT_S8_UINT); ++ VulkanUtils.crashIfFailure(device, VK12.vkCreateGraphicsPipelines(device.vkDevice(), 0L, createInfo, null, pointer), "Can't compile pipeline " + pipelineCreateInfo.name()); ++ long withDepthStencilPipeline = pointer.get(0); ++ device.instance().debug().setObjectName(device.vkDevice(), VK12.VK_OBJECT_TYPE_PIPELINE, withDepthStencilPipeline, () -> "Pipeline " + pipelineCreateInfo.name()); ++ ++ renderingInfo.depthAttachmentFormat(VK12.VK_FORMAT_UNDEFINED); ++ renderingInfo.stencilAttachmentFormat(VK12.VK_FORMAT_S8_UINT); ++ VulkanUtils.crashIfFailure(device, VK12.vkCreateGraphicsPipelines(device.vkDevice(), 0L, createInfo, null, pointer), "Can't compile pipeline " + pipelineCreateInfo.name()); ++ long withStencilPipeline = pointer.get(0); ++ device.instance().debug().setObjectName(device.vkDevice(), VK12.VK_OBJECT_TYPE_PIPELINE, withDepthStencilPipeline, () -> "Pipeline " + pipelineCreateInfo.name()); ++ return new VulkanRenderPipeline( - device, withDepthPipeline, withoutDepthPipeline, pipelineLayout, descriptorSetLayout, compiledShaderModules, pipelineCreateInfo.uniforms() -+ device, withDepthStencilPipeline, withDepthPipeline, withoutDepthPipeline, pipelineLayout, descriptorSetLayout, compiledShaderModules, pipelineCreateInfo.uniforms() ++ device, withStencilPipeline, withDepthStencilPipeline, withDepthPipeline, withoutDepthPipeline, pipelineLayout, descriptorSetLayout, compiledShaderModules, pipelineCreateInfo.uniforms() ); } } -@@ -334,6 +_,10 @@ +@@ -334,6 +_,14 @@ public VulkanDevice device() { return this.device; + } + ++ public long withStencilPipeline() { ++ return this.withStencilPipeline; ++ } ++ + public long withDepthStencilPipeline() { + return this.withDepthStencilPipeline; } diff --git a/tests/src/main/java/net/neoforged/neoforge/oldtest/client/rendering/StencilEnableTest.java b/tests/src/main/java/net/neoforged/neoforge/oldtest/client/rendering/StencilEnableTest.java index a4f8b765e2..b4b9e1d6fd 100644 --- a/tests/src/main/java/net/neoforged/neoforge/oldtest/client/rendering/StencilEnableTest.java +++ b/tests/src/main/java/net/neoforged/neoforge/oldtest/client/rendering/StencilEnableTest.java @@ -5,38 +5,21 @@ package net.neoforged.neoforge.oldtest.client.rendering; -import com.mojang.blaze3d.platform.Lighting; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.renderpearl.api.pipeline.CompareOp; import com.mojang.renderpearl.api.pipeline.DepthStencilState; +import com.mojang.renderpearl.api.pipeline.RenderPipeline; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.navigation.ScreenRectangle; -import net.minecraft.client.gui.render.pip.PictureInPictureRenderer; -import net.minecraft.client.renderer.SubmitNodeCollector; -import net.minecraft.client.renderer.feature.FeatureRenderDispatcher; -import net.minecraft.client.renderer.item.ItemModelResolver; -import net.minecraft.client.renderer.item.TrackingItemStackRenderState; -import net.minecraft.client.renderer.state.gui.pip.PictureInPictureRenderState; -import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.resources.Identifier; -import net.minecraft.resources.ResourceKey; -import net.minecraft.util.LightCoordsUtil; -import net.minecraft.world.item.ItemDisplayContext; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Blocks; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.common.Mod; import net.neoforged.neoforge.client.event.ConfigureMainRenderTargetEvent; import net.neoforged.neoforge.client.event.RegisterGuiLayersEvent; -import net.neoforged.neoforge.client.event.RegisterPictureInPictureRenderersEvent; -import net.neoforged.neoforge.client.pipeline.PipelineModifier; -import net.neoforged.neoforge.client.pipeline.RegisterPipelineModifiersEvent; import net.neoforged.neoforge.client.stencil.StencilOperation; import net.neoforged.neoforge.client.stencil.StencilPerFaceTest; import net.neoforged.neoforge.client.stencil.StencilTest; -import org.jspecify.annotations.Nullable; /** * Basic test that uses the stencil buffer. @@ -60,8 +43,31 @@ public class StencilEnableTest { private static final State ENABLED = State.ENABLE_REGISTRATION; - private static final ResourceKey STENCIL_FILL_KEY = ResourceKey.create(PipelineModifier.MODIFIERS_KEY, Identifier.fromNamespaceAndPath(MOD_ID, "stencil_fill")); - private static final ResourceKey STENCIL_APPLY_KEY = ResourceKey.create(PipelineModifier.MODIFIERS_KEY, Identifier.fromNamespaceAndPath(MOD_ID, "stencil_apply")); + private static final RenderPipeline GUI_TEXTURED_STENCIL_FILL = RenderPipelines.GUI_TEXTURED.toBuilder() + .withLocation(Identifier.fromNamespaceAndPath(MOD_ID, "pipeline/gui_textured_stencil_fill")) + .withDepthStencilState(new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, true, 0F, 0F, new StencilTest( + new StencilPerFaceTest( + StencilOperation.KEEP, + StencilOperation.KEEP, + StencilOperation.REPLACE, + CompareOp.ALWAYS_PASS), + 0xFF, + 0xFF, + 1))) + .build(); + private static final RenderPipeline GUI_STENCIL_APPLY = RenderPipelines.GUI.toBuilder() + .withLocation(Identifier.fromNamespaceAndPath(MOD_ID, "pipeline/gui_textured_stencil_apply")) + .withDepthStencilState(new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, true, 0F, 0F, new StencilTest( + new StencilPerFaceTest( + StencilOperation.KEEP, + StencilOperation.KEEP, + StencilOperation.KEEP, + CompareOp.NOT_EQUAL), + 0xFF, + 0, + 1))) + .build(); + private static final Identifier MASK_TEXTURE = Identifier.withDefaultNamespace("textures/gui/sprites/icon/new_realm.png"); public StencilEnableTest(IEventBus modEventBus) { if (ENABLED == State.DISABLE) { @@ -70,137 +76,20 @@ public class StencilEnableTest { modEventBus.addListener(ConfigureMainRenderTargetEvent.class, event -> { event.enableStencil(); }); - modEventBus.addListener(RegisterPipelineModifiersEvent.class, event -> { - event.register(STENCIL_FILL_KEY, (pipeline, name) -> pipeline.toBuilder() - .withLocation(name) - .withDepthStencilState(new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, true, 0F, 0F, new StencilTest( - new StencilPerFaceTest( - StencilOperation.KEEP, - StencilOperation.KEEP, - StencilOperation.REPLACE, - CompareOp.ALWAYS_PASS), - 0xFF, - 0xFF, - 1))) - .build()); - event.register(STENCIL_APPLY_KEY, (pipeline, name) -> pipeline.toBuilder() - .withLocation(name) - .withDepthStencilState(new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, true, 0F, 0F, new StencilTest( - new StencilPerFaceTest( - StencilOperation.KEEP, - StencilOperation.KEEP, - StencilOperation.KEEP, - CompareOp.NOT_EQUAL), - 0xFF, - 0, - 1))) - .build()); - }); - modEventBus.addListener(RegisterPictureInPictureRenderersEvent.class, event -> { - if (ENABLED != State.ENABLE_UI_LAYER) { - return; - } - event.register(StenciledItemPictureInPictureRenderState.class, StenciledItemPictureInPictureRenderer::new); - }); modEventBus.addListener(RegisterGuiLayersEvent.class, event -> { if (ENABLED != State.ENABLE_UI_LAYER) { return; } event.registerAboveAll( - Identifier.fromNamespaceAndPath(MOD_ID, "block_outline"), + Identifier.fromNamespaceAndPath(MOD_ID, "stenciled_ui_element"), (guiGraphics, _) -> { - ItemModelResolver itemModelResolver = Minecraft.getInstance().getItemModelResolver(); - - TrackingItemStackRenderState maskState = new TrackingItemStackRenderState(); - itemModelResolver.updateForTopItem(maskState, new ItemStack(Blocks.GRASS_BLOCK), ItemDisplayContext.GUI, null, null, 0); - TrackingItemStackRenderState maskedState = new TrackingItemStackRenderState(); - itemModelResolver.updateForTopItem(maskedState, new ItemStack(Blocks.DIAMOND_BLOCK), ItemDisplayContext.GUI, null, null, 0); + RenderSystem.getDevice().createCommandEncoder().clearStencilTexture(Minecraft.getInstance().gameRenderer.mainRenderTarget().getDepthTexture(), 0); int maxX = guiGraphics.guiWidth(); - guiGraphics.submitPictureInPictureRenderState(new StenciledItemPictureInPictureRenderState( - maskState, - maskedState, - maxX - 50, 10, maxX - 10, 50, - 16F, - guiGraphics.peekScissorStack())); + guiGraphics.blit(GUI_TEXTURED_STENCIL_FILL, MASK_TEXTURE, maxX - 100, 10, 0, 0, 40, 20, 40, 20, 0x01FFFFFF); + guiGraphics.nextStratum(); + guiGraphics.fill(GUI_STENCIL_APPLY, maxX - 100, 10, maxX - 60, 30, 0xFF0000AA); }); }); } - - // FIXME: it is no longer possible to render twice in a PiP - private static final class StenciledItemPictureInPictureRenderer extends PictureInPictureRenderer { - @Override - protected void renderToTexture(StenciledItemPictureInPictureRenderState state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector) { - Minecraft.getInstance().gameRenderer.lighting().setupFor(Lighting.Entry.ITEMS_3D); - poseStack.scale(1, -1, -1); - float scale = state.scale; - FeatureRenderDispatcher dispatcher = Minecraft.getInstance().gameRenderer.featureRenderDispatcher(); - RenderSystem.pushPipelineModifier(STENCIL_FILL_KEY); - { - state.maskRenderState.submit(poseStack, submitNodeCollector, LightCoordsUtil.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, 0); - - poseStack.pushPose(); - poseStack.translate(10F / scale, -10F / scale, 0); - state.maskRenderState.submit(poseStack, submitNodeCollector, LightCoordsUtil.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, 0); - poseStack.popPose(); - - //dispatcher.renderAllFeatures((SubmitNodeStorage) submitNodeCollector); - } - RenderSystem.popPipelineModifier(); - - RenderSystem.pushPipelineModifier(STENCIL_APPLY_KEY); - { - poseStack.scale(1.1F, 1.1F, 1.1F); - poseStack.translate(-.5F / scale, .5F / scale, 0); - - state.maskedRenderState.submit(poseStack, submitNodeCollector, LightCoordsUtil.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, 0); - - poseStack.pushPose(); - poseStack.translate(10F / scale, -10F / scale, 0); - state.maskedRenderState.submit(poseStack, submitNodeCollector, LightCoordsUtil.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, 0); - poseStack.popPose(); - - //dispatcher.renderAllFeatures((SubmitNodeStorage) submitNodeCollector); - } - RenderSystem.popPipelineModifier(); - } - - @Override - protected float getTranslateY(int height, int guiScale) { - return height / 2F; - } - - @Override - public Class getRenderStateClass() { - return StenciledItemPictureInPictureRenderState.class; - } - - @Override - protected String getTextureLabel() { - return "stencil enable test"; - } - } - - private record StenciledItemPictureInPictureRenderState( - TrackingItemStackRenderState maskRenderState, - TrackingItemStackRenderState maskedRenderState, - int x0, - int y0, - int x1, - int y1, - float scale, - @Nullable ScreenRectangle bounds, - @Nullable ScreenRectangle scissorArea) implements PictureInPictureRenderState { - public StenciledItemPictureInPictureRenderState( - TrackingItemStackRenderState maskRenderState, - TrackingItemStackRenderState maskedRenderState, - int x0, - int y0, - int x1, - int y1, - float scale, - @Nullable ScreenRectangle scissorArea) { - this(maskRenderState, maskedRenderState, x0, y0, x1, y1, scale, PictureInPictureRenderState.getBounds(x0, y0, x1, y1, scissorArea), scissorArea); - } - } }