Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Native Wayland Support #291

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/main/java/net/vulkanmod/config/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import com.mojang.blaze3d.platform.Window;
import net.minecraft.client.*;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.contents.LiteralContents;
import net.minecraft.network.chat.contents.TranslatableContents;
import net.vulkanmod.Initializer;
import net.vulkanmod.vulkan.Drawer;
import net.vulkanmod.vulkan.Renderer;
import net.vulkanmod.vulkan.Vulkan;

public class Options {

//Fix Glitches+Crashes if Wayland and the Mesa RADV driver are used, and Queue Frames is set above 2 (possible RADV Bug?)
private static final boolean limitSwapChain = VideoResolution.isWayLand() && Vulkan.getDeviceInfo().isAMD();
static net.minecraft.client.Options minecraftOptions = Minecraft.getInstance().options;
static Config config = Initializer.CONFIG;
static Window window = Minecraft.getInstance().getWindow();
Expand Down Expand Up @@ -51,9 +53,7 @@ public static Option<?>[] getVideoOpts() {
new SwitchOption("VSync",
value -> {
minecraftOptions.enableVsync().set(value);
if (Minecraft.getInstance().getWindow() != null) {
Minecraft.getInstance().getWindow().updateVsync(value);
}
Minecraft.getInstance().getWindow().updateVsync(value);
},
() -> minecraftOptions.enableVsync().get()),
new CyclingOption<>("Gui Scale",
Expand Down Expand Up @@ -171,7 +171,7 @@ public static Option<?>[] getGraphicsOpts() {
public static Option<?>[] getOtherOpts() {
return new Option[] {
new RangeOption("Queue Frames", 2,
5, 1,
limitSwapChain ? 2 : 5, 1,
value -> {
config.frameQueueSize = value;
Renderer.scheduleSwapChainUpdate();
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/net/vulkanmod/config/VideoResolution.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,20 @@
import java.util.List;
import java.util.Optional;

import static net.vulkanmod.Initializer.LOGGER;
import static org.lwjgl.glfw.GLFW.*;

public class VideoResolution {
private static VideoResolution[] videoResolutions;

//Make sure Wayland is ALWAYS preferred in 100% of cases (and only fallback to X11 if Wayland isn't available)
private static final int[] plats = new int[]{
GLFW_PLATFORM_WIN32,
GLFW_PLATFORM_WAYLAND,
GLFW_PLATFORM_X11};

private static final int activePlat = getSupportedPlat();

int width;
int height;
int refreshRate;
Expand Down Expand Up @@ -49,13 +60,43 @@ public int[] refreshRates() {

return arr;
}
//Prioritise Wayland over X11 if xWayland (if correct) is present

public static void init() {
RenderSystem.assertOnRenderThread();
GLFW.glfwInitHint(GLFW_PLATFORM, activePlat);
GLFW.glfwInit();
videoResolutions = populateVideoResolutions(GLFW.glfwGetPrimaryMonitor());
}

private static int getSupportedPlat() {

for (int plat : plats) {
if(GLFW.glfwPlatformSupported(plat))
{
LOGGER.info("Selecting Platform: "+getStringFromPlat(plat));
return plat;
}
}
throw new RuntimeException("No Supported Platforms Present!");
}

private static String getStringFromPlat(int plat) {
return switch (plat)
{
case GLFW_PLATFORM_WIN32 -> "WIN32";
case GLFW_PLATFORM_WAYLAND -> "WAYLAND";
case GLFW_PLATFORM_X11 -> "X11";
default -> throw new IllegalStateException("Unexpected value: " + plat);
};
}

public static int getActivePlat() { return activePlat; }
//Allows platform specific checks to be handles (is missing macOS, however that may not be important due to macOS only version))
public static boolean isWayLand() { return activePlat == GLFW_PLATFORM_WAYLAND; }
public static boolean isX11() { return activePlat == GLFW_PLATFORM_X11; }
public static boolean isWindows() { return activePlat == GLFW_PLATFORM_WIN32; }

public static VideoResolution[] getVideoResolutions() {
return videoResolutions;
}
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/net/vulkanmod/mixin/InputConstantsM.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package net.vulkanmod.mixin;

import com.mojang.blaze3d.platform.InputConstants;
import net.vulkanmod.config.VideoResolution;
import org.lwjgl.glfw.*;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(InputConstants.class)
public class InputConstantsM {
/**
* @author
* @reason
*/
@Overwrite
public static void grabOrReleaseMouse(long l, int i, double d, double e) {
if (!VideoResolution.isWayLand()) GLFW.glfwSetCursorPos(l, d, e);
GLFW.glfwSetInputMode(l, 208897, i);
}
}
2 changes: 1 addition & 1 deletion src/main/java/net/vulkanmod/mixin/debug/GlDebugInfoM.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class GlDebugInfoM {
*/
@Overwrite
public static String getVendor() {
return Vulkan.getDeviceInfo() != null ? Vulkan.getDeviceInfo().vendorId : "n/a";
return Vulkan.getDeviceInfo() != null ? Vulkan.getDeviceInfo().vendorIdString : "n/a";
}

/**
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/net/vulkanmod/mixin/render/MinecraftMixin.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package net.vulkanmod.mixin.render;

import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.platform.IconSet;
import com.mojang.blaze3d.platform.Window;
import com.mojang.blaze3d.systems.TimerQuery;
import net.minecraft.SharedConstants;
import net.minecraft.Util;
import net.minecraft.client.GraphicsStatus;
import net.minecraft.client.Minecraft;
Expand All @@ -18,7 +20,11 @@
import net.minecraft.client.resources.PaintingTextureManager;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.sounds.SoundManager;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.VanillaPackResources;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import net.vulkanmod.config.VideoResolution;
import net.vulkanmod.render.texture.SpriteUtil;
import net.vulkanmod.Initializer;
import net.vulkanmod.render.profiling.Profiler2;
import net.vulkanmod.render.texture.SpriteUtil;
Expand All @@ -36,6 +42,7 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;

import java.io.IOException;
import java.util.Optional;

@Mixin(Minecraft.class)
Expand Down Expand Up @@ -67,6 +74,8 @@ private void forceGraphicsMode(GameConfig gameConfig, CallbackInfo ci) {
}
}

@Shadow @Final private VanillaPackResources vanillaPackResources;

@Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;clear(IZ)V"))
private void beginRender(int i, boolean bl) {
Renderer renderer = Renderer.getInstance();
Expand All @@ -82,6 +91,14 @@ private void submitRender(boolean tick, CallbackInfo ci) {
p.pop();
}

@Redirect(method="<init>", at=@At(value="INVOKE", target="Lcom/mojang/blaze3d/platform/Window;setIcon(Lnet/minecraft/server/packs/PackResources;Lcom/mojang/blaze3d/platform/IconSet;)V"))
private void bypassWaylandIcon(Window instance, PackResources packResources, IconSet iconSet) throws IOException {
if(!VideoResolution.isWayLand())
{
this.window.setIcon(this.vanillaPackResources, SharedConstants.getCurrentVersion().isStable() ? IconSet.RELEASE : IconSet.SNAPSHOT);
}
}

@Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/pipeline/RenderTarget;bindWrite(Z)V"))
private void redirectMainTarget1(RenderTarget instance, boolean bl) {
}
Expand Down
18 changes: 16 additions & 2 deletions src/main/java/net/vulkanmod/vulkan/DeviceInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public class DeviceInfo {
public static final List<GraphicsCard> graphicsCards;

private final VkPhysicalDevice device;
public final String vendorId;
public final int vendorId;
public final String vendorIdString;
public final String deviceName;
public final String driverVersion;
public final String vkVersion;
Expand Down Expand Up @@ -57,7 +58,8 @@ public DeviceInfo(VkPhysicalDevice device, VkPhysicalDeviceProperties properties
}

this.device = device;
this.vendorId = decodeVendor(properties.vendorID());
this.vendorId = properties.vendorID();
this.vendorIdString = decodeVendor(this.vendorId);
this.deviceName = properties.deviceNameString();
this.driverVersion = decodeDvrVersion(Device.deviceProperties.driverVersion(), Device.deviceProperties.vendorID());
this.vkVersion = decDefVersion(getVkVer());
Expand Down Expand Up @@ -185,4 +187,16 @@ public static String debugString(PointerBuffer ppPhysicalDevices, Set<String> re
public boolean isDrawIndirectSupported() {
return drawIndirectSupported;
}

//Added these to allow GPU and vendor specific fixes to be applied
// (e.g. if we run into a bug that only occurs on a specific GPU, and only on Wayland for example e.g.)
public boolean isAMD() {
return this.vendorId==0x1022;
}
public boolean isNvidia() {
return this.vendorId==0x10DE;
}
public boolean isIntel() {
return this.vendorId==0x8086;
}
}
6 changes: 4 additions & 2 deletions src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.vulkanmod.vulkan.Renderer;
import net.vulkanmod.vulkan.Synchronization;
import net.vulkanmod.vulkan.Vulkan;
import net.vulkanmod.config.VideoResolution;
import net.vulkanmod.vulkan.queue.Queue;
import net.vulkanmod.vulkan.texture.VulkanImage;
import org.lwjgl.system.MemoryStack;
Expand Down Expand Up @@ -34,8 +35,9 @@ public static int getDefaultDepthFormat() {
}

private RenderPass renderPass;
//Necessary until tearing-control-unstable-v1 is fully implemented on all GPU Drivers for Wayland
private static final int defUncappedMode = VideoResolution.isWayLand() ? VK_PRESENT_MODE_MAILBOX_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR;
private long[] framebuffers;

private long swapChain = VK_NULL_HANDLE;
private List<VulkanImage> swapChainImages;
private VkExtent2D extent2D;
Expand Down Expand Up @@ -353,7 +355,7 @@ private VkSurfaceFormatKHR getFormat(VkSurfaceFormatKHR.Buffer availableFormats)
}

private int getPresentMode(IntBuffer availablePresentModes) {
int requestedMode = vsync ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR;
int requestedMode = vsync ? VK_PRESENT_MODE_FIFO_KHR : defUncappedMode;

//fifo mode is the only mode that has to be supported
if(requestedMode == VK_PRESENT_MODE_FIFO_KHR)
Expand Down
37 changes: 17 additions & 20 deletions src/main/resources/vulkanmod.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,25 @@
"mixins": [
],
"client": [
"InputConstantsM",
"WindowMixin",
"chunk.DirectionMixin",
"chunk.FrustumMixin",
"chunk.LevelRendererMixin",
"chunk.VisibilitySetMixin",

"compatibility.gl.GL11M",
"compatibility.EffectInstanceM",
"compatibility.ProgramM",
"compatibility.UniformM",

"compatibility.gl.GL11M",
"debug.ChunkBorderRendererM",
"debug.GlDebugInfoM",
"debug.KeyboardHandlerM",

"gui.ChatComponentM",
"gui.DebugHudM",
"gui.GuiM",

"matrix.Matrix4fM",

"profiling.GuiMixin",
"profiling.KeyboardHandlerM",

"render.entity.EntityRendererM",
"render.model.ModelPartCubeM",
"render.model.ModelPartM",
"render.vertex.FaceBakeryM",
Expand All @@ -40,39 +35,41 @@
"render.vertex.LiquidBlockRendererM",
"render.vertex.VertexFormatMixin",
"render.BufferUploaderM",
"render.RenderTargetMixin",
"render.GameRendererMixin",
"render.GlProgramManagerMixin",
"render.GlStateManagerM",
"render.vertex.IndexTypeMixin",
"render.LevelRendererMixin",
"render.MainTargetMixin",
"render.MinecraftMixin",
"render.RenderSystemMixin",
"render.RenderTargetMixin",
"render.ShaderInstanceM",
"render.MainTargetMixin",
"render.LevelRendererMixin",

"render.model.ModelPartCubeM",
"render.model.ModelPartM",
"render.vertex.BufferBuilderM",
"render.vertex.FaceBakeryM",
"render.vertex.IndexTypeMixin",
"render.vertex.LiquidBlockRendererM",
"render.vertex.VertexBufferM",
"render.vertex.VertexConsumerM",
"render.vertex.VertexFormatMixin",
"screen.OptionsScreenM",

"texture.MAbstractTexture",
"texture.MDynamicTexture",
"texture.MFontTexture",
"texture.MLightTexture",
"texture.MNativeImage",
"texture.MOverlayTexture",
"texture.MPlayerSkinTexture",
"texture.MSimpleTexture",
"texture.MSpriteAtlasTexture",
"texture.MSpriteContents",
"texture.MTextureManager",
"texture.MNativeImage",

"util.ScreenshotRecorderM",

"vertex.SpriteCoordinateExpanderM",
"vertex.VertexMultiConsumersM$DoubleM",
"vertex.VertexMultiConsumersM$MultipleM",
"vertex.VertexMultiConsumersM$SheetDecalM",

"WindowMixin"
"vertex.VertexMultiConsumersM$SheetDecalM"
],
"injectors": {
"defaultRequire": 1
Expand Down
Loading