diff --git a/Minecraft.Client/Minecraft.Client.vcxproj b/Minecraft.Client/Minecraft.Client.vcxproj
index 93f2070c..6bfce6f1 100644
--- a/Minecraft.Client/Minecraft.Client.vcxproj
+++ b/Minecraft.Client/Minecraft.Client.vcxproj
@@ -1285,7 +1285,7 @@ if not exist "$(TargetDir)\savedata" mkdir "$(TargetDir)\savedata"
MultiThreadedDebug
_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_DEBUG;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64;%(PreprocessorDefinitions)
Disabled
- Windows64\Iggy\include;$(ProjectDir);%(AdditionalIncludeDirectories)
+ $(VULKAN_SDK)\Include;Windows64\Iggy\include;$(ProjectDir);%(AdditionalIncludeDirectories)
true
true
Default
@@ -1294,7 +1294,8 @@ if not exist "$(TargetDir)\savedata" mkdir "$(TargetDir)\savedata"
true
$(OutDir)$(ProjectName).pdb
- d3d11.lib;..\Minecraft.World\x64_Debug\Minecraft.World.lib;%(AdditionalDependencies);XInput9_1_0.lib;..\Minecraft.Client\Windows64\Miles\Lib\mss64.lib
+ $(VULKAN_SDK)\Lib;%(AdditionalLibraryDirectories)
+ vulkan-1.lib;d3d11.lib;..\Minecraft.World\x64_Debug\Minecraft.World.lib;%(AdditionalDependencies);XInput9_1_0.lib;..\Minecraft.Client\Windows64\Miles\Lib\mss64.lib
NotSet
false
%(AdditionalLibraryDirectories)
@@ -1413,7 +1414,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CUMultiThreaded
_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64;MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
Disabled
- Windows64\Iggy\include;$(ProjectDir);$(ProjectDir)\discord;$(ProjectDir)miniupnpc\;%(AdditionalIncludeDirectories)
+ $(VULKAN_SDK)\Include;Windows64\Iggy\include;$(ProjectDir);$(ProjectDir)\discord;$(ProjectDir)miniupnpc\;%(AdditionalIncludeDirectories)
true
true
Default
@@ -1423,7 +1424,8 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU
true
$(OutDir)$(ProjectName).pdb
- d3d11.lib;..\Minecraft.World\x64_Release\Minecraft.World.lib;XInput9_1_0.lib;Windows64\Iggy\lib\iggy_w64.lib;discord_game_sdk.dll.lib;IPHlpApi.lib;%(AdditionalDependencies)
+ $(VULKAN_SDK)\Lib;%(AdditionalLibraryDirectories)
+ vulkan-1.lib;d3d11.lib;..\Minecraft.World\x64_Release\Minecraft.World.lib;XInput9_1_0.lib;Windows64\Iggy\lib\iggy_w64.lib;discord_game_sdk.dll.lib;IPHlpApi.lib;%(AdditionalDependencies)
NotSet
false
$(ProjectDir)\discord;C:\Program Files (x86)\Windows Kits\8.0\Lib\win8\um\x64;%(AdditionalLibraryDirectories)
@@ -1455,7 +1457,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CUMultiThreaded
_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64;%(PreprocessorDefinitions)
Disabled
- Windows64\Iggy\include;$(ProjectDir);%(AdditionalIncludeDirectories)
+ $(VULKAN_SDK)\Include;Windows64\Iggy\include;$(ProjectDir);%(AdditionalIncludeDirectories)
true
true
Default
@@ -1465,7 +1467,8 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU
true
$(OutDir)$(ProjectName).pdb
- d3d11.lib;..\Minecraft.World\x64_Release\Minecraft.World.lib;XInput9_1_0.lib;Windows64\Iggy\lib\iggy_w64.lib;%(AdditionalDependencies)
+ $(VULKAN_SDK)\Lib;%(AdditionalLibraryDirectories)
+ vulkan-1.lib;d3d11.lib;..\Minecraft.World\x64_Release\Minecraft.World.lib;XInput9_1_0.lib;Windows64\Iggy\lib\iggy_w64.lib;%(AdditionalDependencies)
NotSet
false
@@ -21543,19 +21546,58 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
+
+ NotUsing
+ MINIUPNP_STATICLIB;%(PreprocessorDefinitions)
+
@@ -36732,4 +36774,4 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU
-
\ No newline at end of file
+
diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
index 5647f071..d75ae6b8 100644
--- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
+++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
@@ -43,6 +43,10 @@
#include "Xbox/resource.h"
#include "Windows64_Minecraft.h"
+#ifdef _WINDOWS64
+#define VK_USE_PLATFORM_WIN32_KHR
+#include
+#endif
HINSTANCE hMyInst;
LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam);
@@ -347,6 +351,58 @@ D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
ID3D11Device* g_pd3dDevice = NULL;
ID3D11DeviceContext* g_pImmediateContext = NULL;
IDXGISwapChain* g_pSwapChain = NULL;
+ID3D11RenderTargetView* g_pRenderTargetView = NULL;
+ID3D11DepthStencilView* g_pDepthStencilView = NULL;
+ID3D11Texture2D* g_pDepthStencilBuffer = NULL;
+
+enum ERendererBackend
+{
+ RENDERER_BACKEND_D3D11 = 0,
+ RENDERER_BACKEND_VULKAN,
+};
+
+static ERendererBackend g_rendererBackendRequested = RENDERER_BACKEND_D3D11;
+static ERendererBackend g_rendererBackendActive = RENDERER_BACKEND_D3D11;
+
+struct LegacyRendererBridge
+{
+ ID3D11Device *device;
+ ID3D11DeviceContext *context;
+ ID3D11RenderTargetView *renderTargetView;
+ ID3D11DepthStencilView *depthStencilView;
+ IDXGISwapChain *swapChain;
+ bool ready;
+};
+
+struct VulkanBootstrapState
+{
+ VkInstance instance;
+ VkSurfaceKHR surface;
+ VkPhysicalDevice physicalDevice;
+ VkDevice device;
+ VkQueue graphicsQueue;
+ uint32_t graphicsQueueFamilyIndex;
+ VkSwapchainKHR swapChain;
+ VkFormat swapChainFormat;
+ VkExtent2D swapChainExtent;
+ char gpuName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE];
+ bool initialised;
+};
+
+static VulkanBootstrapState g_vulkanBootstrapState =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ VK_FORMAT_UNDEFINED,
+ { 0, 0 },
+ { 0 },
+ false
+};
static WORD g_originalGammaRamp[3][256];
static bool g_gammaRampSaved = false;
@@ -393,9 +449,651 @@ void Windows64_RestoreGamma()
SetDeviceGammaRamp(hdc, g_originalGammaRamp);
ReleaseDC(g_hWnd, hdc);
}
-ID3D11RenderTargetView* g_pRenderTargetView = NULL;
-ID3D11DepthStencilView* g_pDepthStencilView = NULL;
-ID3D11Texture2D* g_pDepthStencilBuffer = NULL;
+
+static const char* GetRendererBackendName(ERendererBackend backend)
+{
+ switch (backend)
+ {
+ case RENDERER_BACKEND_VULKAN: return "vulkan";
+ case RENDERER_BACKEND_D3D11:
+ default: return "d3d11";
+ }
+}
+
+static void PrintRendererStatusToConsole(const char *phase, const char *detail = "")
+{
+ printf("[Renderer] %s | requested=%s active=%s %s\n",
+ phase ? phase : "state",
+ GetRendererBackendName(g_rendererBackendRequested),
+ GetRendererBackendName(g_rendererBackendActive),
+ detail ? detail : "");
+ fflush(stdout);
+}
+
+static LegacyRendererBridge GetLegacyRendererBridge()
+{
+ LegacyRendererBridge bridge;
+ bridge.device = g_pd3dDevice;
+ bridge.context = g_pImmediateContext;
+ bridge.renderTargetView = g_pRenderTargetView;
+ bridge.depthStencilView = g_pDepthStencilView;
+ bridge.swapChain = g_pSwapChain;
+ bridge.ready = (bridge.device && bridge.context && bridge.renderTargetView && bridge.depthStencilView && bridge.swapChain);
+ return bridge;
+}
+
+static const char* VkResultToString(VkResult result)
+{
+ switch (result)
+ {
+ case VK_SUCCESS: return "VK_SUCCESS";
+ case VK_NOT_READY: return "VK_NOT_READY";
+ case VK_TIMEOUT: return "VK_TIMEOUT";
+ case VK_EVENT_SET: return "VK_EVENT_SET";
+ case VK_EVENT_RESET: return "VK_EVENT_RESET";
+ case VK_INCOMPLETE: return "VK_INCOMPLETE";
+ case VK_ERROR_OUT_OF_HOST_MEMORY: return "VK_ERROR_OUT_OF_HOST_MEMORY";
+ case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
+ case VK_ERROR_INITIALIZATION_FAILED: return "VK_ERROR_INITIALIZATION_FAILED";
+ case VK_ERROR_DEVICE_LOST: return "VK_ERROR_DEVICE_LOST";
+ case VK_ERROR_MEMORY_MAP_FAILED: return "VK_ERROR_MEMORY_MAP_FAILED";
+ case VK_ERROR_LAYER_NOT_PRESENT: return "VK_ERROR_LAYER_NOT_PRESENT";
+ case VK_ERROR_EXTENSION_NOT_PRESENT: return "VK_ERROR_EXTENSION_NOT_PRESENT";
+ case VK_ERROR_FEATURE_NOT_PRESENT: return "VK_ERROR_FEATURE_NOT_PRESENT";
+ case VK_ERROR_INCOMPATIBLE_DRIVER: return "VK_ERROR_INCOMPATIBLE_DRIVER";
+ case VK_ERROR_TOO_MANY_OBJECTS: return "VK_ERROR_TOO_MANY_OBJECTS";
+ case VK_ERROR_FORMAT_NOT_SUPPORTED: return "VK_ERROR_FORMAT_NOT_SUPPORTED";
+ case VK_ERROR_SURFACE_LOST_KHR: return "VK_ERROR_SURFACE_LOST_KHR";
+ case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
+ case VK_SUBOPTIMAL_KHR: return "VK_SUBOPTIMAL_KHR";
+ case VK_ERROR_OUT_OF_DATE_KHR: return "VK_ERROR_OUT_OF_DATE_KHR";
+ default: return "VK_UNKNOWN";
+ }
+}
+
+static void CleanupVulkanBootstrap()
+{
+ if (g_vulkanBootstrapState.device != 0)
+ {
+ vkDeviceWaitIdle(g_vulkanBootstrapState.device);
+ }
+ if (g_vulkanBootstrapState.swapChain != 0)
+ {
+ vkDestroySwapchainKHR(g_vulkanBootstrapState.device, g_vulkanBootstrapState.swapChain, NULL);
+ }
+ if (g_vulkanBootstrapState.device != 0)
+ {
+ vkDestroyDevice(g_vulkanBootstrapState.device, NULL);
+ }
+ if (g_vulkanBootstrapState.surface != 0)
+ {
+ vkDestroySurfaceKHR(g_vulkanBootstrapState.instance, g_vulkanBootstrapState.surface, NULL);
+ }
+ if (g_vulkanBootstrapState.instance != 0)
+ {
+ vkDestroyInstance(g_vulkanBootstrapState.instance, NULL);
+ }
+
+ g_vulkanBootstrapState.instance = 0;
+ g_vulkanBootstrapState.surface = 0;
+ g_vulkanBootstrapState.physicalDevice = 0;
+ g_vulkanBootstrapState.device = 0;
+ g_vulkanBootstrapState.graphicsQueue = 0;
+ g_vulkanBootstrapState.graphicsQueueFamilyIndex = 0;
+ g_vulkanBootstrapState.swapChain = 0;
+ g_vulkanBootstrapState.swapChainFormat = VK_FORMAT_UNDEFINED;
+ g_vulkanBootstrapState.swapChainExtent.width = 0;
+ g_vulkanBootstrapState.swapChainExtent.height = 0;
+ g_vulkanBootstrapState.gpuName[0] = 0;
+ g_vulkanBootstrapState.initialised = false;
+}
+
+static bool SelectVulkanPhysicalDevice(VkInstance instance, VkSurfaceKHR surface, VkPhysicalDevice *deviceOut, uint32_t *queueFamilyOut, VkPhysicalDeviceProperties *propsOut)
+{
+ uint32_t deviceCount = 0;
+ if (vkEnumeratePhysicalDevices(instance, &deviceCount, NULL) != VK_SUCCESS || deviceCount == 0)
+ {
+ return false;
+ }
+
+ vector devices(deviceCount);
+ if (vkEnumeratePhysicalDevices(instance, &deviceCount, &devices[0]) != VK_SUCCESS)
+ {
+ return false;
+ }
+
+ for (uint32_t deviceIndex = 0; deviceIndex < deviceCount; ++deviceIndex)
+ {
+ VkPhysicalDevice candidate = devices[deviceIndex];
+
+ uint32_t extensionCount = 0;
+ vkEnumerateDeviceExtensionProperties(candidate, NULL, &extensionCount, NULL);
+ if (extensionCount == 0)
+ {
+ continue;
+ }
+
+ vector extensions(extensionCount);
+ if (vkEnumerateDeviceExtensionProperties(candidate, NULL, &extensionCount, &extensions[0]) != VK_SUCCESS)
+ {
+ continue;
+ }
+
+ bool hasSwapchain = false;
+ for (uint32_t ext = 0; ext < extensionCount; ++ext)
+ {
+ if (strcmp(extensions[ext].extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0)
+ {
+ hasSwapchain = true;
+ break;
+ }
+ }
+ if (!hasSwapchain)
+ {
+ continue;
+ }
+
+ uint32_t queueFamilyCount = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(candidate, &queueFamilyCount, NULL);
+ if (queueFamilyCount == 0)
+ {
+ continue;
+ }
+
+ vector queueFamilies(queueFamilyCount);
+ vkGetPhysicalDeviceQueueFamilyProperties(candidate, &queueFamilyCount, &queueFamilies[0]);
+
+ for (uint32_t queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount; ++queueFamilyIndex)
+ {
+ VkBool32 supportsPresent = VK_FALSE;
+ vkGetPhysicalDeviceSurfaceSupportKHR(candidate, queueFamilyIndex, surface, &supportsPresent);
+
+ if ((queueFamilies[queueFamilyIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) && supportsPresent)
+ {
+ if (propsOut)
+ {
+ vkGetPhysicalDeviceProperties(candidate, propsOut);
+ }
+ *deviceOut = candidate;
+ *queueFamilyOut = queueFamilyIndex;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static HRESULT CreateVulkanBootstrap(HWND hWnd, UINT width, UINT height)
+{
+ CleanupVulkanBootstrap();
+
+ const char *instanceExtensions[] =
+ {
+ VK_KHR_SURFACE_EXTENSION_NAME,
+ VK_KHR_WIN32_SURFACE_EXTENSION_NAME
+ };
+
+ VkApplicationInfo appInfo;
+ ZeroMemory(&appInfo, sizeof(appInfo));
+ appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ appInfo.pApplicationName = "MinecraftClient";
+ appInfo.applicationVersion = VK_MAKE_API_VERSION(0, 1, 0, 0);
+ appInfo.pEngineName = "4JLegacy";
+ appInfo.engineVersion = VK_MAKE_API_VERSION(0, 1, 0, 0);
+ appInfo.apiVersion = VK_API_VERSION_1_0;
+
+ VkInstanceCreateInfo instanceInfo;
+ ZeroMemory(&instanceInfo, sizeof(instanceInfo));
+ instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ instanceInfo.pApplicationInfo = &appInfo;
+ instanceInfo.enabledExtensionCount = ARRAYSIZE(instanceExtensions);
+ instanceInfo.ppEnabledExtensionNames = instanceExtensions;
+
+ VkResult vkResult = vkCreateInstance(&instanceInfo, NULL, &g_vulkanBootstrapState.instance);
+ if (vkResult != VK_SUCCESS)
+ {
+ app.DebugPrintf("Vulkan bootstrap: vkCreateInstance failed (%s)\n", VkResultToString(vkResult));
+ return E_FAIL;
+ }
+
+ VkWin32SurfaceCreateInfoKHR surfaceInfo;
+ ZeroMemory(&surfaceInfo, sizeof(surfaceInfo));
+ surfaceInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+ surfaceInfo.hinstance = GetModuleHandle(NULL);
+ surfaceInfo.hwnd = hWnd;
+ vkResult = vkCreateWin32SurfaceKHR(g_vulkanBootstrapState.instance, &surfaceInfo, NULL, &g_vulkanBootstrapState.surface);
+ if (vkResult != VK_SUCCESS)
+ {
+ app.DebugPrintf("Vulkan bootstrap: vkCreateWin32SurfaceKHR failed (%s)\n", VkResultToString(vkResult));
+ CleanupVulkanBootstrap();
+ return E_FAIL;
+ }
+
+ VkPhysicalDeviceProperties gpuProperties;
+ ZeroMemory(&gpuProperties, sizeof(gpuProperties));
+ if (!SelectVulkanPhysicalDevice(g_vulkanBootstrapState.instance, g_vulkanBootstrapState.surface, &g_vulkanBootstrapState.physicalDevice, &g_vulkanBootstrapState.graphicsQueueFamilyIndex, &gpuProperties))
+ {
+ app.DebugPrintf("Vulkan bootstrap: no suitable physical device found\n");
+ CleanupVulkanBootstrap();
+ return E_FAIL;
+ }
+ strncpy_s(g_vulkanBootstrapState.gpuName, sizeof(g_vulkanBootstrapState.gpuName), gpuProperties.deviceName, _TRUNCATE);
+
+ float queuePriority = 1.0f;
+ VkDeviceQueueCreateInfo queueInfo;
+ ZeroMemory(&queueInfo, sizeof(queueInfo));
+ queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queueInfo.queueFamilyIndex = g_vulkanBootstrapState.graphicsQueueFamilyIndex;
+ queueInfo.queueCount = 1;
+ queueInfo.pQueuePriorities = &queuePriority;
+
+ const char *deviceExtensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
+ VkDeviceCreateInfo deviceInfo;
+ ZeroMemory(&deviceInfo, sizeof(deviceInfo));
+ deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ deviceInfo.queueCreateInfoCount = 1;
+ deviceInfo.pQueueCreateInfos = &queueInfo;
+ deviceInfo.enabledExtensionCount = ARRAYSIZE(deviceExtensions);
+ deviceInfo.ppEnabledExtensionNames = deviceExtensions;
+
+ vkResult = vkCreateDevice(g_vulkanBootstrapState.physicalDevice, &deviceInfo, NULL, &g_vulkanBootstrapState.device);
+ if (vkResult != VK_SUCCESS)
+ {
+ app.DebugPrintf("Vulkan bootstrap: vkCreateDevice failed (%s)\n", VkResultToString(vkResult));
+ CleanupVulkanBootstrap();
+ return E_FAIL;
+ }
+
+ vkGetDeviceQueue(g_vulkanBootstrapState.device, g_vulkanBootstrapState.graphicsQueueFamilyIndex, 0, &g_vulkanBootstrapState.graphicsQueue);
+
+ uint32_t formatCount = 0;
+ vkResult = vkGetPhysicalDeviceSurfaceFormatsKHR(g_vulkanBootstrapState.physicalDevice, g_vulkanBootstrapState.surface, &formatCount, NULL);
+ if (vkResult != VK_SUCCESS || formatCount == 0)
+ {
+ app.DebugPrintf("Vulkan bootstrap: surface formats unavailable (%s)\n", VkResultToString(vkResult));
+ CleanupVulkanBootstrap();
+ return E_FAIL;
+ }
+
+ vector formats(formatCount);
+ vkResult = vkGetPhysicalDeviceSurfaceFormatsKHR(g_vulkanBootstrapState.physicalDevice, g_vulkanBootstrapState.surface, &formatCount, &formats[0]);
+ if (vkResult != VK_SUCCESS)
+ {
+ app.DebugPrintf("Vulkan bootstrap: failed to read surface formats (%s)\n", VkResultToString(vkResult));
+ CleanupVulkanBootstrap();
+ return E_FAIL;
+ }
+
+ VkSurfaceFormatKHR selectedFormat = formats[0];
+ for (uint32_t i = 0; i < formatCount; ++i)
+ {
+ if (formats[i].format == VK_FORMAT_B8G8R8A8_UNORM && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
+ {
+ selectedFormat = formats[i];
+ break;
+ }
+ }
+
+ VkSurfaceCapabilitiesKHR surfaceCaps;
+ ZeroMemory(&surfaceCaps, sizeof(surfaceCaps));
+ vkResult = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_vulkanBootstrapState.physicalDevice, g_vulkanBootstrapState.surface, &surfaceCaps);
+ if (vkResult != VK_SUCCESS)
+ {
+ app.DebugPrintf("Vulkan bootstrap: failed to read surface capabilities (%s)\n", VkResultToString(vkResult));
+ CleanupVulkanBootstrap();
+ return E_FAIL;
+ }
+
+ uint32_t presentModeCount = 0;
+ vkResult = vkGetPhysicalDeviceSurfacePresentModesKHR(g_vulkanBootstrapState.physicalDevice, g_vulkanBootstrapState.surface, &presentModeCount, NULL);
+ if (vkResult != VK_SUCCESS || presentModeCount == 0)
+ {
+ app.DebugPrintf("Vulkan bootstrap: present modes unavailable (%s)\n", VkResultToString(vkResult));
+ CleanupVulkanBootstrap();
+ return E_FAIL;
+ }
+
+ vector presentModes(presentModeCount);
+ vkResult = vkGetPhysicalDeviceSurfacePresentModesKHR(g_vulkanBootstrapState.physicalDevice, g_vulkanBootstrapState.surface, &presentModeCount, &presentModes[0]);
+ if (vkResult != VK_SUCCESS)
+ {
+ app.DebugPrintf("Vulkan bootstrap: failed to read present modes (%s)\n", VkResultToString(vkResult));
+ CleanupVulkanBootstrap();
+ return E_FAIL;
+ }
+
+ VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
+ for (uint32_t i = 0; i < presentModeCount; ++i)
+ {
+ if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
+ {
+ presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
+ break;
+ }
+ }
+
+ VkExtent2D extent;
+ if (surfaceCaps.currentExtent.width != 0xFFFFFFFF)
+ {
+ extent = surfaceCaps.currentExtent;
+ }
+ else
+ {
+ extent.width = width;
+ extent.height = height;
+ if (extent.width < surfaceCaps.minImageExtent.width) extent.width = surfaceCaps.minImageExtent.width;
+ if (extent.width > surfaceCaps.maxImageExtent.width) extent.width = surfaceCaps.maxImageExtent.width;
+ if (extent.height < surfaceCaps.minImageExtent.height) extent.height = surfaceCaps.minImageExtent.height;
+ if (extent.height > surfaceCaps.maxImageExtent.height) extent.height = surfaceCaps.maxImageExtent.height;
+ }
+
+ uint32_t imageCount = surfaceCaps.minImageCount + 1;
+ if (surfaceCaps.maxImageCount > 0 && imageCount > surfaceCaps.maxImageCount)
+ {
+ imageCount = surfaceCaps.maxImageCount;
+ }
+
+ VkSwapchainCreateInfoKHR swapchainInfo;
+ ZeroMemory(&swapchainInfo, sizeof(swapchainInfo));
+ swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ swapchainInfo.surface = g_vulkanBootstrapState.surface;
+ swapchainInfo.minImageCount = imageCount;
+ swapchainInfo.imageFormat = selectedFormat.format;
+ swapchainInfo.imageColorSpace = selectedFormat.colorSpace;
+ swapchainInfo.imageExtent = extent;
+ swapchainInfo.imageArrayLayers = 1;
+ swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapchainInfo.preTransform = surfaceCaps.currentTransform;
+ swapchainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ swapchainInfo.presentMode = presentMode;
+ swapchainInfo.clipped = VK_TRUE;
+ swapchainInfo.oldSwapchain = 0;
+
+ vkResult = vkCreateSwapchainKHR(g_vulkanBootstrapState.device, &swapchainInfo, NULL, &g_vulkanBootstrapState.swapChain);
+ if (vkResult != VK_SUCCESS)
+ {
+ app.DebugPrintf("Vulkan bootstrap: vkCreateSwapchainKHR failed (%s)\n", VkResultToString(vkResult));
+ CleanupVulkanBootstrap();
+ return E_FAIL;
+ }
+
+ g_vulkanBootstrapState.swapChainFormat = selectedFormat.format;
+ g_vulkanBootstrapState.swapChainExtent = extent;
+ g_vulkanBootstrapState.initialised = true;
+ return S_OK;
+}
+
+static bool ParseRendererBackend(const char *value, ERendererBackend *backendOut)
+{
+ if (!value || !*value || !backendOut)
+ return false;
+
+ if (_stricmp(value, "vulkan") == 0 || _stricmp(value, "vk") == 0)
+ {
+ *backendOut = RENDERER_BACKEND_VULKAN;
+ return true;
+ }
+ if (_stricmp(value, "d3d11") == 0 || _stricmp(value, "dx11") == 0)
+ {
+ *backendOut = RENDERER_BACKEND_D3D11;
+ return true;
+ }
+ return false;
+}
+
+static bool TryGetBackendFromEnv(ERendererBackend *backendOut)
+{
+ char value[32] = { 0 };
+ DWORD chars = GetEnvironmentVariableA("MC_RENDERER", value, ARRAYSIZE(value));
+ if (chars == 0 || chars >= ARRAYSIZE(value))
+ return false;
+
+ return ParseRendererBackend(value, backendOut);
+}
+
+static bool TryGetBackendFromCommandLine(const char *commandLine, ERendererBackend *backendOut)
+{
+ if (!commandLine || !*commandLine || !backendOut)
+ return false;
+
+ const char *option = strstr(commandLine, "-renderer");
+ if (!option)
+ option = strstr(commandLine, "/renderer");
+ if (!option)
+ return false;
+
+ option += 9; // strlen("-renderer")
+ while (*option == ' ' || *option == '\t' || *option == '=')
+ ++option;
+ if (!*option)
+ return false;
+
+ char token[32] = { 0 };
+ int i = 0;
+ while (option[i] && option[i] != ' ' && option[i] != '\t' && i < ((int)ARRAYSIZE(token) - 1))
+ {
+ token[i] = option[i];
+ ++i;
+ }
+ token[i] = 0;
+
+ return ParseRendererBackend(token, backendOut);
+}
+
+static void SelectRendererBackend(const char *commandLine)
+{
+ ERendererBackend selected = RENDERER_BACKEND_D3D11;
+ if (TryGetBackendFromEnv(&selected))
+ {
+ g_rendererBackendRequested = selected;
+ }
+
+ if (TryGetBackendFromCommandLine(commandLine, &selected))
+ {
+ g_rendererBackendRequested = selected;
+ }
+
+ g_rendererBackendActive = g_rendererBackendRequested;
+ app.DebugPrintf("Renderer backend requested=%s active=%s\n",
+ GetRendererBackendName(g_rendererBackendRequested),
+ GetRendererBackendName(g_rendererBackendActive));
+ PrintRendererStatusToConsole("Selected");
+}
+
+static void ReleaseD3D11Device()
+{
+ if (g_pImmediateContext)
+ {
+ g_pImmediateContext->OMSetRenderTargets(0, NULL, NULL);
+ g_pImmediateContext->ClearState();
+ g_pImmediateContext->Flush();
+ }
+
+ if (g_pRenderTargetView) { g_pRenderTargetView->Release(); g_pRenderTargetView = NULL; }
+ if (g_pDepthStencilView) { g_pDepthStencilView->Release(); g_pDepthStencilView = NULL; }
+ if (g_pDepthStencilBuffer) { g_pDepthStencilBuffer->Release(); g_pDepthStencilBuffer = NULL; }
+ if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
+ if (g_pImmediateContext) { g_pImmediateContext->Release(); g_pImmediateContext = NULL; }
+ if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
+}
+
+static HRESULT CreateD3D11Device(HWND hWnd, UINT width, UINT height)
+{
+ UINT createDeviceFlags = 0;
+#ifdef _DEBUG
+ createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+ D3D_DRIVER_TYPE driverTypes[] =
+ {
+ D3D_DRIVER_TYPE_HARDWARE,
+ D3D_DRIVER_TYPE_WARP,
+ D3D_DRIVER_TYPE_REFERENCE,
+ };
+
+ D3D_FEATURE_LEVEL featureLevels[] =
+ {
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ };
+
+ DXGI_SWAP_CHAIN_DESC sd;
+ ZeroMemory(&sd, sizeof(sd));
+ sd.BufferCount = 1;
+ sd.BufferDesc.Width = width;
+ sd.BufferDesc.Height = height;
+ sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ sd.BufferDesc.RefreshRate.Numerator = 60;
+ sd.BufferDesc.RefreshRate.Denominator = 1;
+ sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ sd.OutputWindow = hWnd;
+ sd.SampleDesc.Count = 1;
+ sd.SampleDesc.Quality = 0;
+ sd.Windowed = TRUE;
+
+ HRESULT hr = E_FAIL;
+ for (UINT i = 0; i < ARRAYSIZE(driverTypes); ++i)
+ {
+ g_driverType = driverTypes[i];
+ hr = D3D11CreateDeviceAndSwapChain(NULL, g_driverType, NULL, createDeviceFlags,
+ featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION,
+ &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext);
+ if (SUCCEEDED(hr))
+ break;
+ }
+ if (FAILED(hr))
+ return hr;
+
+ ID3D11Texture2D *pBackBuffer = NULL;
+ hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
+ if (FAILED(hr))
+ {
+ ReleaseD3D11Device();
+ return hr;
+ }
+
+ hr = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_pRenderTargetView);
+ pBackBuffer->Release();
+ if (FAILED(hr))
+ {
+ ReleaseD3D11Device();
+ return hr;
+ }
+
+ D3D11_TEXTURE2D_DESC descDepth;
+ ZeroMemory(&descDepth, sizeof(descDepth));
+ descDepth.Width = width;
+ descDepth.Height = height;
+ descDepth.MipLevels = 1;
+ descDepth.ArraySize = 1;
+ descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ descDepth.SampleDesc.Count = 1;
+ descDepth.SampleDesc.Quality = 0;
+ descDepth.Usage = D3D11_USAGE_DEFAULT;
+ descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+
+ hr = g_pd3dDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencilBuffer);
+ if (FAILED(hr))
+ {
+ ReleaseD3D11Device();
+ return hr;
+ }
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
+ ZeroMemory(&descDSV, sizeof(descDSV));
+ descDSV.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ descDSV.Texture2D.MipSlice = 0;
+
+ hr = g_pd3dDevice->CreateDepthStencilView(g_pDepthStencilBuffer, &descDSV, &g_pDepthStencilView);
+ if (FAILED(hr))
+ {
+ ReleaseD3D11Device();
+ return hr;
+ }
+
+ g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView);
+
+ D3D11_VIEWPORT vp;
+ vp.Width = (FLOAT)width;
+ vp.Height = (FLOAT)height;
+ vp.MinDepth = 0.0f;
+ vp.MaxDepth = 1.0f;
+ vp.TopLeftX = 0;
+ vp.TopLeftY = 0;
+ g_pImmediateContext->RSSetViewports(1, &vp);
+
+ return S_OK;
+}
+
+static HRESULT ResizeD3D11Device(HWND hWnd, UINT width, UINT height)
+{
+ ReleaseD3D11Device();
+ return CreateD3D11Device(hWnd, width, height);
+}
+
+static HRESULT CreateActiveRendererDevice(HWND hWnd, UINT width, UINT height)
+{
+ if (g_rendererBackendRequested == RENDERER_BACKEND_VULKAN)
+ {
+ HRESULT vulkanProbeResult = CreateVulkanBootstrap(hWnd, width, height);
+ if (SUCCEEDED(vulkanProbeResult))
+ {
+ app.DebugPrintf("Vulkan bootstrap OK on GPU '%s' (%ux%u)\n",
+ g_vulkanBootstrapState.gpuName,
+ g_vulkanBootstrapState.swapChainExtent.width,
+ g_vulkanBootstrapState.swapChainExtent.height);
+
+ char detail[256];
+ sprintf_s(detail, sizeof(detail), "probe=ok gpu=%s extent=%ux%u",
+ g_vulkanBootstrapState.gpuName,
+ g_vulkanBootstrapState.swapChainExtent.width,
+ g_vulkanBootstrapState.swapChainExtent.height);
+ PrintRendererStatusToConsole("Vulkan", detail);
+ }
+ else
+ {
+ app.DebugPrintf("Vulkan bootstrap failed, continuing with d3d11 compatibility path.\n");
+ PrintRendererStatusToConsole("Vulkan", "probe=failed fallback=d3d11");
+ }
+ CleanupVulkanBootstrap();
+ }
+
+ g_rendererBackendActive = RENDERER_BACKEND_D3D11;
+ HRESULT hr = CreateD3D11Device(hWnd, width, height);
+ if (SUCCEEDED(hr))
+ {
+ PrintRendererStatusToConsole("Startup", "active=d3d11");
+ }
+ return hr;
+}
+
+static HRESULT ResizeActiveRendererDevice(HWND hWnd, UINT width, UINT height)
+{
+ return ResizeD3D11Device(hWnd, width, height);
+}
+
+static void CleanupActiveRendererDevice()
+{
+ CleanupVulkanBootstrap();
+ ReleaseD3D11Device();
+}
+
+static void InitialiseRenderManager()
+{
+ LegacyRendererBridge bridge = GetLegacyRendererBridge();
+ if (bridge.ready)
+ {
+ RenderManager.Initialise(bridge.device, bridge.swapChain);
+ }
+ else
+ {
+ app.DebugPrintf("RenderManager init skipped: legacy renderer bridge is unavailable.\n");
+ }
+}
//
@@ -426,94 +1124,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
g_iScreenWidth = (int)newWidth;
g_iScreenHeight = (int)newHeight;
- // Full device teardown
- if (g_pImmediateContext)
- {
- g_pImmediateContext->OMSetRenderTargets(0, NULL, NULL);
- g_pImmediateContext->ClearState();
- g_pImmediateContext->Flush();
- }
- if (g_pRenderTargetView) { g_pRenderTargetView->Release(); g_pRenderTargetView = NULL; }
- if (g_pDepthStencilView) { g_pDepthStencilView->Release(); g_pDepthStencilView = NULL; }
- if (g_pDepthStencilBuffer) { g_pDepthStencilBuffer->Release(); g_pDepthStencilBuffer = NULL; }
- if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
- if (g_pImmediateContext) { g_pImmediateContext->Release(); g_pImmediateContext = NULL; }
- if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
-
- // Rebuild swap chain + device from scratch
- UINT createDeviceFlags = 0;
-#ifdef _DEBUG
- createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
-#endif
- D3D_DRIVER_TYPE driverTypes[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE };
- D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 };
-
- DXGI_SWAP_CHAIN_DESC sd;
- ZeroMemory(&sd, sizeof(sd));
- sd.BufferCount = 1;
- sd.BufferDesc.Width = newWidth;
- sd.BufferDesc.Height = newHeight;
- sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- sd.BufferDesc.RefreshRate.Numerator = 60;
- sd.BufferDesc.RefreshRate.Denominator = 1;
- sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- sd.OutputWindow = hWnd;
- sd.SampleDesc.Count = 1;
- sd.SampleDesc.Quality = 0;
- sd.Windowed = TRUE;
-
- HRESULT hr = E_FAIL;
- for (UINT i = 0; i < ARRAYSIZE(driverTypes); i++)
- {
- g_driverType = driverTypes[i];
- hr = D3D11CreateDeviceAndSwapChain(NULL, g_driverType, NULL, createDeviceFlags,
- featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION,
- &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext);
- if (SUCCEEDED(hr)) break;
- }
+ HRESULT hr = ResizeActiveRendererDevice(hWnd, newWidth, newHeight);
if (FAILED(hr))
{
- app.DebugPrintf("WM_SIZE device recreate FAILED: 0x%08X\n", hr);
+ app.DebugPrintf("WM_SIZE recreate failed for backend %s: 0x%08X\n", GetRendererBackendName(g_rendererBackendActive), hr);
break;
}
- app.DebugPrintf("WM_SIZE device recreate OK %dx%d\n", newWidth, newHeight);
-
- // Render target view
- ID3D11Texture2D *pBackBuffer = NULL;
- g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
- g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_pRenderTargetView);
- pBackBuffer->Release();
-
- // Depth stencil
- D3D11_TEXTURE2D_DESC descDepth = {};
- descDepth.Width = newWidth;
- descDepth.Height = newHeight;
- descDepth.MipLevels = 1;
- descDepth.ArraySize = 1;
- descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
- descDepth.SampleDesc.Count = 1;
- descDepth.SampleDesc.Quality = 0;
- descDepth.Usage = D3D11_USAGE_DEFAULT;
- descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
- g_pd3dDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencilBuffer);
-
- D3D11_DEPTH_STENCIL_VIEW_DESC descDSV = {};
- descDSV.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
- descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
- descDSV.Texture2D.MipSlice = 0;
- g_pd3dDevice->CreateDepthStencilView(g_pDepthStencilBuffer, &descDSV, &g_pDepthStencilView);
-
- g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView);
-
- // Viewport
- D3D11_VIEWPORT vp;
- vp.Width = (FLOAT)newWidth;
- vp.Height = (FLOAT)newHeight;
- vp.MinDepth = 0.0f;
- vp.MaxDepth = 1.0f;
- vp.TopLeftX = 0;
- vp.TopLeftY = 0;
- g_pImmediateContext->RSSetViewports(1, &vp);
+ app.DebugPrintf("WM_SIZE recreate ok for backend %s (%dx%d)\n", GetRendererBackendName(g_rendererBackendActive), newWidth, newHeight);
Minecraft *pMinecraft = Minecraft::GetInstance();
if (pMinecraft)
@@ -755,8 +1372,6 @@ LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
HRESULT InitDevice()
{
- HRESULT hr = S_OK;
-
RECT rc;
GetClientRect( g_hWnd, &rc );
UINT width = rc.right - rc.left;
@@ -764,103 +1379,8 @@ HRESULT InitDevice()
//app.DebugPrintf("width: %d, height: %d\n", width, height);
width = g_iScreenWidth;
height = g_iScreenHeight;
- app.DebugPrintf("width: %d, height: %d\n", width, height);
-
- UINT createDeviceFlags = 0;
-#ifdef _DEBUG
- createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
-#endif
-
- D3D_DRIVER_TYPE driverTypes[] =
- {
- D3D_DRIVER_TYPE_HARDWARE,
- D3D_DRIVER_TYPE_WARP,
- D3D_DRIVER_TYPE_REFERENCE,
- };
- UINT numDriverTypes = ARRAYSIZE( driverTypes );
-
- D3D_FEATURE_LEVEL featureLevels[] =
- {
- D3D_FEATURE_LEVEL_11_0,
- D3D_FEATURE_LEVEL_10_1,
- D3D_FEATURE_LEVEL_10_0,
- };
- UINT numFeatureLevels = ARRAYSIZE( featureLevels );
-
- DXGI_SWAP_CHAIN_DESC sd;
- ZeroMemory( &sd, sizeof( sd ) );
- sd.BufferCount = 1;
- sd.BufferDesc.Width = width;
- sd.BufferDesc.Height = height;
- sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- sd.BufferDesc.RefreshRate.Numerator = 60;
- sd.BufferDesc.RefreshRate.Denominator = 1;
- sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- sd.OutputWindow = g_hWnd;
- sd.SampleDesc.Count = 1;
- sd.SampleDesc.Quality = 0;
- sd.Windowed = TRUE;
-
- for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
- {
- g_driverType = driverTypes[driverTypeIndex];
- hr = D3D11CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, featureLevels, numFeatureLevels,
- D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );
- if( HRESULT_SUCCEEDED( hr ) )
- break;
- }
- if( FAILED( hr ) )
- return hr;
-
- // Create a render target view
- ID3D11Texture2D* pBackBuffer = NULL;
- hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer );
- if( FAILED( hr ) )
- return hr;
-
- // Create a depth stencil buffer
- D3D11_TEXTURE2D_DESC descDepth;
-
- descDepth.Width = width;
- descDepth.Height = height;
- descDepth.MipLevels = 1;
- descDepth.ArraySize = 1;
- descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
- descDepth.SampleDesc.Count = 1;
- descDepth.SampleDesc.Quality = 0;
- descDepth.Usage = D3D11_USAGE_DEFAULT;
- descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
- descDepth.CPUAccessFlags = 0;
- descDepth.MiscFlags = 0;
- hr = g_pd3dDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencilBuffer);
-
- D3D11_DEPTH_STENCIL_VIEW_DESC descDSView;
- descDSView.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
- descDSView.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
- descDSView.Texture2D.MipSlice = 0;
-
- hr = g_pd3dDevice->CreateDepthStencilView(g_pDepthStencilBuffer, &descDSView, &g_pDepthStencilView);
-
- hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView );
- pBackBuffer->Release();
- if( FAILED( hr ) )
- return hr;
-
- g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, g_pDepthStencilView );
-
- // Setup the viewport
- D3D11_VIEWPORT vp;
- vp.Width = (FLOAT)width;
- vp.Height = (FLOAT)height;
- vp.MinDepth = 0.0f;
- vp.MaxDepth = 1.0f;
- vp.TopLeftX = 0;
- vp.TopLeftY = 0;
- g_pImmediateContext->RSSetViewports( 1, &vp );
-
- RenderManager.Initialise(g_pd3dDevice, g_pSwapChain);
-
- return S_OK;
+ app.DebugPrintf("InitDevice backend=%s width=%d height=%d\n", GetRendererBackendName(g_rendererBackendActive), width, height);
+ return CreateActiveRendererDevice(g_hWnd, width, height);
}
//--------------------------------------------------------------------------------------
@@ -883,12 +1403,7 @@ void CleanupDevice()
extern void Windows64_RestoreGamma();
Windows64_RestoreGamma();
- if( g_pImmediateContext ) g_pImmediateContext->ClearState();
-
- if( g_pRenderTargetView ) g_pRenderTargetView->Release();
- if( g_pSwapChain ) g_pSwapChain->Release();
- if( g_pImmediateContext ) g_pImmediateContext->Release();
- if( g_pd3dDevice ) g_pd3dDevice->Release();
+ CleanupActiveRendererDevice();
}
@@ -907,7 +1422,11 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
#endif
UNREFERENCED_PARAMETER(hPrevInstance);
- UNREFERENCED_PARAMETER(lpCmdLine);
+ char cmdLineA[1024] = { 0 };
+ if (lpCmdLine)
+ {
+ strncpy_s(cmdLineA, sizeof(cmdLineA), lpCmdLine, _TRUNCATE);
+ }
if(lpCmdLine)
{
@@ -932,9 +1451,6 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
//g_iScreenHeight = 544;
}
- char cmdLineA[1024];
- strncpy_s(cmdLineA, sizeof(cmdLineA), lpCmdLine, _TRUNCATE);
-
char *nameArg = strstr(cmdLineA, "-name ");
if (nameArg)
{
@@ -957,6 +1473,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
}
MultiByteToWideChar(CP_ACP, 0, g_Win64Username, -1, g_Win64UsernameW, 17);
+ SelectRendererBackend(cmdLineA);
// Initialize global strings
MyRegisterClass(hInstance);
@@ -1027,12 +1544,38 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
}
#endif
+ {
+ wchar_t exePath[MAX_PATH] = { 0 };
+ if (GetModuleFileNameW(NULL, exePath, MAX_PATH))
+ {
+ wstring exeDir(exePath);
+ size_t lastSlash = exeDir.find_last_of(L"\\/");
+ if (lastSlash != wstring::npos)
+ {
+ exeDir = exeDir.substr(0, lastSlash);
+ }
+
+ wstring contentRoot = exeDir + L"\\..\\..\\Minecraft.Client";
+ wstring fontProbe = contentRoot + L"\\Common\\res\\font\\Mojangles_7.png";
+ if (GetFileAttributesW(fontProbe.c_str()) != INVALID_FILE_ATTRIBUTES)
+ {
+ SetCurrentDirectoryW(contentRoot.c_str());
+ }
+ }
+ }
app.loadMediaArchive();
- RenderManager.Initialise(g_pd3dDevice, g_pSwapChain);
+ InitialiseRenderManager();
app.loadStringTable();
- ui.init(g_pd3dDevice,g_pImmediateContext,g_pRenderTargetView,g_pDepthStencilView,g_iScreenWidth,g_iScreenHeight);
+ LegacyRendererBridge bridge = GetLegacyRendererBridge();
+ if (!bridge.ready)
+ {
+ app.DebugPrintf("UI init failed: legacy renderer bridge is unavailable.\n");
+ CleanupDevice();
+ return 0;
+ }
+ ui.init(bridge.device, bridge.context, bridge.renderTargetView, bridge.depthStencilView, g_iScreenWidth, g_iScreenHeight);
////////////////
// Initialise //
@@ -1557,7 +2100,8 @@ ui.render();
// Free resources, unregister custom classes, and exit.
// app.Uninit();
- g_pd3dDevice->Release();
+ CleanupDevice();
+ return 0;
}
#ifdef MEMORY_TRACKING
@@ -1747,4 +2291,4 @@ void MemPixStuff()
PIXAddNamedCounter(((float)allSectsTotal)/(4096.0f),"MemSect total pages");
}
-#endif
\ No newline at end of file
+#endif