From 49ebeb07641a03cf1f551680733c2b2d072d20f3 Mon Sep 17 00:00:00 2001 From: emiyl Date: Mon, 20 Apr 2026 22:46:57 +0100 Subject: [PATCH 01/32] remove vulkan/opengl code if ENABLE_VULKAN or ENABLE_OPENGL is not defined --- CMakeLists.txt | 7 ++ src/CMakeLists.txt | 94 +++++++------- src/Cafe/CMakeLists.txt | 108 +++++++++------- src/Cafe/HW/Latte/Core/LatteBufferData.cpp | 4 + src/Cafe/HW/Latte/Core/LatteShader.cpp | 105 +++++++++++----- src/Cafe/HW/Latte/Core/LatteShaderCache.cpp | 115 ++++++++++++++---- src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp | 4 + .../HW/Latte/Core/LatteTextureReadback.cpp | 2 + src/Cafe/HW/Latte/Core/LatteTiming.cpp | 4 + .../HW/Latte/Renderer/RendererOuputShader.cpp | 4 + src/config/ActiveSettings.cpp | 5 + src/gui/wxgui/CMakeLists.txt | 18 ++- src/gui/wxgui/CemuApp.cpp | 4 + src/gui/wxgui/MainWindow.cpp | 22 +++- src/gui/wxgui/PadViewFrame.cpp | 13 ++ src/imgui/CMakeLists.txt | 18 ++- src/imgui/imgui_extension.cpp | 6 +- src/main.cpp | 9 +- 18 files changed, 381 insertions(+), 161 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a00879fe..10fd422c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,6 +115,13 @@ option(ENABLE_VULKAN "Enables the Vulkan backend" ON) option(ENABLE_METAL "Enables the Metal backend" ${ENABLE_METAL_DEFAULT}) option(ENABLE_DISCORD_RPC "Enables the Discord Rich Presence feature" ON) +if (ENABLE_OPENGL) + set_compile_definitions(ENABLE_OPENGL) +else() +if (ENABLE_VULKAN) + add_compile_definitions(ENABLE_VULKAN) +else() + if (ENABLE_METAL AND NOT APPLE) message(FATAL_ERROR "Metal backend is only supported on Apple platforms") endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b7fd67fe..271bf00a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,18 +13,24 @@ if(MSVC) add_compile_definitions(WIN32_LEAN_AND_MEAN CURL_STATICLIB) elseif(UNIX) if(APPLE) - add_compile_definitions( - _XOPEN_SOURCE - VK_USE_PLATFORM_MACOS_MVK - VK_USE_PLATFORM_METAL_EXT - ) + if (ENABLE_VULKAN) + add_compile_definitions( + _XOPEN_SOURCE + VK_USE_PLATFORM_MACOS_MVK + VK_USE_PLATFORM_METAL_EXT + ) + else() + add_compile_definitions(_XOPEN_SOURCE) + endif() else() - add_compile_definitions( - VK_USE_PLATFORM_XLIB_KHR # legacy. Do we need to support XLIB surfaces? - VK_USE_PLATFORM_XCB_KHR - ) - if (ENABLE_WAYLAND) - add_compile_definitions(VK_USE_PLATFORM_WAYLAND_KHR) + if (ENABLE_VULKAN) + add_compile_definitions( + VK_USE_PLATFORM_XLIB_KHR # legacy. Do we need to support XLIB surfaces? + VK_USE_PLATFORM_XCB_KHR + ) + if (ENABLE_WAYLAND) + add_compile_definitions(VK_USE_PLATFORM_WAYLAND_KHR) + endif() endif() endif() # warnings @@ -35,7 +41,9 @@ elseif(UNIX) add_compile_options(-Wno-multichar -Wno-invalid-offsetof -Wno-switch -Wno-ignored-attributes -Wno-deprecated-enum-enum-conversion) endif() -add_compile_definitions(VK_NO_PROTOTYPES) +if (ENABLE_VULKAN) + add_compile_definitions(VK_NO_PROTOTYPES) +endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -113,42 +121,38 @@ if (MACOS_BUNDLE) COMMAND ${CMAKE_COMMAND} ARGS -E copy_directory "${CMAKE_SOURCE_DIR}/bin/${folder}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/SharedSupport/${folder}") endforeach(folder) - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(LIBUSB_PATH "${CMAKE_BINARY_DIR}/vcpkg_installed/${VCPKG_TARGET_TRIPLET}/debug/lib/libusb-1.0.0.dylib") - else() - set(LIBUSB_PATH "${CMAKE_BINARY_DIR}/vcpkg_installed/${VCPKG_TARGET_TRIPLET}/lib/libusb-1.0.0.dylib") + if (ENABLE_VULKAN) + if (EXISTS "/usr/local/lib/libMoltenVK.dylib") + set(MOLTENVK_PATH "/usr/local/lib/libMoltenVK.dylib") + elseif (EXISTS "/opt/homebrew/lib/libMoltenVK.dylib") + set(MOLTENVK_PATH "/opt/homebrew/lib/libMoltenVK.dylib") + else() + message(FATAL_ERROR "failed to find libMoltenVK.dylib") + endif () + + add_custom_command (TARGET CemuBin POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy "${MOLTENVK_PATH}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib" + COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_SOURCE_DIR}/src/resource/update.sh" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/update.sh" + COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}") endif() - - if (EXISTS "/usr/local/lib/libMoltenVK.dylib") - set(MOLTENVK_PATH "/usr/local/lib/libMoltenVK.dylib") - elseif (EXISTS "/opt/homebrew/lib/libMoltenVK.dylib") - set(MOLTENVK_PATH "/opt/homebrew/lib/libMoltenVK.dylib") - else() - message(FATAL_ERROR "failed to find libMoltenVK.dylib") - endif () - - add_custom_command (TARGET CemuBin POST_BUILD - COMMAND ${CMAKE_COMMAND} ARGS -E copy "${MOLTENVK_PATH}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib" - COMMAND ${CMAKE_COMMAND} ARGS -E copy "${LIBUSB_PATH}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libusb-1.0.0.dylib" - COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_SOURCE_DIR}/src/resource/update.sh" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/update.sh" - COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}" - COMMAND install_name_tool -change @rpath/libusb-1.0.0.dylib @executable_path/../Frameworks/libusb-1.0.0.dylib ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}) else() if(APPLE) - find_library(MOLTENVK_LIBRARY - NAMES MoltenVK moltenvk libMoltenVK.dylib - PATHS /usr/local/lib /opt/homebrew/lib - ) - if(MOLTENVK_LIBRARY) - message(STATUS "Found MoltenVK: ${MOLTENVK_LIBRARY}") - target_link_libraries(CemuBin PRIVATE ${MOLTENVK_LIBRARY}) - else() - message(WARNING "libMoltenVK.dylib not found") - endif() - set_target_properties(CemuBin PROPERTIES - BUILD_WITH_INSTALL_RPATH TRUE - INSTALL_RPATH "/usr/local/lib;/opt/homebrew/lib" - ) + if (ENABLE_VULKAN) + find_library(MOLTENVK_LIBRARY + NAMES MoltenVK moltenvk libMoltenVK.dylib + PATHS /usr/local/lib /opt/homebrew/lib + ) + if(MOLTENVK_LIBRARY) + message(STATUS "Found MoltenVK: ${MOLTENVK_LIBRARY}") + target_link_libraries(CemuBin PRIVATE ${MOLTENVK_LIBRARY}) + else() + message(WARNING "libMoltenVK.dylib not found") + endif() + set_target_properties(CemuBin PROPERTIES + BUILD_WITH_INSTALL_RPATH TRUE + INSTALL_RPATH "/usr/local/lib;/opt/homebrew/lib" + ) + endif() endif() endif() diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index 78a8cce0..2b9d8e28 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -162,58 +162,12 @@ add_library(CemuCafe HW/Latte/LegacyShaderDecompiler/LatteDecompilerInstructions.h HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h HW/Latte/LegacyShaderDecompiler/LatteDecompilerRegisterDataTypeTracker.cpp - HW/Latte/Renderer/OpenGL/CachedFBOGL.h - HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp - HW/Latte/Renderer/OpenGL/LatteTextureGL.h - HW/Latte/Renderer/OpenGL/LatteTextureViewGL.cpp - HW/Latte/Renderer/OpenGL/LatteTextureViewGL.h - HW/Latte/Renderer/OpenGL/OpenGLQuery.cpp - HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp - HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp - HW/Latte/Renderer/OpenGL/OpenGLRenderer.h - HW/Latte/Renderer/OpenGL/OpenGLRendererStreamout.cpp - HW/Latte/Renderer/OpenGL/OpenGLRendererUniformData.cpp - HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp - HW/Latte/Renderer/OpenGL/OpenGLTextureReadback.h - HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp - HW/Latte/Renderer/OpenGL/RendererShaderGL.h - HW/Latte/Renderer/OpenGL/TextureReadbackGL.cpp HW/Latte/Renderer/Renderer.cpp HW/Latte/Renderer/Renderer.h HW/Latte/Renderer/RendererOuputShader.cpp HW/Latte/Renderer/RendererOuputShader.h HW/Latte/Renderer/RendererShader.cpp HW/Latte/Renderer/RendererShader.h - HW/Latte/Renderer/Vulkan/CachedFBOVk.cpp - HW/Latte/Renderer/Vulkan/CachedFBOVk.h - HW/Latte/Renderer/Vulkan/CocoaSurface.h - HW/Latte/Renderer/Vulkan/LatteTextureViewVk.cpp - HW/Latte/Renderer/Vulkan/LatteTextureViewVk.h - HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp - HW/Latte/Renderer/Vulkan/LatteTextureVk.h - HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp - HW/Latte/Renderer/Vulkan/RendererShaderVk.h - HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp - HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h - HW/Latte/Renderer/Vulkan/TextureReadbackVk.cpp - HW/Latte/Renderer/Vulkan/VKRBase.h - HW/Latte/Renderer/Vulkan/VKRMemoryManager.cpp - HW/Latte/Renderer/Vulkan/VKRMemoryManager.h - HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp - HW/Latte/Renderer/Vulkan/VsyncDriver.cpp - HW/Latte/Renderer/Vulkan/VsyncDriver.h - HW/Latte/Renderer/Vulkan/VulkanAPI.cpp - HW/Latte/Renderer/Vulkan/VulkanAPI.h - HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp - HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.h - HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp - HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.h - HW/Latte/Renderer/Vulkan/VulkanQuery.cpp - HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp - HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp - HW/Latte/Renderer/Vulkan/VulkanRenderer.h - HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp - HW/Latte/Renderer/Vulkan/VulkanTextureReadback.h HW/Latte/ShaderInfo/ShaderDescription.cpp HW/Latte/ShaderInfo/ShaderInfo.h HW/Latte/ShaderInfo/ShaderInstanceInfo.cpp @@ -539,12 +493,72 @@ add_library(CemuCafe TitleList/TitleList.h ) +if (ENABLE_OPENGL) + target_sources(CemuCafe PRIVATE + HW/Latte/Renderer/OpenGL/CachedFBOGL.h + HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp + HW/Latte/Renderer/OpenGL/LatteTextureGL.h + HW/Latte/Renderer/OpenGL/LatteTextureViewGL.cpp + HW/Latte/Renderer/OpenGL/LatteTextureViewGL.h + HW/Latte/Renderer/OpenGL/OpenGLQuery.cpp + HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp + HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp + HW/Latte/Renderer/OpenGL/OpenGLRenderer.h + HW/Latte/Renderer/OpenGL/OpenGLRendererStreamout.cpp + HW/Latte/Renderer/OpenGL/OpenGLRendererUniformData.cpp + HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp + HW/Latte/Renderer/OpenGL/OpenGLTextureReadback.h + HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp + HW/Latte/Renderer/OpenGL/RendererShaderGL.h + HW/Latte/Renderer/OpenGL/TextureReadbackGL.cpp + ) +endif() + +if (ENABLE_VULKAN) + target_sources(CemuCafe PRIVATE + HW/Latte/Renderer/Vulkan/CachedFBOVk.cpp + HW/Latte/Renderer/Vulkan/CachedFBOVk.h + HW/Latte/Renderer/Vulkan/CocoaSurface.h + HW/Latte/Renderer/Vulkan/LatteTextureViewVk.cpp + HW/Latte/Renderer/Vulkan/LatteTextureViewVk.h + HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp + HW/Latte/Renderer/Vulkan/LatteTextureVk.h + HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp + HW/Latte/Renderer/Vulkan/RendererShaderVk.h + HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp + HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h + HW/Latte/Renderer/Vulkan/TextureReadbackVk.cpp + HW/Latte/Renderer/Vulkan/VKRBase.h + HW/Latte/Renderer/Vulkan/VKRMemoryManager.cpp + HW/Latte/Renderer/Vulkan/VKRMemoryManager.h + HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp + HW/Latte/Renderer/Vulkan/VsyncDriver.cpp + HW/Latte/Renderer/Vulkan/VsyncDriver.h + HW/Latte/Renderer/Vulkan/VulkanAPI.cpp + HW/Latte/Renderer/Vulkan/VulkanAPI.h + HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp + HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.h + HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp + HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.h + HW/Latte/Renderer/Vulkan/VulkanQuery.cpp + HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp + HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp + HW/Latte/Renderer/Vulkan/VulkanRenderer.h + HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp + HW/Latte/Renderer/Vulkan/VulkanTextureReadback.h + ) +endif() + if(APPLE) target_sources(CemuCafe PRIVATE - HW/Latte/Renderer/Vulkan/CocoaSurface.mm HW/Latte/Renderer/MetalView.mm HW/Latte/Renderer/MetalView.h ) + if (ENABLE_VULKAN) + target_sources(CemuCafe PRIVATE + HW/Latte/Renderer/Vulkan/CocoaSurface.mm + ) + endif() endif() if(ENABLE_METAL) diff --git a/src/Cafe/HW/Latte/Core/LatteBufferData.cpp b/src/Cafe/HW/Latte/Core/LatteBufferData.cpp index 7620e6a7..9d606e72 100644 --- a/src/Cafe/HW/Latte/Core/LatteBufferData.cpp +++ b/src/Cafe/HW/Latte/Core/LatteBufferData.cpp @@ -9,7 +9,9 @@ #include "Cafe/GameProfile/GameProfile.h" #include "Cafe/HW/Latte/Core/LatteBufferCache.h" +#ifdef ENABLE_VULKAN #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h" +#endif template void rectGenerate4thVertex(uint32be* output, uint32be* input0, uint32be* input1, uint32be* input2) @@ -199,6 +201,7 @@ bool LatteBufferCache_Sync(uint32 minIndex, uint32 maxIndex, uint32 baseInstance #if BOOST_OS_MACOS if(bufferStride % 4 != 0) { + #ifdef ENABLE_VULKAN if (g_renderer->GetType() == RendererAPI::Vulkan) { if (VulkanRenderer* vkRenderer = VulkanRenderer::GetInstance()) @@ -208,6 +211,7 @@ bool LatteBufferCache_Sync(uint32 minIndex, uint32 maxIndex, uint32 baseInstance continue; } } + #endif } #endif diff --git a/src/Cafe/HW/Latte/Core/LatteShader.cpp b/src/Cafe/HW/Latte/Core/LatteShader.cpp index 91de6310..2f9bac94 100644 --- a/src/Cafe/HW/Latte/Core/LatteShader.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShader.cpp @@ -6,7 +6,9 @@ #include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h" #include "Cafe/HW/Latte/Core/FetchShader.h" #include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h" +#ifdef ENABLE_VULKAN #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h" +#endif #include "Cafe/OS/libs/gx2/GX2.h" // todo - remove dependency #include "Cafe/GraphicPack/GraphicPack2.h" #include "HW/Latte/Core/Latte.h" @@ -683,20 +685,69 @@ uint64 LatteSHRC_CalcPSAuxHash(LatteDecompilerShader* pixelShader, uint32* conte return auxHash; } +void InitUniformLayoutFromDecompiler( + LatteDecompilerShader* shader, + const LatteDecompilerOutput_t& decompilerOutput +) +{ + const auto& offsets = decompilerOutput.uniformOffsetsVK; + + shader->uniform.loc_remapped = offsets.offset_remapped; + shader->uniform.loc_uniformRegister = offsets.offset_uniformRegister; + shader->uniform.count_uniformRegister = offsets.count_uniformRegister; + shader->uniform.loc_windowSpaceToClipSpaceTransform = offsets.offset_windowSpaceToClipSpaceTransform; + shader->uniform.loc_alphaTestRef = offsets.offset_alphaTestRef; + shader->uniform.loc_pointSize = offsets.offset_pointSize; + shader->uniform.loc_fragCoordScale = offsets.offset_fragCoordScale; + + // Texture scale uniforms + shader->uniform.list_ufTexRescale.clear(); + for (sint32 t = 0; t < LATTE_NUM_MAX_TEX_UNITS; t++) + { + if (offsets.offset_texScale[t] >= 0) + { + LatteUniformTextureScaleEntry_t entry{}; + entry.texUnit = t; + entry.uniformLocation = offsets.offset_texScale[t]; + shader->uniform.list_ufTexRescale.push_back(entry); + } + } + + shader->uniform.loc_verticesPerInstance = offsets.offset_verticesPerInstance; + + // Streamout buffers + for (sint32 t = 0; t < LATTE_NUM_STREAMOUT_BUFFER; t++) + { + shader->uniform.loc_streamoutBufferBase[t] = offsets.offset_streamoutBufferBase[t]; + } + + shader->uniform.uniformRangeSize = offsets.offset_endOfBlock; +} + LatteDecompilerShader* LatteShader_CreateShaderFromDecompilerOutput(LatteDecompilerOutput_t& decompilerOutput, uint64 baseHash, bool calculateAuxHash, uint64 optionalAuxHash, uint32* contextRegister) { LatteDecompilerShader* shader = decompilerOutput.shader; shader->baseHash = baseHash; // copy resource mapping // HACK - if (g_renderer->GetType() == RendererAPI::OpenGL) + switch (g_renderer->GetType()) + { +#ifdef ENABLE_OPENGL + case RendererAPI::OpenGL: shader->resourceMapping = decompilerOutput.resourceMappingGL; - else if (g_renderer->GetType() == RendererAPI::Vulkan) - shader->resourceMapping = decompilerOutput.resourceMappingVK; -#if ENABLE_METAL - else - shader->resourceMapping = decompilerOutput.resourceMappingMTL; + break; #endif +#ifdef ENABLE_VULKAN + case RendererAPI::Vulkan: + shader->resourceMapping = decompilerOutput.resourceMappingVK; + break; +#endif +#if ENABLE_METAL + case RendererAPI::Metal: + shader->resourceMapping = decompilerOutput.resourceMappingMTL; + break; +#endif + } // copy texture info shader->textureUnitMask2 = decompilerOutput.textureUnitMask; // copy streamout info @@ -705,33 +756,23 @@ LatteDecompilerShader* LatteShader_CreateShaderFromDecompilerOutput(LatteDecompi // copy uniform offsets // for OpenGL these are retrieved in _prepareSeparableUniforms() // HACK - if (g_renderer->GetType() == RendererAPI::Vulkan || g_renderer->GetType() == RendererAPI::Metal) - { - shader->uniform.loc_remapped = decompilerOutput.uniformOffsetsVK.offset_remapped; - shader->uniform.loc_uniformRegister = decompilerOutput.uniformOffsetsVK.offset_uniformRegister; - shader->uniform.count_uniformRegister = decompilerOutput.uniformOffsetsVK.count_uniformRegister; - shader->uniform.loc_windowSpaceToClipSpaceTransform = decompilerOutput.uniformOffsetsVK.offset_windowSpaceToClipSpaceTransform; - shader->uniform.loc_alphaTestRef = decompilerOutput.uniformOffsetsVK.offset_alphaTestRef; - shader->uniform.loc_pointSize = decompilerOutput.uniformOffsetsVK.offset_pointSize; - shader->uniform.loc_fragCoordScale = decompilerOutput.uniformOffsetsVK.offset_fragCoordScale; - for (sint32 t = 0; t < LATTE_NUM_MAX_TEX_UNITS; t++) - { - if (decompilerOutput.uniformOffsetsVK.offset_texScale[t] >= 0) - { - LatteUniformTextureScaleEntry_t entry = { 0 }; - entry.texUnit = t; - entry.uniformLocation = decompilerOutput.uniformOffsetsVK.offset_texScale[t]; - shader->uniform.list_ufTexRescale.push_back(entry); - } - } - shader->uniform.loc_verticesPerInstance = decompilerOutput.uniformOffsetsVK.offset_verticesPerInstance; - for (sint32 t = 0; t < LATTE_NUM_STREAMOUT_BUFFER; t++) - shader->uniform.loc_streamoutBufferBase[t] = decompilerOutput.uniformOffsetsVK.offset_streamoutBufferBase[t]; - shader->uniform.uniformRangeSize = decompilerOutput.uniformOffsetsVK.offset_endOfBlock; - } - else + switch (g_renderer->GetType()) { +#ifdef ENABLE_OPENGL + case RendererAPI::OpenGL: shader->uniform.count_uniformRegister = decompilerOutput.uniformOffsetsGL.count_uniformRegister; + break; +#endif +#ifdef ENABLE_VULKAN + case RendererAPI::Vulkan: + InitUniformLayoutFromDecompiler(shader, decompilerOutput); + break; +#endif +#if ENABLE_METAL + case RendererAPI::Metal: + InitUniformLayoutFromDecompiler(shader, decompilerOutput); + break; +#endif } // calculate aux hash if (calculateAuxHash) @@ -766,10 +807,12 @@ void LatteShader_GetDecompilerOptions(LatteDecompilerOptions& options, LatteCons options.usesGeometryShader = geometryShaderEnabled; options.spirvInstrinsics.hasRoundingModeRTEFloat32 = false; options.useTFViaSSBO = g_renderer->UseTFViaSSBO(); + #ifdef ENABLE_VULKAN if (g_renderer->GetType() == RendererAPI::Vulkan) { options.spirvInstrinsics.hasRoundingModeRTEFloat32 = VulkanRenderer::GetInstance()->HasSPRIVRoundingModeRTE32(); } + #endif options.strictMul = g_current_game_profile->GetAccurateShaderMul() != AccurateShaderMulOption::False; } diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index 14a1f9b0..d723797d 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -9,13 +9,17 @@ #include "WindowSystem.h" #include "Cafe/HW/Latte/Renderer/Renderer.h" +#ifdef ENABLE_OPENGL #include "Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h" +#endif +#ifdef ENABLE_VULKAN #include "Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h" +#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.h" +#endif #if ENABLE_METAL #include "Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h" #endif -#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.h" #include #include "imgui/imgui_extension.h" @@ -273,13 +277,23 @@ static BootSoundPlayer g_bootSndPlayer; void LatteShaderCache_finish() { - if (g_renderer->GetType() == RendererAPI::Vulkan) + switch (g_renderer->GetType()) + { +#ifdef ENABLE_VULKAN + case: RendererAPI::Vulkan: RendererShaderVk::ShaderCacheLoading_end(); - else if (g_renderer->GetType() == RendererAPI::OpenGL) + return; +#endif +#ifdef ENABLE_OPENGL + case RendererAPI::OpenGL: RendererShaderGL::ShaderCacheLoading_end(); + return; + } +#endif #if ENABLE_METAL - else if (g_renderer->GetType() == RendererAPI::Metal) - RendererShaderMtl::ShaderCacheLoading_end(); + case RendererAPI::Metal: + RendererShaderMtl::ShaderCacheLoading_end(); + return; #endif } @@ -359,14 +373,24 @@ void LatteShaderCache_Load() fs::create_directories(ActiveSettings::GetCachePath("shaderCache/transferable"), ec); fs::create_directories(ActiveSettings::GetCachePath("shaderCache/precompiled"), ec); // initialize renderer specific caches - if (g_renderer->GetType() == RendererAPI::Vulkan) + switch(g_renderer->GetType()) + { +#ifdef ENABLE_VULKAN + case: RendererAPI::Vulkan RendererShaderVk::ShaderCacheLoading_begin(cacheTitleId); - else if (g_renderer->GetType() == RendererAPI::OpenGL) - RendererShaderGL::ShaderCacheLoading_begin(cacheTitleId); -#if ENABLE_METAL - else if (g_renderer->GetType() == RendererAPI::Metal) - RendererShaderMtl::ShaderCacheLoading_begin(cacheTitleId); + break; #endif +#ifdef ENABLE_OPENGL + case: RendererAPI::OpenGL: + RendererShaderGL::ShaderCacheLoading_begin(cacheTitleId); + break; +#endif +#if ENABLE_METAL + case: RendererAPI::Metal: + RendererShaderMtl::ShaderCacheLoading_begin(cacheTitleId); + break; +#endif + } // get cache file name fs::path pathGeneric; @@ -634,31 +658,52 @@ void LatteShaderCache_ShowProgress(const std::function & loadUpdateF void LatteShaderCache_LoadPipelineCache(uint64 cacheTitleId) { - if (g_renderer->GetType() == RendererAPI::Vulkan) + switch(g_renderer->GetType()) + { + #ifdef ENABLE_VULKAN + case RendererAPI::Vulkan: g_shaderCacheLoaderState.pipelineFileCount = VulkanPipelineStableCache::GetInstance().BeginLoading(cacheTitleId); + break; + #endif #if ENABLE_METAL - else if (g_renderer->GetType() == RendererAPI::Metal) + case RendererAPI::Metal: g_shaderCacheLoaderState.pipelineFileCount = MetalPipelineCache::GetInstance().BeginLoading(cacheTitleId); + break; #endif + } + g_shaderCacheLoaderState.loadedPipelines = 0; LatteShaderCache_ShowProgress(LatteShaderCache_updatePipelineLoadingProgress, true); - if (g_renderer->GetType() == RendererAPI::Vulkan) + + switch(g_renderer->GetType()) + { +#ifdef ENABLE_VULKAN + case RendererAPI::Vulkan: VulkanPipelineStableCache::GetInstance().EndLoading(); -#if ENABLE_METAL - else if (g_renderer->GetType() == RendererAPI::Metal) - MetalPipelineCache::GetInstance().EndLoading(); + break; #endif +#if ENABLE_METAL + case RendererAPI::Metal: + MetalPipelineCache::GetInstance().EndLoading(); + break; +#endif + } } bool LatteShaderCache_updatePipelineLoadingProgress() { uint32 pipelinesMissingShaders = 0; - if (g_renderer->GetType() == RendererAPI::Vulkan) + switch(g_renderer->GetType()) + { +#ifdef ENABLE_VULKAN + case RendererAPI::Vulkan: return VulkanPipelineStableCache::GetInstance().UpdateLoading(g_shaderCacheLoaderState.loadedPipelines, pipelinesMissingShaders); +#endif #if ENABLE_METAL - else if (g_renderer->GetType() == RendererAPI::Metal) + case RendererAPI::Metal: return MetalPipelineCache::GetInstance().UpdateLoading(g_shaderCacheLoaderState.loadedPipelines, pipelinesMissingShaders); #endif + } return false; } @@ -918,20 +963,36 @@ void LatteShaderCache_Close() delete s_shaderCacheGeneric; s_shaderCacheGeneric = nullptr; } - if (g_renderer->GetType() == RendererAPI::Vulkan) + switch(g_renderer->GetType()) + { +#ifdef ENABLE_VULKAN + case RendererAPI::Vulkan: RendererShaderVk::ShaderCacheLoading_Close(); - else if (g_renderer->GetType() == RendererAPI::OpenGL) + break; +#endif +#ifdef ENABLE_OPENGL + case RendererAPI::OpenGL: RendererShaderGL::ShaderCacheLoading_Close(); + break; +#endif #if ENABLE_METAL - else if (g_renderer->GetType() == RendererAPI::Metal) - RendererShaderMtl::ShaderCacheLoading_Close(); + case RendererAPI::Metal: + RendererShaderMtl::ShaderCacheLoading_Close(); + break; #endif // if Vulkan or Metal then also close pipeline cache - if (g_renderer->GetType() == RendererAPI::Vulkan) - VulkanPipelineStableCache::GetInstance().Close(); + switch(g_renderer->GetType()) + { + #ifdef ENABLE_VULKAN + case: RendererAPI::Vulkan: + VulkanPipelineStableCache::GetInstance().Close(); + break; + #endif #if ENABLE_METAL - else if (g_renderer->GetType() == RendererAPI::Metal) - MetalPipelineCache::GetInstance().Close(); + case: RendererAPI::Metal: + MetalPipelineCache::GetInstance().Close(); + break; #endif + } } diff --git a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp index 4c11e57c..f54cf064 100644 --- a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp +++ b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp @@ -4,9 +4,11 @@ #include "Cafe/HW/Latte/Renderer/Renderer.h" +#ifdef ENABLE_OPENGL #include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h" #include "Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.h" #include "Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.h" +#endif struct TexScaleXY { @@ -192,6 +194,7 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u LatteGPUState.repeatTextureInitialization = true; } + #ifdef ENABLE_OPENGL if (g_renderer->GetType() == RendererAPI::OpenGL) { // on OpenGL, texture views and sampler parameters are tied together (we are avoiding sampler objects due to driver bugs) @@ -214,6 +217,7 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u textureView->lastTextureBindIndex = LatteGPUState.textureBindCounter; rendererGL->renderstate_updateTextureSettingsGL(shaderContext, textureView, textureIndex + glBackendBaseTexUnit, word4, textureIndex, isDepthSampler); } + #endif g_renderer->texture_setLatteTexture(textureView, textureIndex + glBackendBaseTexUnit); // update if data changed bool swizzleChanged = false; diff --git a/src/Cafe/HW/Latte/Core/LatteTextureReadback.cpp b/src/Cafe/HW/Latte/Core/LatteTextureReadback.cpp index 8df5dcea..b0a6bdf5 100644 --- a/src/Cafe/HW/Latte/Core/LatteTextureReadback.cpp +++ b/src/Cafe/HW/Latte/Core/LatteTextureReadback.cpp @@ -6,7 +6,9 @@ #include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Cafe/HW/Latte/Core/LatteTexture.h" +#ifdef ENABLE_OPENGL #include "Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.h" +#endif #define LOG_READBACK_TIME diff --git a/src/Cafe/HW/Latte/Core/LatteTiming.cpp b/src/Cafe/HW/Latte/Core/LatteTiming.cpp index 115b60d9..60f4c52d 100644 --- a/src/Cafe/HW/Latte/Core/LatteTiming.cpp +++ b/src/Cafe/HW/Latte/Core/LatteTiming.cpp @@ -1,6 +1,8 @@ #include "Cafe/HW/Latte/Core/Latte.h" #include "Cafe/OS/libs/gx2/GX2_Event.h" +#ifdef ENABLE_VULKAN #include "Cafe/HW/Latte/Renderer/Vulkan/VsyncDriver.h" +#endif #include "util/highresolutiontimer/HighResolutionTimer.h" #include "config/CemuConfig.h" #include "Cafe/CafeSystem.h" @@ -55,8 +57,10 @@ void LatteTiming_EnableHostDrivenVSync() { if (s_usingHostDrivenVSync) return; + #ifdef ENABLE_VULKAN VsyncDriver_startThread(LatteTiming_NotifyHostVSync); s_usingHostDrivenVSync = true; + #endif } bool LatteTiming_IsUsingHostDrivenVSync() diff --git a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp index a4f538a8..3c417e2b 100644 --- a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp +++ b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp @@ -1,5 +1,9 @@ #include "Cafe/HW/Latte/Renderer/RendererOuputShader.h" +#include "Cafe/HW/Latte/Renderer/Renderer.h" +#include "Cafe/HW/Latte/Core/Latte.h" +#ifdef ENABLE_OPENGL #include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h" +#endif #include "config/ActiveSettings.h" const std::string RendererOutputShader::s_copy_shader_source = diff --git a/src/config/ActiveSettings.cpp b/src/config/ActiveSettings.cpp index 862ac6c3..9ab146a4 100644 --- a/src/config/ActiveSettings.cpp +++ b/src/config/ActiveSettings.cpp @@ -1,7 +1,9 @@ #include "Cafe/GameProfile/GameProfile.h" #include "Cafe/IOSU/legacy/iosu_crypto.h" #include "Cafe/HW/Latte/Core/Latte.h" +#ifdef ENABLE_VULKAN #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h" +#endif #include "Cafe/CafeSystem.h" #include "Cemu/Logging/CemuLogging.h" #include "config/ActiveSettings.h" @@ -107,9 +109,12 @@ bool ActiveSettings::WaitForGX2DrawDoneEnabled() GraphicAPI ActiveSettings::GetGraphicsAPI() { GraphicAPI api = g_current_game_profile->GetGraphicsAPI().value_or(GetConfig().graphic_api); + + #ifdef ENABLE_VULKAN && HAS_OPENGL // check if vulkan even available if (api == kVulkan && !g_vulkan_available) api = kOpenGL; + #endif return api; } diff --git a/src/gui/wxgui/CMakeLists.txt b/src/gui/wxgui/CMakeLists.txt index 12fc62d9..7c7dc05e 100644 --- a/src/gui/wxgui/CMakeLists.txt +++ b/src/gui/wxgui/CMakeLists.txt @@ -1,9 +1,5 @@ add_library(CemuWxGui STATIC canvas/IRenderCanvas.h - canvas/OpenGLCanvas.cpp - canvas/OpenGLCanvas.h - canvas/VulkanCanvas.cpp - canvas/VulkanCanvas.h CemuApp.cpp CemuApp.h CemuUpdateWindow.cpp @@ -116,6 +112,20 @@ add_library(CemuWxGui STATIC wxHelper.h ) +if (ENABLE_OPENGL) + target_sources(CemuWxGui PRIVATE + canvas/OpenGLCanvas.cpp + canvas/OpenGLCanvas.h + ) +endif() + +if (ENABLE_VULKAN) + target_sources(CemuWxGui PRIVATE + canvas/VulkanCanvas.cpp + canvas/VulkanCanvas.h + ) +endif() + if (ENABLE_METAL) target_sources(CemuWxGui PRIVATE canvas/MetalCanvas.cpp diff --git a/src/gui/wxgui/CemuApp.cpp b/src/gui/wxgui/CemuApp.cpp index a900f10b..4160acb6 100644 --- a/src/gui/wxgui/CemuApp.cpp +++ b/src/gui/wxgui/CemuApp.cpp @@ -3,7 +3,9 @@ #include "wxgui/MainWindow.h" #include "wxgui/wxgui.h" #include "config/CemuConfig.h" +#ifdef ENABLE_VULKAN #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h" +#endif #include "Cafe/HW/Latte/Core/LatteOverlay.h" #include "config/ActiveSettings.h" #include "config/LaunchSettings.h" @@ -349,7 +351,9 @@ bool CemuApp::OnInit() __fastfail(0); } #endif + #ifdef ENABLE_VULKAN InitializeGlobalVulkan(); + #endif Bind(wxEVT_ACTIVATE_APP, &CemuApp::ActivateApp, this); diff --git a/src/gui/wxgui/MainWindow.cpp b/src/gui/wxgui/MainWindow.cpp index 4ef4fe08..4efb172a 100644 --- a/src/gui/wxgui/MainWindow.cpp +++ b/src/gui/wxgui/MainWindow.cpp @@ -11,8 +11,12 @@ #include "wxgui/windows/TextureRelationViewer/TextureRelationWindow.h" #include "wxgui/windows/PPCThreadsViewer/DebugPPCThreadsWindow.h" #include "AudioDebuggerWindow.h" +#ifdef ENABLE_OPENGL #include "wxgui/canvas/OpenGLCanvas.h" +#endif +#ifdef ENABLE_VULKAN #include "wxgui/canvas/VulkanCanvas.h" +#endif #if ENABLE_METAL #include "wxgui/canvas/MetalCanvas.h" #endif @@ -42,7 +46,9 @@ #include "wxgui/DownloadGraphicPacksWindow.h" #include "wxgui/GettingStartedDialog.h" #include "wxgui/helpers/wxHelpers.h" +#ifdef ENABLE_VULKAN #include "Cafe/HW/Latte/Renderer/Vulkan/VsyncDriver.h" +#endif #include "wxgui/input/InputSettings2.h" #include "wxgui/input/HotkeySettings.h" #include "input/InputManager.h" @@ -1601,15 +1607,25 @@ void MainWindow::CreateCanvas() this->GetSizer()->Add(m_game_panel, 1, wxEXPAND); // create canvas - if (ActiveSettings::GetGraphicsAPI() == kVulkan) + if (ActiveSettings::GetGraphicsAPI() == kVulkan) + { + #ifdef ENABLE_VULKAN m_render_canvas = new VulkanCanvas(m_game_panel, wxSize(1280, 720), true); + #endif + } else if (ActiveSettings::GetGraphicsAPI() == kOpenGL) + { + #ifdef ENABLE_OPENGL m_render_canvas = GLCanvas_Create(m_game_panel, wxSize(1280, 720), true); + #endif + } #if ENABLE_METAL else m_render_canvas = new MetalCanvas(m_game_panel, wxSize(1280, 720), true); #endif + cemu_assert(m_render_canvas != nullptr); + // mouse events m_render_canvas->Bind(wxEVT_MOTION, &MainWindow::OnMouseMove, this); m_render_canvas->Bind(wxEVT_MOUSEWHEEL, &MainWindow::OnMouseWheel, this); @@ -1670,7 +1686,9 @@ void MainWindow::OnSizeEvent(wxSizeEvent& event) event.Skip(); + #ifdef ENABLE_VULKAN VsyncDriver_notifyWindowPosChanged(); + #endif } void MainWindow::OnDPIChangedEvent(wxDPIChangedEvent& event) @@ -1691,7 +1709,9 @@ void MainWindow::OnMove(wxMoveEvent& event) if (m_debugger_window && m_debugger_window->IsShown()) m_debugger_window->OnParentMove(GetPosition(), GetSize()); + #ifdef ENABLE_VULKAN VsyncDriver_notifyWindowPosChanged(); + #endif } void MainWindow::OnDebuggerClose(wxCloseEvent& event) diff --git a/src/gui/wxgui/PadViewFrame.cpp b/src/gui/wxgui/PadViewFrame.cpp index 2079f1eb..6bcdb079 100644 --- a/src/gui/wxgui/PadViewFrame.cpp +++ b/src/gui/wxgui/PadViewFrame.cpp @@ -6,8 +6,12 @@ #include "config/ActiveSettings.h" #include "Cafe/OS/libs/swkbd/swkbd.h" +#ifdef ENABLE_OPENGL #include "wxgui/canvas/OpenGLCanvas.h" +#endif +#ifdef ENABLE_VULKAN #include "wxgui/canvas/VulkanCanvas.h" +#endif #if ENABLE_METAL #include "wxgui/canvas/MetalCanvas.h" #endif @@ -76,15 +80,24 @@ void PadViewFrame::InitializeRenderCanvas() auto sizer = new wxBoxSizer(wxVERTICAL); { if (ActiveSettings::GetGraphicsAPI() == kVulkan) + { + #ifdef ENABLE_VULKAN m_render_canvas = new VulkanCanvas(this, wxSize(854, 480), false); + #endif + } else if (ActiveSettings::GetGraphicsAPI() == kOpenGL) + { + #ifdef ENABLE_OPENGL m_render_canvas = GLCanvas_Create(this, wxSize(854, 480), false); + #endif + } #if ENABLE_METAL else m_render_canvas = new MetalCanvas(this, wxSize(854, 480), false); #endif sizer->Add(m_render_canvas, 1, wxEXPAND, 0, nullptr); } + cemu_assert(m_render_canvas != nullptr); SetSizer(sizer); Layout(); diff --git a/src/imgui/CMakeLists.txt b/src/imgui/CMakeLists.txt index e2d669c5..b5e91075 100644 --- a/src/imgui/CMakeLists.txt +++ b/src/imgui/CMakeLists.txt @@ -1,12 +1,22 @@ add_library(imguiImpl - imgui_impl_opengl3.cpp - imgui_impl_opengl3.h - imgui_impl_vulkan.cpp - imgui_impl_vulkan.h imgui_extension.cpp imgui_extension.h ) +if (ENABLE_OPENGL) + target_sources(imguiImpl PRIVATE + imgui_impl_opengl3.cpp + imgui_impl_opengl3.h + ) +endif() + +if (ENABLE_VULKAN) + target_sources(imguiImpl PRIVATE + imgui_impl_vulkan.cpp + imgui_impl_vulkan.h + ) +endif() + if (ENABLE_METAL) target_sources(imguiImpl PRIVATE imgui_impl_metal.mm diff --git a/src/imgui/imgui_extension.cpp b/src/imgui/imgui_extension.cpp index dadd2031..eb0e31ef 100644 --- a/src/imgui/imgui_extension.cpp +++ b/src/imgui/imgui_extension.cpp @@ -2,9 +2,13 @@ #include "WindowSystem.h" #include "Cafe/HW/Latte/Renderer/Renderer.h" #include "resource/IconsFontAwesome5.h" -#include "imgui_impl_opengl3.h" #include "resource/resource.h" +#ifdef ENABLE_OPENGL +#include "imgui_impl_opengl3.h" +#endif +#ifdef ENABLE_VULKAN #include "imgui_impl_vulkan.h" +#endif #include "input/InputManager.h" // diff --git a/src/main.cpp b/src/main.cpp index adce2680..a4e44115 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,7 +19,6 @@ #include "util/helpers/helpers.h" #include "config/ActiveSettings.h" -#include "Cafe/HW/Latte/Renderer/Vulkan/VsyncDriver.h" #include "Cafe/IOSU/legacy/iosu_crypto.h" #include "Cafe/OS/libs/vpad/vpad.h" @@ -65,6 +64,7 @@ void _putenvSafe(const char* c) _putenv(s->c_str()); } +#ifdef ENABLE_OPENGL void reconfigureGLDrivers() { // reconfigure GL drivers to store @@ -85,12 +85,15 @@ void reconfigureGLDrivers() _putenvSafe("__GL_SHADER_DISK_CACHE_SKIP_CLEANUP=1"); } +#endif +#ifdef ENABLE_VULKAN void reconfigureVkDrivers() { _putenvSafe("DISABLE_LAYER_AMD_SWITCHABLE_GRAPHICS_1=1"); _putenvSafe("DISABLE_VK_LAYER_VALVE_steam_fossilize_1=1"); } +#endif void WindowsInitCwd() { @@ -109,8 +112,12 @@ void WindowsInitCwd() void CemuCommonInit() { + #ifdef ENABLE_OPENGL reconfigureGLDrivers(); + #endif + #ifdef ENABLE_VULKAN reconfigureVkDrivers(); + #endif // crypto init AES128_init(); // init PPC timer From d63551c3ca598bd21f3590ff32aa43848cd01424 Mon Sep 17 00:00:00 2001 From: emiyl Date: Mon, 20 Apr 2026 22:52:39 +0100 Subject: [PATCH 02/32] whoopsies syntax errors --- src/Cafe/HW/Latte/Core/LatteShaderCache.cpp | 19 ++++++++++--------- src/gui/wxgui/wxWindowSystem.cpp | 4 ++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index d723797d..2f9b3f13 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -280,7 +280,7 @@ void LatteShaderCache_finish() switch (g_renderer->GetType()) { #ifdef ENABLE_VULKAN - case: RendererAPI::Vulkan: + case RendererAPI::Vulkan: RendererShaderVk::ShaderCacheLoading_end(); return; #endif @@ -288,13 +288,13 @@ void LatteShaderCache_finish() case RendererAPI::OpenGL: RendererShaderGL::ShaderCacheLoading_end(); return; - } #endif #if ENABLE_METAL case RendererAPI::Metal: RendererShaderMtl::ShaderCacheLoading_end(); return; #endif + } } uint32 LatteShaderCache_getShaderCacheExtraVersion(uint64 titleId) @@ -376,17 +376,17 @@ void LatteShaderCache_Load() switch(g_renderer->GetType()) { #ifdef ENABLE_VULKAN - case: RendererAPI::Vulkan + case RendererAPI::Vulkan: RendererShaderVk::ShaderCacheLoading_begin(cacheTitleId); break; #endif #ifdef ENABLE_OPENGL - case: RendererAPI::OpenGL: + case RendererAPI::OpenGL: RendererShaderGL::ShaderCacheLoading_begin(cacheTitleId); break; #endif #if ENABLE_METAL - case: RendererAPI::Metal: + case RendererAPI::Metal: RendererShaderMtl::ShaderCacheLoading_begin(cacheTitleId); break; #endif @@ -980,17 +980,18 @@ void LatteShaderCache_Close() RendererShaderMtl::ShaderCacheLoading_Close(); break; #endif + } // if Vulkan or Metal then also close pipeline cache switch(g_renderer->GetType()) { - #ifdef ENABLE_VULKAN - case: RendererAPI::Vulkan: +#ifdef ENABLE_VULKAN + case RendererAPI::Vulkan: VulkanPipelineStableCache::GetInstance().Close(); break; - #endif +#endif #if ENABLE_METAL - case: RendererAPI::Metal: + case RendererAPI::Metal: MetalPipelineCache::GetInstance().Close(); break; #endif diff --git a/src/gui/wxgui/wxWindowSystem.cpp b/src/gui/wxgui/wxWindowSystem.cpp index 4b199741..d35e0ee8 100644 --- a/src/gui/wxgui/wxWindowSystem.cpp +++ b/src/gui/wxgui/wxWindowSystem.cpp @@ -95,12 +95,16 @@ void WindowSystem::UpdateWindowTitles(bool isIdle, bool isLoading, double fps) { switch (g_renderer->GetType()) { +#ifdef ENABLE_OPENGL case RendererAPI::OpenGL: renderer = "[OpenGL]"; break; +#endif +#ifdef ENABLE_VULKAN case RendererAPI::Vulkan: renderer = "[Vulkan]"; break; +#endif #if ENABLE_METAL case RendererAPI::Metal: renderer = "[Metal]"; From 0bd8c2f06160048c95b2fc08624bc4c397bbf279 Mon Sep 17 00:00:00 2001 From: emiyl Date: Mon, 20 Apr 2026 23:06:52 +0100 Subject: [PATCH 03/32] fix #if in activesettings --- src/config/ActiveSettings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ActiveSettings.cpp b/src/config/ActiveSettings.cpp index 9ab146a4..3352c143 100644 --- a/src/config/ActiveSettings.cpp +++ b/src/config/ActiveSettings.cpp @@ -110,11 +110,11 @@ GraphicAPI ActiveSettings::GetGraphicsAPI() { GraphicAPI api = g_current_game_profile->GetGraphicsAPI().value_or(GetConfig().graphic_api); - #ifdef ENABLE_VULKAN && HAS_OPENGL +#if defined(ENABLE_VULKAN) && defined(ENABLE_OPENGL) // check if vulkan even available if (api == kVulkan && !g_vulkan_available) api = kOpenGL; - #endif +#endif return api; } From cf36aaaf3be1b0ef82215df83ca3086fefc3a735 Mon Sep 17 00:00:00 2001 From: emiyl Date: Mon, 20 Apr 2026 23:08:30 +0100 Subject: [PATCH 04/32] add m_api_map to generalsettings2 and separate vulkan/opengl --- src/gui/wxgui/GeneralSettings2.cpp | 64 ++++++++++++++++++++---------- src/gui/wxgui/GeneralSettings2.h | 4 ++ 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/gui/wxgui/GeneralSettings2.cpp b/src/gui/wxgui/GeneralSettings2.cpp index 003bd130..c8ab14a0 100644 --- a/src/gui/wxgui/GeneralSettings2.cpp +++ b/src/gui/wxgui/GeneralSettings2.cpp @@ -27,8 +27,10 @@ #include "audio/IAudioInputAPI.h" +#ifdef ENABLE_VULKAN #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h" #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h" +#endif #if ENABLE_METAL #include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h" #endif @@ -87,6 +89,7 @@ private: IAudioInputAPI::DeviceDescriptionPtr m_description; }; +#ifdef ENABLE_VULKAN class wxVulkanUUID : public wxClientData { public: @@ -97,6 +100,7 @@ public: private: VulkanRenderer::DeviceInfo m_device_info; }; +#endif #if ENABLE_METAL class wxMetalUUID : public wxClientData @@ -352,15 +356,25 @@ wxPanel* GeneralSettings2::AddGraphicsPage(wxNotebook* notebook) row->Add(new wxStaticText(box, wxID_ANY, _("Graphics API")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); - sint32 api_size = 1; - wxString choices[3] = { "OpenGL" }; + sint32 api_size = 0; + wxString choices[NUM_GRAPHICS_APIS]; + +#ifdef ENABLE_OPENGL + choices[api_size++] = "OpenGL"; + m_api_map.push_back(GraphicAPI::kOpenGL); +#endif +#ifdef ENABLE_VULKAN if (g_vulkan_available) { choices[api_size++] = "Vulkan"; + m_api_map.push_back(GraphicAPI::kVulkan); } +#endif #if ENABLE_METAL choices[api_size++] = "Metal"; + m_api_map.push_back(GraphicAPI::kMetal); #endif + wxASSERT(api_size > 0); m_graphic_api = new wxChoice(box, wxID_ANY, wxDefaultPosition, wxDefaultSize, api_size, choices); m_graphic_api->SetSelection(0); @@ -1219,6 +1233,7 @@ void GeneralSettings2::StoreConfig() config.graphic_api = (GraphicAPI)m_graphic_api->GetSelection(); selection = m_graphic_device->GetSelection(); +#ifdef ENABLE_VULKAN if (config.graphic_api == GraphicAPI::kVulkan) { if (selection != wxNOT_FOUND) @@ -1232,19 +1247,20 @@ void GeneralSettings2::StoreConfig() else config.vk_graphic_device_uuid = {}; } +#endif #if ENABLE_METAL - else if (config.graphic_api == GraphicAPI::kMetal) + if (config.graphic_api == GraphicAPI::kMetal) { - if (selection != wxNOT_FOUND) - { - const auto* info = (wxMetalUUID*)m_graphic_device->GetClientObject(selection); - if (info) - config.mtl_graphic_device_uuid = info->GetDeviceInfo().uuid; - else - config.mtl_graphic_device_uuid = {}; - } - else - config.mtl_graphic_device_uuid = {}; + if (selection != wxNOT_FOUND) + { + const auto* info = (wxMetalUUID*)m_graphic_device->GetClientObject(selection); + if (info) + config.mtl_graphic_device_uuid = info->GetDeviceInfo().uuid; + else + config.mtl_graphic_device_uuid = {}; + } + else + config.mtl_graphic_device_uuid = {}; } #endif @@ -1721,8 +1737,12 @@ void GeneralSettings2::HandleGraphicsApiSelection() selection = GetConfig().vsync; m_vsync->Clear(); - if (m_graphic_api->GetSelection() == 0) + + auto api = m_api_map[m_graphic_api->GetSelection()]; + switch (api) { +#ifdef ENABLE_OPENGL + case GraphicAPI::kOpenGL: // OpenGL m_vsync->AppendString(_("Off")); m_vsync->AppendString(_("On")); @@ -1739,9 +1759,10 @@ void GeneralSettings2::HandleGraphicsApiSelection() #if ENABLE_METAL m_force_mesh_shaders->Disable(); #endif - } - else if (m_graphic_api->GetSelection() == 1) - { + break; +#endif +#ifdef ENABLE_VULKAN + case GraphicAPI::kVulkan: // Vulkan m_gx2drawdone_sync->Disable(); m_async_compile->Enable(); @@ -1779,10 +1800,10 @@ void GeneralSettings2::HandleGraphicsApiSelection() } } } - } + break; + #endif #if ENABLE_METAL - else - { + case GraphicAPI::kMetal: // Metal m_gx2drawdone_sync->Disable(); m_async_compile->Enable(); @@ -1815,6 +1836,7 @@ void GeneralSettings2::HandleGraphicsApiSelection() } } } + break; } #endif } @@ -1870,7 +1892,7 @@ void GeneralSettings2::ApplyConfig() } // graphics - m_graphic_api->SetSelection(config.graphic_api); + m_graphic_api->SetSelection((int)config.graphic_api); m_vsync->SetSelection(config.vsync); m_overrideGamma->SetValue(config.overrideAppGammaPreference); m_overrideGammaValue->SetValue(config.overrideGammaValue); diff --git a/src/gui/wxgui/GeneralSettings2.h b/src/gui/wxgui/GeneralSettings2.h index 634f0cfa..77c5fe49 100644 --- a/src/gui/wxgui/GeneralSettings2.h +++ b/src/gui/wxgui/GeneralSettings2.h @@ -1,4 +1,5 @@ #pragma once +#include "config/CemuConfig.h" #include #include #include @@ -16,6 +17,8 @@ class wxStaticText; wxDECLARE_EVENT(wxEVT_ACCOUNTLIST_REFRESH, wxCommandEvent); +#define NUM_GRAPHICS_APIS 3 + class GeneralSettings2 : public wxDialog { public: @@ -36,6 +39,7 @@ private: bool m_game_launched; bool m_has_account_change = false; // keep track of dirty state of accounts + std::vector m_api_map; // map from dropdown index to GraphicsAPISetting, used in HandleGraphicsApiSelection wxPanel* AddGeneralPage(wxNotebook* notebook); From 5d185dc203d8f89cbc80f9741689ca43fdf1019b Mon Sep 17 00:00:00 2001 From: emiyl Date: Mon, 20 Apr 2026 23:25:18 +0100 Subject: [PATCH 05/32] fix cmake syntax --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 10fd422c..bec2a399 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,10 +117,10 @@ option(ENABLE_DISCORD_RPC "Enables the Discord Rich Presence feature" ON) if (ENABLE_OPENGL) set_compile_definitions(ENABLE_OPENGL) -else() +endif() if (ENABLE_VULKAN) add_compile_definitions(ENABLE_VULKAN) -else() +endif() if (ENABLE_METAL AND NOT APPLE) message(FATAL_ERROR "Metal backend is only supported on Apple platforms") From d65d6d26b8069c431999f687630513ce9b47a3ac Mon Sep 17 00:00:00 2001 From: emiyl Date: Mon, 20 Apr 2026 23:27:08 +0100 Subject: [PATCH 06/32] wrap this switch in braces --- src/gui/wxgui/GeneralSettings2.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/wxgui/GeneralSettings2.cpp b/src/gui/wxgui/GeneralSettings2.cpp index c8ab14a0..6d57b5ac 100644 --- a/src/gui/wxgui/GeneralSettings2.cpp +++ b/src/gui/wxgui/GeneralSettings2.cpp @@ -1743,6 +1743,7 @@ void GeneralSettings2::HandleGraphicsApiSelection() { #ifdef ENABLE_OPENGL case GraphicAPI::kOpenGL: + { // OpenGL m_vsync->AppendString(_("Off")); m_vsync->AppendString(_("On")); @@ -1760,9 +1761,11 @@ void GeneralSettings2::HandleGraphicsApiSelection() m_force_mesh_shaders->Disable(); #endif break; + } #endif #ifdef ENABLE_VULKAN case GraphicAPI::kVulkan: + { // Vulkan m_gx2drawdone_sync->Disable(); m_async_compile->Enable(); @@ -1801,9 +1804,11 @@ void GeneralSettings2::HandleGraphicsApiSelection() } } break; + } #endif #if ENABLE_METAL case GraphicAPI::kMetal: + { // Metal m_gx2drawdone_sync->Disable(); m_async_compile->Enable(); @@ -1838,6 +1843,7 @@ void GeneralSettings2::HandleGraphicsApiSelection() } break; } + } #endif } From becab72c13e3825ad22a4007cdeb28192b4a73d0 Mon Sep 17 00:00:00 2001 From: emiyl Date: Mon, 20 Apr 2026 23:33:37 +0100 Subject: [PATCH 07/32] set_compile_definitions -> add_compile_definitions --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bec2a399..4e5f8ad7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,7 +116,7 @@ option(ENABLE_METAL "Enables the Metal backend" ${ENABLE_METAL_DEFAULT}) option(ENABLE_DISCORD_RPC "Enables the Discord Rich Presence feature" ON) if (ENABLE_OPENGL) - set_compile_definitions(ENABLE_OPENGL) + add_compile_definitions(ENABLE_OPENGL) endif() if (ENABLE_VULKAN) add_compile_definitions(ENABLE_VULKAN) From 3bb486c68e29bf37ed140747136c3daa7a769568 Mon Sep 17 00:00:00 2001 From: emiyl Date: Mon, 20 Apr 2026 23:38:10 +0100 Subject: [PATCH 08/32] another include conditional and another switch for LatteDecompiler.cpp --- .../LatteDecompiler.cpp | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp index 13188743..028ac359 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp @@ -10,7 +10,9 @@ #include "Cafe/HW/Latte/Core/FetchShader.h" #include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h" #include "Cafe/HW/Latte/Renderer/Renderer.h" +#ifdef ENABLE_VULKAN #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h" +#endif #include "util/helpers/helpers.h" // parse instruction and if valid append it to instructionList @@ -1069,12 +1071,24 @@ void _LatteDecompiler_Process(LatteDecompilerShaderContext* shaderContext, uint8 // emit code if (shaderContext->shader->hasError == false) { - if (g_renderer->GetType() == RendererAPI::OpenGL || g_renderer->GetType() == RendererAPI::Vulkan) - LatteDecompiler_emitGLSLShader(shaderContext, shaderContext->shader); -#if ENABLE_METAL - else - LatteDecompiler_emitMSLShader(shaderContext, shaderContext->shader); + switch(g_renderer->GetType()) + { +#ifdef ENABLE_OPENGL + case RendererAPI::OpenGL: + LatteDecompiler_emitGLSLShader(shaderContext, shaderContext->shader); + break; #endif +#ifdef ENABLE_VULKAN + case RendererAPI::Vulkan: + LatteDecompiler_emitGLSLShader(shaderContext, shaderContext->shader); + break; +#endif +#if ENABLE_METAL + case RendererAPI::Metal: + LatteDecompiler_emitMSLShader(shaderContext, shaderContext->shader); + break; +#endif + } } LatteDecompiler_cleanup(shaderContext); // fast access From ed5b73938ca7ffdeade3d2ca80d87088c48e9296 Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 00:34:30 +0100 Subject: [PATCH 09/32] Create CommonRendererCore to move LatteDraw_cleanupAfterFrame away from opengl stuffs --- src/Cafe/CMakeLists.txt | 2 + src/Cafe/HW/Latte/Core/LatteDraw.h | 2 +- src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp | 3 +- .../Renderer/Common/CommonRendererCore.cpp | 155 ++++++++++ .../Renderer/Common/CommonRendererCore.h | 98 ++++++ .../Renderer/OpenGL/OpenGLRendererCore.cpp | 284 +++++------------- 6 files changed, 332 insertions(+), 212 deletions(-) create mode 100644 src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp create mode 100644 src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index 2b9d8e28..f6b427e9 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -168,6 +168,8 @@ add_library(CemuCafe HW/Latte/Renderer/RendererOuputShader.h HW/Latte/Renderer/RendererShader.cpp HW/Latte/Renderer/RendererShader.h + HW/Latte/Renderer/Common/CommonRendererCore.cpp + HW/Latte/Renderer/Common/CommonRendererCore.h HW/Latte/ShaderInfo/ShaderDescription.cpp HW/Latte/ShaderInfo/ShaderInfo.h HW/Latte/ShaderInfo/ShaderInstanceInfo.cpp diff --git a/src/Cafe/HW/Latte/Core/LatteDraw.h b/src/Cafe/HW/Latte/Core/LatteDraw.h index 89c34dc0..37390ae1 100644 --- a/src/Cafe/HW/Latte/Core/LatteDraw.h +++ b/src/Cafe/HW/Latte/Core/LatteDraw.h @@ -1,4 +1,4 @@ #pragma once #include "Common/GLInclude/GLInclude.h" -void LatteDraw_cleanupAfterFrame(); \ No newline at end of file +void CommonRenderer_cleanupAfterFrame(); \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp index 1bdbc4bb..a466b652 100644 --- a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp +++ b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp @@ -10,6 +10,7 @@ #include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h" #include "Cafe/GraphicPack/GraphicPack2.h" +#include "HW/Latte/Renderer/Common/CommonRendererCore.h" #include "config/ActiveSettings.h" #include "WindowSystem.h" #include "Cafe/OS/libs/erreula/erreula.h" @@ -694,7 +695,7 @@ void LatteRenderTarget_itHLESwapScanBuffer() performanceMonitor.gpuTime_frameTime.beginMeasuring(); LatteTC_CleanupUnusedTextures(); - LatteDraw_cleanupAfterFrame(); + CommonRenderer_cleanupAfterFrame(); LatteQuery_CancelActiveGPU7Queries(); LatteBufferCache_notifySwapTVScanBuffer(); LattePerformanceMonitor_frameBegin(); diff --git a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp new file mode 100644 index 00000000..c8dab968 --- /dev/null +++ b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp @@ -0,0 +1,155 @@ +#include "CommonRendererCore.h" + +indexState_t indexState = { 0 }; +AttributePointerCacheEntry_t activeAttributePointer[LATTE_VS_ATTRIBUTE_LIMIT] = { 0 }; + +indexDataCacheEntry2_t* indexDataCacheBucket[INDEX_DATA_CACHE_BUCKETS] = { 0 }; +indexDataCacheEntry2_t* indexDataCacheFirst = nullptr; // points to least recently used item +indexDataCacheEntry2_t* indexDataCacheLast = nullptr; // points to most recently used item +sint32 indexDataCacheEntryCount = 0; + +uint8* CommonRenderer_getAttributePointerCacheVboOutput(uint32 attributeShaderLoc) +{ + return activeAttributePointer[attributeShaderLoc].vboOutput; +} + +void CommonRenderer_setAttributePointerCacheVboOutput(uint32 attributeShaderLoc, uint8* vboOutput) +{ + activeAttributePointer[attributeShaderLoc].vboOutput = vboOutput; +} + +uint32 CommonRenderer_getAttributePointerCacheVboStride(uint32 attributeShaderLoc) +{ + return activeAttributePointer[attributeShaderLoc].vboStride; +} + +void CommonRenderer_setAttributePointerCacheVboStride(uint32 attributeShaderLoc, uint32 vboStride) +{ + activeAttributePointer[attributeShaderLoc].vboStride = vboStride; +} + +uint8 CommonRenderer_getAttributePointerCacheDataFormat(uint32 attributeShaderLoc) +{ + return activeAttributePointer[attributeShaderLoc].dataFormat; +} + +void CommonRenderer_setAttributePointerCacheDataFormat(uint32 attributeShaderLoc, uint8 dataFormat) +{ + activeAttributePointer[attributeShaderLoc].dataFormat = dataFormat; +} + +uint8 CommonRenderer_getAttributePointerCacheNfa(uint32 attributeShaderLoc) +{ + return activeAttributePointer[attributeShaderLoc].nfa; +} + +void CommonRenderer_setAttributePointerCacheNfa(uint32 attributeShaderLoc, uint8 nfa) +{ + activeAttributePointer[attributeShaderLoc].nfa = nfa; +} + +bool CommonRenderer_getAttributePointerCacheIsSigned(uint32 attributeShaderLoc) +{ + return activeAttributePointer[attributeShaderLoc].isSigned; +} + +void CommonRenderer_setAttributePointerCacheIsSigned(uint32 attributeShaderLoc, bool isSigned) +{ + activeAttributePointer[attributeShaderLoc].isSigned = isSigned; +} + +indexState_t* CommonRenderer_getIndexState() +{ + return &indexState; +} + +indexDataCacheEntry2_t** CommonRenderer_getIndexDataCacheFirst() +{ + return &indexDataCacheFirst; +} + +indexDataCacheEntry2_t** CommonRenderer_getIndexDataCacheBucket(uint32 bucketIdx) +{ + return &indexDataCacheBucket[bucketIdx]; +} + +sint32* CommonRenderer_getIndexDataCacheEntryCount() +{ + return &indexDataCacheEntryCount; +} + +void CommonRenderer_appendToUsageLinkedList(indexDataCacheEntry2_t* entry) +{ + if (indexDataCacheLast == nullptr) + { + indexDataCacheLast = entry; + indexDataCacheFirst = entry; + entry->nextInMostRecentUsage = nullptr; + entry->prevInMostRecentUsage = nullptr; + } + else + { + indexDataCacheLast->nextInMostRecentUsage = entry; + entry->prevInMostRecentUsage = indexDataCacheLast; + entry->nextInMostRecentUsage = nullptr; + indexDataCacheLast = entry; + } +} + +void CommonRenderer_removeFromUsageLinkedList(indexDataCacheEntry2_t* entry) +{ + if (entry->prevInMostRecentUsage) + { + entry->prevInMostRecentUsage->nextInMostRecentUsage = entry->nextInMostRecentUsage; + } + else + indexDataCacheFirst = entry->nextInMostRecentUsage; + if (entry->nextInMostRecentUsage) + { + entry->nextInMostRecentUsage->prevInMostRecentUsage = entry->prevInMostRecentUsage; + } + else + indexDataCacheLast = entry->prevInMostRecentUsage; + entry->prevInMostRecentUsage = nullptr; + entry->nextInMostRecentUsage = nullptr; +} + +void CommonRenderer_removeFromBucket(indexDataCacheEntry2_t* entry) +{ + uint32 indexDataBucketIdx = (uint32)((entry->key.physAddr + entry->key.count) ^ (entry->key.physAddr >> 16)) % INDEX_DATA_CACHE_BUCKETS; + if (indexDataCacheBucket[indexDataBucketIdx] == entry) + { + indexDataCacheBucket[indexDataBucketIdx] = entry->nextInBucket; + entry->nextInBucket = nullptr; + return; + } + indexDataCacheEntry2_t* cacheEntryItr = indexDataCacheBucket[indexDataBucketIdx]; + while (cacheEntryItr) + { + if (cacheEntryItr->nextInBucket == entry) + { + cacheEntryItr->nextInBucket = entry->nextInBucket; + entry->nextInBucket = nullptr; + return; + } + // next + cacheEntryItr = cacheEntryItr->nextInBucket; + } +} + +void CommonRenderer_cleanupAfterFrame() +{ + // drop everything from cache that is older than 30 frames + uint32 frameCounter = LatteGPUState.frameCounter; + while (indexDataCacheFirst) + { + indexDataCacheEntry2_t* entry = indexDataCacheFirst; + if ((frameCounter - entry->lastAccessFrameCount) < 30) + break; + // remove entry + virtualBufferHeap_free(indexState.indexBufferVirtualHeap, entry->heapEntry); + CommonRenderer_removeFromUsageLinkedList(entry); + CommonRenderer_removeFromBucket(entry); + free(entry); + } +} \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h new file mode 100644 index 00000000..be7fe519 --- /dev/null +++ b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h @@ -0,0 +1,98 @@ +#pragma once + +#include "Cafe/HW/Latte/Core/LatteRingBuffer.h" +#include "Cafe/HW/Latte/Core/Latte.h" + +using _INDEX_TYPE = Latte::LATTE_VGT_DMA_INDEX_TYPE::E_INDEX_TYPE; + +#define INDEX_CACHE_ENTRIES (8) + +typedef struct +{ + MPTR prevIndexDataMPTR; + sint32 prevIndexType; + sint32 prevCount; + // index data + uint8* indexData; + uint8* indexData2; + uint32 indexBufferOffset; + sint32 indexDataSize; // current size + sint32 indexDataLimit; // maximum size + // info + uint32 maxIndex; + uint32 minIndex; +}indexDataCacheEntry_t; + +typedef struct +{ + indexDataCacheEntry_t indexCacheEntry[INDEX_CACHE_ENTRIES]; + sint32 nextCacheEntryIndex; + // info about currently used index data + uint32 maxIndex; + uint32 minIndex; + uint8* indexData; + // buffer + unsigned int glIndexCacheBuffer; + VirtualBufferHeap_t* indexBufferVirtualHeap; + uint8* mappedIndexBuffer; + LatteRingBuffer_t* indexRingBuffer; + uint8* tempIndexStorage; + // misc + bool initialized; + unsigned int glActiveElementArrayBuffer; +}indexState_t; + +typedef struct +{ + uint8* vboOutput; + uint32 vboStride; + uint8 dataFormat; + uint8 nfa; + bool isSigned; +} AttributePointerCacheEntry_t; + +#define INDEX_DATA_CACHE_BUCKETS (1783) + +typedef struct +{ + MPTR physAddr; + sint32 count; + uint32 primitiveRestartIndex; + uint32 primitiveMode; +}indexDataCacheKey_t; + +typedef struct _indexDataCacheEntry_t +{ + indexDataCacheKey_t key; + _indexDataCacheEntry_t* nextInBucket; // points to next element in same bucket + uint32 physSize; + uint32 hash; + _INDEX_TYPE indexType; + //sint32 indexType; + uint32 minIndex; + uint32 maxIndex; + uint32 lastAccessFrameCount; + VirtualBufferHeapEntry_t* heapEntry; + _indexDataCacheEntry_t* nextInMostRecentUsage; // points to element which was used more recently + _indexDataCacheEntry_t* prevInMostRecentUsage; // points to element which was used less recently +}indexDataCacheEntry2_t; + +uint8* CommonRenderer_getAttributePointerCacheVboOutput(uint32 attributeShaderLoc); +void CommonRenderer_setAttributePointerCacheVboOutput(uint32 attributeShaderLoc, uint8* vboOutput); +uint32 CommonRenderer_getAttributePointerCacheVboStride(uint32 attributeShaderLoc); +void CommonRenderer_setAttributePointerCacheVboStride(uint32 attributeShaderLoc, uint32 vboStride); +uint8 CommonRenderer_getAttributePointerCacheDataFormat(uint32 attributeShaderLoc); +void CommonRenderer_setAttributePointerCacheDataFormat(uint32 attributeShaderLoc, uint8 dataFormat); +uint8 CommonRenderer_getAttributePointerCacheNfa(uint32 attributeShaderLoc); +void CommonRenderer_setAttributePointerCacheNfa(uint32 attributeShaderLoc, uint8 nfa); +bool CommonRenderer_getAttributePointerCacheIsSigned(uint32 attributeShaderLoc); +void CommonRenderer_setAttributePointerCacheIsSigned(uint32 attributeShaderLoc, bool isSigned); +indexState_t* CommonRenderer_getIndexState(); +indexDataCacheEntry2_t** CommonRenderer_getIndexDataCacheFirst(); +indexDataCacheEntry2_t** CommonRenderer_getIndexDataCacheBucket(uint32 bucketIdx); +sint32* CommonRenderer_getIndexDataCacheEntryCount(); + +void CommonRenderer_appendToUsageLinkedList(indexDataCacheEntry2_t* entry); +void CommonRenderer_removeFromUsageLinkedList(indexDataCacheEntry2_t* entry); +void CommonRenderer_removeFromBucket(indexDataCacheEntry2_t* entry); +void CommonRenderer_cleanupAfterFrame(); \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp index 571961f4..19c4825d 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp @@ -13,71 +13,24 @@ #include "Cafe/HW/Latte/Renderer/OpenGL/CachedFBOGL.h" #include "Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h" +#include "Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h" + #include "Cafe/HW/Latte/ISA/RegDefines.h" #include "Cafe/OS/libs/gx2/GX2.h" #include "Cafe/GameProfile/GameProfile.h" #include "config/ActiveSettings.h" - -using _INDEX_TYPE = Latte::LATTE_VGT_DMA_INDEX_TYPE::E_INDEX_TYPE; - GLenum sGLActiveDrawMode = 0; extern bool hasValidFramebufferAttached; -#define INDEX_CACHE_ENTRIES (8) - -typedef struct -{ - MPTR prevIndexDataMPTR; - sint32 prevIndexType; - sint32 prevCount; - // index data - uint8* indexData; - uint8* indexData2; - uint32 indexBufferOffset; - sint32 indexDataSize; // current size - sint32 indexDataLimit; // maximum size - // info - uint32 maxIndex; - uint32 minIndex; -}indexDataCacheEntry_t; - -struct -{ - indexDataCacheEntry_t indexCacheEntry[INDEX_CACHE_ENTRIES]; - sint32 nextCacheEntryIndex; - // info about currently used index data - uint32 maxIndex; - uint32 minIndex; - uint8* indexData; - // buffer - GLuint glIndexCacheBuffer; - VirtualBufferHeap_t* indexBufferVirtualHeap; - uint8* mappedIndexBuffer; - LatteRingBuffer_t* indexRingBuffer; - uint8* tempIndexStorage; - // misc - bool initialized; - GLuint glActiveElementArrayBuffer; -}indexState = { 0 }; - -struct -{ - uint8* vboOutput; - uint32 vboStride; - uint8 dataFormat; - uint8 nfa; - bool isSigned; -}activeAttributePointer[LATTE_VS_ATTRIBUTE_LIMIT] = { 0 }; - void LatteDraw_resetAttributePointerCache() { for (sint32 i = 0; i < LATTE_VS_ATTRIBUTE_LIMIT; i++) { - activeAttributePointer[i].vboOutput = (uint8*)-1; - activeAttributePointer[i].vboStride = (uint32)-1; + CommonRenderer_setAttributePointerCacheVboOutput(i, (uint8*)-1); + CommonRenderer_setAttributePointerCacheVboStride(i, (uint32)-1); } } @@ -87,15 +40,21 @@ void _setAttributeBufferPointerRaw(uint32 attributeShaderLoc, uint8* buffer, uin bool isSigned = attrib->isSigned != 0; uint8 nfa = attrib->nfa; // don't call glVertexAttribIPointer if parameters have not changed - if (activeAttributePointer[attributeShaderLoc].vboOutput == vboOutput && activeAttributePointer[attributeShaderLoc].vboStride == vboStride && activeAttributePointer[attributeShaderLoc].dataFormat == dataFormat && activeAttributePointer[attributeShaderLoc].nfa == nfa && activeAttributePointer[attributeShaderLoc].isSigned == isSigned) + if ( + CommonRenderer_getAttributePointerCacheVboOutput(attributeShaderLoc) == vboOutput && + CommonRenderer_getAttributePointerCacheVboStride(attributeShaderLoc) == vboStride && + CommonRenderer_getAttributePointerCacheDataFormat(attributeShaderLoc) == dataFormat && + CommonRenderer_getAttributePointerCacheNfa(attributeShaderLoc) == nfa && + CommonRenderer_getAttributePointerCacheIsSigned(attributeShaderLoc) == isSigned + ) { return; } - activeAttributePointer[attributeShaderLoc].vboOutput = vboOutput; - activeAttributePointer[attributeShaderLoc].vboStride = vboStride; - activeAttributePointer[attributeShaderLoc].dataFormat = dataFormat; - activeAttributePointer[attributeShaderLoc].nfa = nfa; - activeAttributePointer[attributeShaderLoc].isSigned = isSigned; + CommonRenderer_setAttributePointerCacheVboOutput(attributeShaderLoc, vboOutput); + CommonRenderer_setAttributePointerCacheVboStride(attributeShaderLoc, vboStride); + CommonRenderer_setAttributePointerCacheDataFormat(attributeShaderLoc, dataFormat); + CommonRenderer_setAttributePointerCacheNfa(attributeShaderLoc, nfa); + CommonRenderer_setAttributePointerCacheIsSigned(attributeShaderLoc, isSigned); // setup attribute pointer if (dataFormat == FMT_32_32_32_32_FLOAT || dataFormat == FMT_32_32_32_32) { @@ -194,111 +153,23 @@ void OpenGLRenderer::SetAttributeArrayState(uint32 index, bool isEnabled, sint32 // Sets the currently active element array buffer and binds it void OpenGLRenderer::SetArrayElementBuffer(GLuint arrayElementBuffer) { - if (arrayElementBuffer == indexState.glActiveElementArrayBuffer) + indexState_t* indexState = CommonRenderer_getIndexState(); + if (arrayElementBuffer == indexState->glActiveElementArrayBuffer) return; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrayElementBuffer); - indexState.glActiveElementArrayBuffer = arrayElementBuffer; -} - -typedef struct -{ - MPTR physAddr; - sint32 count; - uint32 primitiveRestartIndex; - uint32 primitiveMode; -}indexDataCacheKey_t; - -typedef struct _indexDataCacheEntry_t -{ - indexDataCacheKey_t key; - _indexDataCacheEntry_t* nextInBucket; // points to next element in same bucket - uint32 physSize; - uint32 hash; - _INDEX_TYPE indexType; - //sint32 indexType; - uint32 minIndex; - uint32 maxIndex; - uint32 lastAccessFrameCount; - VirtualBufferHeapEntry_t* heapEntry; - _indexDataCacheEntry_t* nextInMostRecentUsage; // points to element which was used more recently - _indexDataCacheEntry_t* prevInMostRecentUsage; // points to element which was used less recently -}indexDataCacheEntry2_t; - -#define INDEX_DATA_CACHE_BUCKETS (1783) - -indexDataCacheEntry2_t* indexDataCacheBucket[INDEX_DATA_CACHE_BUCKETS] = { 0 }; -indexDataCacheEntry2_t* indexDataCacheFirst = nullptr; // points to least recently used item -indexDataCacheEntry2_t* indexDataCacheLast = nullptr; // points to most recently used item -sint32 indexDataCacheEntryCount = 0; - -void _appendToUsageLinkedList(indexDataCacheEntry2_t* entry) -{ - if (indexDataCacheLast == nullptr) - { - indexDataCacheLast = entry; - indexDataCacheFirst = entry; - entry->nextInMostRecentUsage = nullptr; - entry->prevInMostRecentUsage = nullptr; - } - else - { - indexDataCacheLast->nextInMostRecentUsage = entry; - entry->prevInMostRecentUsage = indexDataCacheLast; - entry->nextInMostRecentUsage = nullptr; - indexDataCacheLast = entry; - } -} - -void _removeFromUsageLinkedList(indexDataCacheEntry2_t* entry) -{ - if (entry->prevInMostRecentUsage) - { - entry->prevInMostRecentUsage->nextInMostRecentUsage = entry->nextInMostRecentUsage; - } - else - indexDataCacheFirst = entry->nextInMostRecentUsage; - if (entry->nextInMostRecentUsage) - { - entry->nextInMostRecentUsage->prevInMostRecentUsage = entry->prevInMostRecentUsage; - } - else - indexDataCacheLast = entry->prevInMostRecentUsage; - entry->prevInMostRecentUsage = nullptr; - entry->nextInMostRecentUsage = nullptr; -} - -void _removeFromBucket(indexDataCacheEntry2_t* entry) -{ - uint32 indexDataBucketIdx = (uint32)((entry->key.physAddr + entry->key.count) ^ (entry->key.physAddr >> 16)) % INDEX_DATA_CACHE_BUCKETS; - if (indexDataCacheBucket[indexDataBucketIdx] == entry) - { - indexDataCacheBucket[indexDataBucketIdx] = entry->nextInBucket; - entry->nextInBucket = nullptr; - return; - } - indexDataCacheEntry2_t* cacheEntryItr = indexDataCacheBucket[indexDataBucketIdx]; - while (cacheEntryItr) - { - if (cacheEntryItr->nextInBucket == entry) - { - cacheEntryItr->nextInBucket = entry->nextInBucket; - entry->nextInBucket = nullptr; - return; - } - // next - cacheEntryItr = cacheEntryItr->nextInBucket; - } + indexState->glActiveElementArrayBuffer = arrayElementBuffer; } void _decodeAndUploadIndexData(indexDataCacheEntry2_t* cacheEntry) { uint32 count = cacheEntry->key.count; uint32 primitiveRestartIndex = cacheEntry->key.primitiveRestartIndex; + indexState_t *indexState = CommonRenderer_getIndexState(); if (cacheEntry->indexType == _INDEX_TYPE::U16_BE) { // 16bit indices uint16* indexInputU16 = (uint16*)memory_getPointerFromPhysicalOffset(cacheEntry->key.physAddr); - uint16* indexOutputU16 = (uint16*)indexState.tempIndexStorage; + uint16* indexOutputU16 = (uint16*)indexState->tempIndexStorage; cemu_assert_debug(count != 0); uint16 indexMinU16 = 0xFFFF; uint16 indexMaxU16 = 0; @@ -334,14 +205,14 @@ void _decodeAndUploadIndexData(indexDataCacheEntry2_t* cacheEntry) } cacheEntry->minIndex = indexMinU16; cacheEntry->maxIndex = indexMaxU16; - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, cacheEntry->heapEntry->startOffset, count * sizeof(uint16), indexState.tempIndexStorage); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, cacheEntry->heapEntry->startOffset, count * sizeof(uint16), indexState->tempIndexStorage); performanceMonitor.cycle[performanceMonitor.cycleIndex].indexDataUploaded += (count * sizeof(uint16)); } else if(cacheEntry->indexType == _INDEX_TYPE::U32_BE) { // 32bit indices uint32* indexInputU32 = (uint32*)memory_getPointerFromPhysicalOffset(cacheEntry->key.physAddr); - uint32* indexOutputU32 = (uint32*)indexState.tempIndexStorage; + uint32* indexOutputU32 = (uint32*)indexState->tempIndexStorage; cemu_assert_debug(count != 0); uint32 indexMinU32 = _swapEndianU32(*indexInputU32); uint32 indexMaxU32 = _swapEndianU32(*indexInputU32); @@ -359,7 +230,7 @@ void _decodeAndUploadIndexData(indexDataCacheEntry2_t* cacheEntry) } cacheEntry->minIndex = indexMinU32; cacheEntry->maxIndex = indexMaxU32; - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, cacheEntry->heapEntry->startOffset, count * sizeof(uint32), indexState.tempIndexStorage); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, cacheEntry->heapEntry->startOffset, count * sizeof(uint32), indexState->tempIndexStorage); performanceMonitor.cycle[performanceMonitor.cycleIndex].indexDataUploaded += (count * sizeof(uint32)); } else @@ -368,33 +239,18 @@ void _decodeAndUploadIndexData(indexDataCacheEntry2_t* cacheEntry) } } - -void LatteDraw_cleanupAfterFrame() -{ - // drop everything from cache that is older than 30 frames - uint32 frameCounter = LatteGPUState.frameCounter; - while (indexDataCacheFirst) - { - indexDataCacheEntry2_t* entry = indexDataCacheFirst; - if ((frameCounter - entry->lastAccessFrameCount) < 30) - break; - // remove entry - virtualBufferHeap_free(indexState.indexBufferVirtualHeap, entry->heapEntry); - _removeFromUsageLinkedList(entry); - _removeFromBucket(entry); - free(entry); - } -} - void LatteDrawGL_removeLeastRecentlyUsedIndexCacheEntries(sint32 count) { - while (indexDataCacheFirst && count > 0) + indexState_t *indexState = CommonRenderer_getIndexState(); + indexDataCacheEntry2_t** indexDataCacheFirst = CommonRenderer_getIndexDataCacheFirst(); + + while (*indexDataCacheFirst && count > 0) { - indexDataCacheEntry2_t* entry = indexDataCacheFirst; + indexDataCacheEntry2_t* entry = *indexDataCacheFirst; // remove entry - virtualBufferHeap_free(indexState.indexBufferVirtualHeap, entry->heapEntry); - _removeFromUsageLinkedList(entry); - _removeFromBucket(entry); + virtualBufferHeap_free(indexState->indexBufferVirtualHeap, entry->heapEntry); + CommonRenderer_removeFromUsageLinkedList(entry); + CommonRenderer_removeFromBucket(entry); free(entry); count--; } @@ -432,19 +288,22 @@ uint32 LatteDrawGL_calculateIndexDataHash(uint8* data, uint32 size) // todo - Outdated cache implementation. Update OpenGL renderer to use the generic implementation that is also used by the Vulkan renderer void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE indexType, sint32 count, sint32 primitiveMode) { + indexState_t* indexState = CommonRenderer_getIndexState(); + indexDataCacheEntry2_t** indexDataCacheFirst = CommonRenderer_getIndexDataCacheFirst(); + if (indexType == _INDEX_TYPE::AUTO) { - indexState.minIndex = 0; - indexState.maxIndex = count - 1; + indexState->minIndex = 0; + indexState->maxIndex = count - 1; // since no indices are used we don't need to unbind the element array buffer return; // automatic indices } - OpenGLRenderer::SetArrayElementBuffer(indexState.glIndexCacheBuffer); + OpenGLRenderer::SetArrayElementBuffer(indexState->glIndexCacheBuffer); uint32 indexDataBucketIdx = (uint32)((indexDataMPTR + count) ^ (indexDataMPTR >> 16)) % INDEX_DATA_CACHE_BUCKETS; // find matching entry uint32 primitiveRestartIndex = LatteGPUState.contextNew.VGT_MULTI_PRIM_IB_RESET_INDX.get_RESTART_INDEX(); - indexDataCacheEntry2_t* cacheEntryItr = indexDataCacheBucket[indexDataBucketIdx]; + indexDataCacheEntry2_t* cacheEntryItr = *CommonRenderer_getIndexDataCacheBucket(indexDataBucketIdx); indexDataCacheKey_t compareKey; compareKey.physAddr = indexDataMPTR; compareKey.count = count; @@ -459,9 +318,9 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde continue; } // entry found - indexState.minIndex = cacheEntryItr->minIndex; - indexState.maxIndex = cacheEntryItr->maxIndex; - indexState.indexData = (uint8*)(size_t)cacheEntryItr->heapEntry->startOffset; + indexState->minIndex = cacheEntryItr->minIndex; + indexState->maxIndex = cacheEntryItr->maxIndex; + indexState->indexData = (uint8*)(size_t)cacheEntryItr->heapEntry->startOffset; cacheEntryItr->lastAccessFrameCount = LatteGPUState.frameCounter; // check if the data changed uint32 h = LatteDrawGL_calculateIndexDataHash(memory_getPointerFromPhysicalOffset(indexDataMPTR), cacheEntryItr->physSize); @@ -472,8 +331,8 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde cacheEntryItr->hash = h; } // move entry to the front - _removeFromUsageLinkedList(cacheEntryItr); - _appendToUsageLinkedList(cacheEntryItr); + CommonRenderer_removeFromUsageLinkedList(cacheEntryItr); + CommonRenderer_appendToUsageLinkedList(cacheEntryItr); return; } // calculate size of index data in cache @@ -483,16 +342,16 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde else cacheIndexDataSize = count * sizeof(uint32); // no matching entry, create new one - VirtualBufferHeapEntry_t* heapEntry = virtualBufferHeap_allocate(indexState.indexBufferVirtualHeap, cacheIndexDataSize); + VirtualBufferHeapEntry_t* heapEntry = virtualBufferHeap_allocate(indexState->indexBufferVirtualHeap, cacheIndexDataSize); if (heapEntry == nullptr) { while (true) { LatteDrawGL_removeLeastRecentlyUsedIndexCacheEntries(10); - heapEntry = virtualBufferHeap_allocate(indexState.indexBufferVirtualHeap, cacheIndexDataSize); + heapEntry = virtualBufferHeap_allocate(indexState->indexBufferVirtualHeap, cacheIndexDataSize); if (heapEntry != nullptr) break; - if (indexDataCacheFirst == nullptr) + if (*indexDataCacheFirst == nullptr) { cemuLog_log(LogType::Force, "Unable to allocate entry in index cache"); assert_dbg(); @@ -511,17 +370,19 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde cacheEntry->heapEntry = heapEntry; cacheEntry->lastAccessFrameCount = LatteGPUState.frameCounter; // append entry in bucket list - cacheEntry->nextInBucket = indexDataCacheBucket[indexDataBucketIdx]; - indexDataCacheBucket[indexDataBucketIdx] = cacheEntry; + indexDataCacheEntry2_t** bucket = CommonRenderer_getIndexDataCacheBucket(indexDataBucketIdx); + cacheEntry->nextInBucket = *bucket; + *bucket = cacheEntry; // append as most recently used entry - _appendToUsageLinkedList(cacheEntry); + CommonRenderer_appendToUsageLinkedList(cacheEntry); // decode and upload the data _decodeAndUploadIndexData(cacheEntry); - indexDataCacheEntryCount++; - indexState.minIndex = cacheEntry->minIndex; - indexState.maxIndex = cacheEntry->maxIndex; - indexState.indexData = (uint8*)(size_t)cacheEntry->heapEntry->startOffset; + sint32* indexDataCacheEntryCount = CommonRenderer_getIndexDataCacheEntryCount(); + (*indexDataCacheEntryCount)++; + indexState->minIndex = cacheEntry->minIndex; + indexState->maxIndex = cacheEntry->maxIndex; + indexState->indexData = (uint8*)(size_t)cacheEntry->heapEntry->startOffset; } void LatteDraw_handleSpecialState8_clearAsDepth() @@ -590,19 +451,20 @@ void LatteDraw_handleSpecialState8_clearAsDepth() void LatteDrawGL_doDraw(_INDEX_TYPE indexType, uint32 baseVertex, uint32 baseInstance, uint32 instanceCount, uint32 count) { + indexState_t* indexState = CommonRenderer_getIndexState(); if (indexType == _INDEX_TYPE::U16_BE) { // 16bit index, big endian if (instanceCount > 1 || baseInstance != 0) { - glDrawElementsInstancedBaseVertexBaseInstance(sGLActiveDrawMode, count, GL_UNSIGNED_SHORT, indexState.indexData, instanceCount, baseVertex, baseInstance); + glDrawElementsInstancedBaseVertexBaseInstance(sGLActiveDrawMode, count, GL_UNSIGNED_SHORT, indexState->indexData, instanceCount, baseVertex, baseInstance); } else { if (baseVertex != 0) - glDrawRangeElementsBaseVertex(sGLActiveDrawMode, indexState.minIndex, indexState.maxIndex, count, GL_UNSIGNED_SHORT, indexState.indexData, baseVertex); + glDrawRangeElementsBaseVertex(sGLActiveDrawMode, indexState->minIndex, indexState->maxIndex, count, GL_UNSIGNED_SHORT, indexState->indexData, baseVertex); else - glDrawRangeElements(sGLActiveDrawMode, indexState.minIndex, indexState.maxIndex, count, GL_UNSIGNED_SHORT, indexState.indexData); + glDrawRangeElements(sGLActiveDrawMode, indexState->minIndex, indexState->maxIndex, count, GL_UNSIGNED_SHORT, indexState->indexData); } } else if (indexType == _INDEX_TYPE::U32_BE) @@ -611,11 +473,11 @@ void LatteDrawGL_doDraw(_INDEX_TYPE indexType, uint32 baseVertex, uint32 baseIns if (instanceCount > 1 || baseInstance != 0) { //debug_printf("Render instanced\n"); - glDrawElementsInstancedBaseVertexBaseInstance(sGLActiveDrawMode, count, GL_UNSIGNED_INT, indexState.indexData, instanceCount, baseVertex, baseInstance); + glDrawElementsInstancedBaseVertexBaseInstance(sGLActiveDrawMode, count, GL_UNSIGNED_INT, indexState->indexData, instanceCount, baseVertex, baseInstance); } else { - glDrawRangeElementsBaseVertex(sGLActiveDrawMode, indexState.minIndex, indexState.maxIndex, count, GL_UNSIGNED_INT, indexState.indexData, baseVertex); + glDrawRangeElementsBaseVertex(sGLActiveDrawMode, indexState->minIndex, indexState->maxIndex, count, GL_UNSIGNED_INT, indexState->indexData, baseVertex); } } else if (indexType == _INDEX_TYPE::AUTO) @@ -1040,7 +902,8 @@ void OpenGLRenderer::draw_genericDrawHandler(uint32 baseVertex, uint32 baseInsta endPerfMonProfiling(performanceMonitor.gpuTime_dcStageIndexMgr); // synchronize vertex and uniform buffers - LatteBufferCache_Sync(indexState.minIndex + baseVertex, indexState.maxIndex + baseVertex, baseInstance, instanceCount); + indexState_t *indexState = CommonRenderer_getIndexState(); + LatteBufferCache_Sync(indexState->minIndex + baseVertex, indexState->maxIndex + baseVertex, baseInstance, instanceCount); _setupVertexAttributes(); @@ -1231,23 +1094,24 @@ void OpenGLRenderer::draw_endSequence() void OpenGLRenderer::draw_init() { - if (indexState.initialized) + indexState_t* indexState = CommonRenderer_getIndexState(); + if (indexState->initialized) return; - indexState.initialized = true; + indexState->initialized = true; // create index buffer - glGenBuffers(1, &indexState.glIndexCacheBuffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexState.glIndexCacheBuffer); + glGenBuffers(1, &indexState->glIndexCacheBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexState->glIndexCacheBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR, NULL, GL_DYNAMIC_DRAW); #if BOOST_OS_WINDOWS - indexState.mappedIndexBuffer = (uint8*)_aligned_malloc(GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR, 256); + indexState->mappedIndexBuffer = (uint8*)_aligned_malloc(GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR, 256); #else - indexState.mappedIndexBuffer = (uint8*)aligned_alloc(256, GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR); + indexState->mappedIndexBuffer = (uint8*)aligned_alloc(256, GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR); #endif glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - indexState.indexRingBuffer = LatteRingBuffer_create(indexState.mappedIndexBuffer, GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR); - indexState.tempIndexStorage = (uint8*)malloc(1024 * 1024 * 8); + indexState->indexRingBuffer = LatteRingBuffer_create(indexState->mappedIndexBuffer, GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR); + indexState->tempIndexStorage = (uint8*)malloc(1024 * 1024 * 8); // create virtual heap for index buffer - indexState.indexBufferVirtualHeap = virtualBufferHeap_create(GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR); + indexState->indexBufferVirtualHeap = virtualBufferHeap_create(GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR); } void OpenGLRenderer::bufferCache_upload(uint8* buffer, sint32 size, uint32 bufferOffset) From 828ddea0a8659626a5bbeda0680713279f0849a9 Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 00:36:20 +0100 Subject: [PATCH 10/32] actually rename it back to LatteDraw for consistency --- src/Cafe/HW/Latte/Core/LatteDraw.h | 2 +- src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp | 2 +- src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp | 2 +- src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/LatteDraw.h b/src/Cafe/HW/Latte/Core/LatteDraw.h index 37390ae1..89c34dc0 100644 --- a/src/Cafe/HW/Latte/Core/LatteDraw.h +++ b/src/Cafe/HW/Latte/Core/LatteDraw.h @@ -1,4 +1,4 @@ #pragma once #include "Common/GLInclude/GLInclude.h" -void CommonRenderer_cleanupAfterFrame(); \ No newline at end of file +void LatteDraw_cleanupAfterFrame(); \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp index a466b652..b5053df8 100644 --- a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp +++ b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp @@ -695,7 +695,7 @@ void LatteRenderTarget_itHLESwapScanBuffer() performanceMonitor.gpuTime_frameTime.beginMeasuring(); LatteTC_CleanupUnusedTextures(); - CommonRenderer_cleanupAfterFrame(); + LatteDraw_cleanupAfterFrame(); LatteQuery_CancelActiveGPU7Queries(); LatteBufferCache_notifySwapTVScanBuffer(); LattePerformanceMonitor_frameBegin(); diff --git a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp index c8dab968..4a5de6b3 100644 --- a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp @@ -137,7 +137,7 @@ void CommonRenderer_removeFromBucket(indexDataCacheEntry2_t* entry) } } -void CommonRenderer_cleanupAfterFrame() +void LatteDraw_cleanupAfterFrame() { // drop everything from cache that is older than 30 frames uint32 frameCounter = LatteGPUState.frameCounter; diff --git a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h index be7fe519..e7a71d69 100644 --- a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h +++ b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h @@ -95,4 +95,4 @@ sint32* CommonRenderer_getIndexDataCacheEntryCount(); void CommonRenderer_appendToUsageLinkedList(indexDataCacheEntry2_t* entry); void CommonRenderer_removeFromUsageLinkedList(indexDataCacheEntry2_t* entry); void CommonRenderer_removeFromBucket(indexDataCacheEntry2_t* entry); -void CommonRenderer_cleanupAfterFrame(); \ No newline at end of file +void LatteDraw_cleanupAfterFrame(); \ No newline at end of file From 4be30f6ef93d95d62a67fe4b86686001144a60f1 Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 00:49:41 +0100 Subject: [PATCH 11/32] condense attribute pointer cache functions and move handleSpecialState8_clearAsDepth to common renderer --- .../Renderer/Common/CommonRendererCore.cpp | 137 +++++++++++++----- .../Renderer/Common/CommonRendererCore.h | 16 +- .../HW/Latte/Renderer/Metal/MetalRenderer.cpp | 2 +- .../Renderer/OpenGL/OpenGLRendererCore.cpp | 86 +---------- .../Renderer/Vulkan/VulkanRendererCore.cpp | 1 + 5 files changed, 109 insertions(+), 133 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp index 4a5de6b3..a8a26eb4 100644 --- a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp @@ -1,4 +1,12 @@ #include "CommonRendererCore.h" +#include "Cafe/HW/Latte/Renderer/Renderer.h" +#include "Cafe/HW/Latte/ISA/RegDefines.h" +#include "config/CemuConfig.h" + +#ifdef ENABLE_OPENGL +#include "Common/GLInclude/glFunctions.h" +#include "Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.h" +#endif indexState_t indexState = { 0 }; AttributePointerCacheEntry_t activeAttributePointer[LATTE_VS_ATTRIBUTE_LIMIT] = { 0 }; @@ -8,54 +16,35 @@ indexDataCacheEntry2_t* indexDataCacheFirst = nullptr; // points to least recent indexDataCacheEntry2_t* indexDataCacheLast = nullptr; // points to most recently used item sint32 indexDataCacheEntryCount = 0; -uint8* CommonRenderer_getAttributePointerCacheVboOutput(uint32 attributeShaderLoc) +void CommonRenderer_resetAttributePointerCache() { - return activeAttributePointer[attributeShaderLoc].vboOutput; + for (sint32 i = 0; i < LATTE_VS_ATTRIBUTE_LIMIT; i++) + { + activeAttributePointer[i].vboOutput = (uint8*)-1; + activeAttributePointer[i].vboStride = (uint32)-1; + } } -void CommonRenderer_setAttributePointerCacheVboOutput(uint32 attributeShaderLoc, uint8* vboOutput) +bool CommonRenderer_checkIfAttributePointerCacheChanged(uint32 attributeShaderLoc, uint8* vboOutput, uint32 vboStride, uint8 dataFormat, uint8 nfa, bool isSigned) { + // don't call glVertexAttribPointer if parameters have not changed + if ( + activeAttributePointer[attributeShaderLoc].vboOutput == vboOutput && + activeAttributePointer[attributeShaderLoc].vboStride == vboStride && + activeAttributePointer[attributeShaderLoc].dataFormat == dataFormat && + activeAttributePointer[attributeShaderLoc].nfa == nfa && + activeAttributePointer[attributeShaderLoc].isSigned == isSigned + ) + { + return false; + } activeAttributePointer[attributeShaderLoc].vboOutput = vboOutput; -} - -uint32 CommonRenderer_getAttributePointerCacheVboStride(uint32 attributeShaderLoc) -{ - return activeAttributePointer[attributeShaderLoc].vboStride; -} - -void CommonRenderer_setAttributePointerCacheVboStride(uint32 attributeShaderLoc, uint32 vboStride) -{ activeAttributePointer[attributeShaderLoc].vboStride = vboStride; -} - -uint8 CommonRenderer_getAttributePointerCacheDataFormat(uint32 attributeShaderLoc) -{ - return activeAttributePointer[attributeShaderLoc].dataFormat; -} - -void CommonRenderer_setAttributePointerCacheDataFormat(uint32 attributeShaderLoc, uint8 dataFormat) -{ activeAttributePointer[attributeShaderLoc].dataFormat = dataFormat; -} - -uint8 CommonRenderer_getAttributePointerCacheNfa(uint32 attributeShaderLoc) -{ - return activeAttributePointer[attributeShaderLoc].nfa; -} - -void CommonRenderer_setAttributePointerCacheNfa(uint32 attributeShaderLoc, uint8 nfa) -{ activeAttributePointer[attributeShaderLoc].nfa = nfa; -} - -bool CommonRenderer_getAttributePointerCacheIsSigned(uint32 attributeShaderLoc) -{ - return activeAttributePointer[attributeShaderLoc].isSigned; -} - -void CommonRenderer_setAttributePointerCacheIsSigned(uint32 attributeShaderLoc, bool isSigned) -{ activeAttributePointer[attributeShaderLoc].isSigned = isSigned; + + return true; } indexState_t* CommonRenderer_getIndexState() @@ -152,4 +141,74 @@ void LatteDraw_cleanupAfterFrame() CommonRenderer_removeFromBucket(entry); free(entry); } +} + + +void LatteDraw_handleSpecialState8_clearAsDepth() +{ + if (LatteGPUState.contextNew.GetSpecialStateValues()[0] == 0) + cemuLog_logDebug(LogType::Force, "Special state 8 requires special state 0 but it is not set?"); + // get depth buffer information + uint32 regDepthBuffer = LatteGPUState.contextRegister[mmDB_HTILE_DATA_BASE]; + uint32 regDepthSize = LatteGPUState.contextRegister[mmDB_DEPTH_SIZE]; + uint32 regDepthBufferInfo = LatteGPUState.contextRegister[mmDB_DEPTH_INFO]; + // get format and tileMode from info reg + uint32 depthBufferTileMode = (regDepthBufferInfo >> 15) & 0xF; + + MPTR depthBufferPhysMem = regDepthBuffer << 8; + uint32 depthBufferPitch = (((regDepthSize >> 0) & 0x3FF) + 1); + uint32 depthBufferHeight = ((((regDepthSize >> 10) & 0xFFFFF) + 1) / depthBufferPitch); + depthBufferPitch <<= 3; + depthBufferHeight <<= 3; + uint32 depthBufferWidth = depthBufferPitch; + + sint32 sliceIndex = 0; // todo + sint32 mipIndex = 0; + + // clear all color buffers that match the format of the depth buffer + sint32 searchIndex = 0; + bool targetFound = false; + while (true) + { + LatteTextureView* view = LatteTC_LookupTextureByData(depthBufferPhysMem, depthBufferWidth, depthBufferHeight, depthBufferPitch, 0, 1, sliceIndex, 1, &searchIndex); + if (!view) + { + // should we clear in RAM instead? + break; + } + sint32 effectiveClearWidth = view->baseTexture->width; + sint32 effectiveClearHeight = view->baseTexture->height; + LatteTexture_scaleToEffectiveSize(view->baseTexture, &effectiveClearWidth, &effectiveClearHeight, 0); + + // hacky way to get clear color + float* regClearColor = (float*)(LatteGPUState.contextRegister + 0xC000 + 0); // REG_BASE_ALU_CONST + + uint8 clearColor[4] = { 0 }; + clearColor[0] = (uint8)(regClearColor[0] * 255.0f); + clearColor[1] = (uint8)(regClearColor[1] * 255.0f); + clearColor[2] = (uint8)(regClearColor[2] * 255.0f); + clearColor[3] = (uint8)(regClearColor[3] * 255.0f); + + // todo - use fragment shader software emulation (evoke for one pixel) to determine clear color + // todo - dont clear entire slice, use effectiveClearWidth, effectiveClearHeight + + switch (g_renderer->GetType()) + { +#ifdef ENABLE_OPENGL + case RendererAPI::OpenGL: + { + //cemu_assert_debug(false); // implement g_renderer->texture_clearColorSlice properly for OpenGL renderer + if (glClearTexSubImage) + glClearTexSubImage(((LatteTextureViewGL*)view)->glTexId, mipIndex, 0, 0, 0, effectiveClearWidth, effectiveClearHeight, 1, GL_RGBA, GL_UNSIGNED_BYTE, clearColor); + } +#endif + default: + { + if (view->baseTexture->isDepth) + g_renderer->texture_clearDepthSlice(view->baseTexture, sliceIndex + view->firstSlice, mipIndex + view->firstMip, true, view->baseTexture->hasStencil, 0.0f, 0); + else + g_renderer->texture_clearColorSlice(view->baseTexture, sliceIndex + view->firstSlice, mipIndex + view->firstMip, clearColor[0], clearColor[1], clearColor[2], clearColor[3]); + } + } + } } \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h index e7a71d69..1866c30c 100644 --- a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h +++ b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h @@ -77,16 +77,9 @@ typedef struct _indexDataCacheEntry_t _indexDataCacheEntry_t* prevInMostRecentUsage; // points to element which was used less recently }indexDataCacheEntry2_t; -uint8* CommonRenderer_getAttributePointerCacheVboOutput(uint32 attributeShaderLoc); -void CommonRenderer_setAttributePointerCacheVboOutput(uint32 attributeShaderLoc, uint8* vboOutput); -uint32 CommonRenderer_getAttributePointerCacheVboStride(uint32 attributeShaderLoc); -void CommonRenderer_setAttributePointerCacheVboStride(uint32 attributeShaderLoc, uint32 vboStride); -uint8 CommonRenderer_getAttributePointerCacheDataFormat(uint32 attributeShaderLoc); -void CommonRenderer_setAttributePointerCacheDataFormat(uint32 attributeShaderLoc, uint8 dataFormat); -uint8 CommonRenderer_getAttributePointerCacheNfa(uint32 attributeShaderLoc); -void CommonRenderer_setAttributePointerCacheNfa(uint32 attributeShaderLoc, uint8 nfa); -bool CommonRenderer_getAttributePointerCacheIsSigned(uint32 attributeShaderLoc); -void CommonRenderer_setAttributePointerCacheIsSigned(uint32 attributeShaderLoc, bool isSigned); +void CommonRenderer_resetAttributePointerCache(); +bool CommonRenderer_checkIfAttributePointerCacheChanged(uint32 attributeShaderLoc, uint8* vboOutput, uint32 vboStride, uint8 dataFormat, uint8 nfa, bool isSigned); + indexState_t* CommonRenderer_getIndexState(); indexDataCacheEntry2_t** CommonRenderer_getIndexDataCacheFirst(); indexDataCacheEntry2_t** CommonRenderer_getIndexDataCacheBucket(uint32 bucketIdx); @@ -95,4 +88,5 @@ sint32* CommonRenderer_getIndexDataCacheEntryCount(); void CommonRenderer_appendToUsageLinkedList(indexDataCacheEntry2_t* entry); void CommonRenderer_removeFromUsageLinkedList(indexDataCacheEntry2_t* entry); void CommonRenderer_removeFromBucket(indexDataCacheEntry2_t* entry); -void LatteDraw_cleanupAfterFrame(); \ No newline at end of file +void LatteDraw_cleanupAfterFrame(); +void LatteDraw_handleSpecialState8_clearAsDepth(); \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 7ceaf74d..8c2da361 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -33,7 +33,7 @@ extern bool hasValidFramebufferAttached; float supportBufferData[512 * 4]; -// Defined in the OpenGL renderer +// Defined in the Common renderer void LatteDraw_handleSpecialState8_clearAsDepth(); std::vector MetalRenderer::GetDevices() diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp index 19c4825d..94620cda 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp @@ -27,11 +27,7 @@ extern bool hasValidFramebufferAttached; void LatteDraw_resetAttributePointerCache() { - for (sint32 i = 0; i < LATTE_VS_ATTRIBUTE_LIMIT; i++) - { - CommonRenderer_setAttributePointerCacheVboOutput(i, (uint8*)-1); - CommonRenderer_setAttributePointerCacheVboStride(i, (uint32)-1); - } + CommonRenderer_resetAttributePointerCache(); } void _setAttributeBufferPointerRaw(uint32 attributeShaderLoc, uint8* buffer, uint32 bufferSize, uint32 stride, LatteParsedFetchShaderAttribute_t* attrib, uint8* vboOutput, uint32 vboStride) @@ -40,21 +36,11 @@ void _setAttributeBufferPointerRaw(uint32 attributeShaderLoc, uint8* buffer, uin bool isSigned = attrib->isSigned != 0; uint8 nfa = attrib->nfa; // don't call glVertexAttribIPointer if parameters have not changed - if ( - CommonRenderer_getAttributePointerCacheVboOutput(attributeShaderLoc) == vboOutput && - CommonRenderer_getAttributePointerCacheVboStride(attributeShaderLoc) == vboStride && - CommonRenderer_getAttributePointerCacheDataFormat(attributeShaderLoc) == dataFormat && - CommonRenderer_getAttributePointerCacheNfa(attributeShaderLoc) == nfa && - CommonRenderer_getAttributePointerCacheIsSigned(attributeShaderLoc) == isSigned - ) - { + bool attributePointerChanged = CommonRenderer_checkIfAttributePointerCacheChanged(attributeShaderLoc, vboOutput, vboStride, dataFormat, nfa, isSigned); + if (!attributePointerChanged) { return; } - CommonRenderer_setAttributePointerCacheVboOutput(attributeShaderLoc, vboOutput); - CommonRenderer_setAttributePointerCacheVboStride(attributeShaderLoc, vboStride); - CommonRenderer_setAttributePointerCacheDataFormat(attributeShaderLoc, dataFormat); - CommonRenderer_setAttributePointerCacheNfa(attributeShaderLoc, nfa); - CommonRenderer_setAttributePointerCacheIsSigned(attributeShaderLoc, isSigned); + // setup attribute pointer if (dataFormat == FMT_32_32_32_32_FLOAT || dataFormat == FMT_32_32_32_32) { @@ -385,70 +371,6 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde indexState->indexData = (uint8*)(size_t)cacheEntry->heapEntry->startOffset; } -void LatteDraw_handleSpecialState8_clearAsDepth() -{ - if (LatteGPUState.contextNew.GetSpecialStateValues()[0] == 0) - cemuLog_logDebug(LogType::Force, "Special state 8 requires special state 0 but it is not set?"); - // get depth buffer information - uint32 regDepthBuffer = LatteGPUState.contextRegister[mmDB_HTILE_DATA_BASE]; - uint32 regDepthSize = LatteGPUState.contextRegister[mmDB_DEPTH_SIZE]; - uint32 regDepthBufferInfo = LatteGPUState.contextRegister[mmDB_DEPTH_INFO]; - // get format and tileMode from info reg - uint32 depthBufferTileMode = (regDepthBufferInfo >> 15) & 0xF; - - MPTR depthBufferPhysMem = regDepthBuffer << 8; - uint32 depthBufferPitch = (((regDepthSize >> 0) & 0x3FF) + 1); - uint32 depthBufferHeight = ((((regDepthSize >> 10) & 0xFFFFF) + 1) / depthBufferPitch); - depthBufferPitch <<= 3; - depthBufferHeight <<= 3; - uint32 depthBufferWidth = depthBufferPitch; - - sint32 sliceIndex = 0; // todo - sint32 mipIndex = 0; - - // clear all color buffers that match the format of the depth buffer - sint32 searchIndex = 0; - bool targetFound = false; - while (true) - { - LatteTextureView* view = LatteTC_LookupTextureByData(depthBufferPhysMem, depthBufferWidth, depthBufferHeight, depthBufferPitch, 0, 1, sliceIndex, 1, &searchIndex); - if (!view) - { - // should we clear in RAM instead? - break; - } - sint32 effectiveClearWidth = view->baseTexture->width; - sint32 effectiveClearHeight = view->baseTexture->height; - LatteTexture_scaleToEffectiveSize(view->baseTexture, &effectiveClearWidth, &effectiveClearHeight, 0); - - // hacky way to get clear color - float* regClearColor = (float*)(LatteGPUState.contextRegister + 0xC000 + 0); // REG_BASE_ALU_CONST - - uint8 clearColor[4] = { 0 }; - clearColor[0] = (uint8)(regClearColor[0] * 255.0f); - clearColor[1] = (uint8)(regClearColor[1] * 255.0f); - clearColor[2] = (uint8)(regClearColor[2] * 255.0f); - clearColor[3] = (uint8)(regClearColor[3] * 255.0f); - - // todo - use fragment shader software emulation (evoke for one pixel) to determine clear color - // todo - dont clear entire slice, use effectiveClearWidth, effectiveClearHeight - - if (g_renderer->GetType() == RendererAPI::OpenGL) - { - //cemu_assert_debug(false); // implement g_renderer->texture_clearColorSlice properly for OpenGL renderer - if (glClearTexSubImage) - glClearTexSubImage(((LatteTextureViewGL*)view)->glTexId, mipIndex, 0, 0, 0, effectiveClearWidth, effectiveClearHeight, 1, GL_RGBA, GL_UNSIGNED_BYTE, clearColor); - } - else - { - if (view->baseTexture->isDepth) - g_renderer->texture_clearDepthSlice(view->baseTexture, sliceIndex + view->firstSlice, mipIndex + view->firstMip, true, view->baseTexture->hasStencil, 0.0f, 0); - else - g_renderer->texture_clearColorSlice(view->baseTexture, sliceIndex + view->firstSlice, mipIndex + view->firstMip, clearColor[0], clearColor[1], clearColor[2], clearColor[3]); - } - } -} - void LatteDrawGL_doDraw(_INDEX_TYPE indexType, uint32 baseVertex, uint32 baseInstance, uint32 instanceCount, uint32 count) { indexState_t* indexState = CommonRenderer_getIndexState(); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp index a6814186..d0933e35 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp @@ -1221,6 +1221,7 @@ void VulkanRenderer::draw_endRenderPass() m_state.activeRenderpassFBO = nullptr; } +// Defined in the Common renderer void LatteDraw_handleSpecialState8_clearAsDepth(); // transfer depth buffer data to color buffer From e30558a5032e76f3ad69dc3cb54bd1fad9d659ac Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 00:55:17 +0100 Subject: [PATCH 12/32] move LatteDefaultShaders to opengl only and add ifdef opengl to latteshader_prepareseparableuniforms --- src/Cafe/CMakeLists.txt | 4 ++-- src/Cafe/HW/Latte/Core/LatteShaderGL.cpp | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index f6b427e9..828f87f2 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -106,8 +106,6 @@ add_library(CemuCafe HW/Latte/Core/LatteCachedFBO.h HW/Latte/Core/LatteCommandProcessor.cpp HW/Latte/Core/LatteConst.h - HW/Latte/Core/LatteDefaultShaders.cpp - HW/Latte/Core/LatteDefaultShaders.h HW/Latte/Core/LatteDraw.h HW/Latte/Core/LatteGSCopyShaderParser.cpp HW/Latte/Core/Latte.h @@ -497,6 +495,8 @@ add_library(CemuCafe if (ENABLE_OPENGL) target_sources(CemuCafe PRIVATE + HW/Latte/Core/LatteDefaultShaders.cpp + HW/Latte/Core/LatteDefaultShaders.h HW/Latte/Renderer/OpenGL/CachedFBOGL.h HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp HW/Latte/Renderer/OpenGL/LatteTextureGL.h diff --git a/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp b/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp index 09c484e6..f708f53a 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp @@ -26,6 +26,7 @@ bool gxShader_checkIfSuccessfullyLinked(GLuint glProgram) void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader) { +#ifdef ENABLE_OPENGL if (g_renderer->GetType() != RendererAPI::OpenGL) return; @@ -65,6 +66,7 @@ void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader) shader->uniform.list_ufTexRescale.push_back(entry); } } +#endif } GLuint gpu7ShaderGLDepr_compileShader(const std::string& source, uint32_t type) { From b02a2cd2c05108664795e412c252101752b3222a Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 01:02:19 +0100 Subject: [PATCH 13/32] move cmake compile definitions to appropriate place --- CMakeLists.txt | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e5f8ad7..adc78b44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,13 +115,6 @@ option(ENABLE_VULKAN "Enables the Vulkan backend" ON) option(ENABLE_METAL "Enables the Metal backend" ${ENABLE_METAL_DEFAULT}) option(ENABLE_DISCORD_RPC "Enables the Discord Rich Presence feature" ON) -if (ENABLE_OPENGL) - add_compile_definitions(ENABLE_OPENGL) -endif() -if (ENABLE_VULKAN) - add_compile_definitions(ENABLE_VULKAN) -endif() - if (ENABLE_METAL AND NOT APPLE) message(FATAL_ERROR "Metal backend is only supported on Apple platforms") endif() @@ -192,10 +185,12 @@ endif() if (ENABLE_VULKAN) include_directories("dependencies/Vulkan-Headers/include") + add_compile_definitions(ENABLE_VULKAN) endif() if (ENABLE_OPENGL) find_package(OpenGL REQUIRED) + add_compile_definitions(ENABLE_OPENGL) endif() if (ENABLE_METAL) From b6d0c66e91c094fcaab1bfb95eef5b8d2524776b Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 01:05:46 +0100 Subject: [PATCH 14/32] use correct include file for glcleartexsubimage --- src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp index a8a26eb4..19690550 100644 --- a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp @@ -4,7 +4,7 @@ #include "config/CemuConfig.h" #ifdef ENABLE_OPENGL -#include "Common/GLInclude/glFunctions.h" +#include "Common/GLInclude/GLInclude.h" #include "Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.h" #endif From 5ee1759deebc6277f257269352862ed976b0dea8 Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 01:28:16 +0100 Subject: [PATCH 15/32] fix graphic api setting and selection in GeneralSettings2 and MainWindow --- src/config/CemuConfig.h | 1 + src/gui/wxgui/GeneralSettings2.cpp | 2 +- src/gui/wxgui/GeneralSettings2.h | 2 - src/gui/wxgui/MainWindow.cpp | 66 ++++++++++++++++++++++-------- 4 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/config/CemuConfig.h b/src/config/CemuConfig.h index 6778ceb5..dafad429 100644 --- a/src/config/CemuConfig.h +++ b/src/config/CemuConfig.h @@ -65,6 +65,7 @@ struct GraphicPackEntry bool enabled = true; }; +#define GRAPHIC_API_COUNT 3 enum GraphicAPI { kOpenGL = 0, diff --git a/src/gui/wxgui/GeneralSettings2.cpp b/src/gui/wxgui/GeneralSettings2.cpp index 6d57b5ac..d7a3d0e8 100644 --- a/src/gui/wxgui/GeneralSettings2.cpp +++ b/src/gui/wxgui/GeneralSettings2.cpp @@ -357,7 +357,7 @@ wxPanel* GeneralSettings2::AddGraphicsPage(wxNotebook* notebook) row->Add(new wxStaticText(box, wxID_ANY, _("Graphics API")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); sint32 api_size = 0; - wxString choices[NUM_GRAPHICS_APIS]; + wxString choices[GRAPHIC_API_COUNT]; #ifdef ENABLE_OPENGL choices[api_size++] = "OpenGL"; diff --git a/src/gui/wxgui/GeneralSettings2.h b/src/gui/wxgui/GeneralSettings2.h index 77c5fe49..5615b433 100644 --- a/src/gui/wxgui/GeneralSettings2.h +++ b/src/gui/wxgui/GeneralSettings2.h @@ -17,8 +17,6 @@ class wxStaticText; wxDECLARE_EVENT(wxEVT_ACCOUNTLIST_REFRESH, wxCommandEvent); -#define NUM_GRAPHICS_APIS 3 - class GeneralSettings2 : public wxDialog { public: diff --git a/src/gui/wxgui/MainWindow.cpp b/src/gui/wxgui/MainWindow.cpp index 4efb172a..ddb95419 100644 --- a/src/gui/wxgui/MainWindow.cpp +++ b/src/gui/wxgui/MainWindow.cpp @@ -1606,23 +1606,57 @@ void MainWindow::CreateCanvas() m_game_panel->SetSizer(sizer); this->GetSizer()->Add(m_game_panel, 1, wxEXPAND); - // create canvas - if (ActiveSettings::GetGraphicsAPI() == kVulkan) - { - #ifdef ENABLE_VULKAN - m_render_canvas = new VulkanCanvas(m_game_panel, wxSize(1280, 720), true); - #endif - } - else if (ActiveSettings::GetGraphicsAPI() == kOpenGL) - { - #ifdef ENABLE_OPENGL - m_render_canvas = GLCanvas_Create(m_game_panel, wxSize(1280, 720), true); - #endif - } -#if ENABLE_METAL - else - m_render_canvas = new MetalCanvas(m_game_panel, wxSize(1280, 720), true); + GraphicAPI available_apis[GRAPHIC_API_COUNT]; + int count = 0; +#ifdef ENABLE_OPENGL + if (count < GRAPHIC_API_COUNT) available_apis[count++] = kOpenGL; #endif +#ifdef ENABLE_VULKAN + if (count < GRAPHIC_API_COUNT) available_apis[count++] = kVulkan; +#endif +#ifdef ENABLE_METAL + if (count < GRAPHIC_API_COUNT) available_apis[count++] = kMetal; +#endif + cemu_assert(count > 0); + + GraphicAPI selected = ActiveSettings::GetGraphicsAPI(); + bool found = false; + + for (int i = 0; i < count; i++) + { + if (available_apis[i] == selected) + { + printf("Selected graphics API: %d\n", selected); + found = true; + break; + } + } + + if (!found) + selected = available_apis[0]; + + // create canvas + switch (selected) + { + case kVulkan: +#if defined(ENABLE_VULKAN) + m_render_canvas = new VulkanCanvas(m_game_panel, wxSize(1280, 720), true); + break; +#endif + case kOpenGL: +#if defined(ENABLE_OPENGL) + m_render_canvas = GLCanvas_Create(m_game_panel, wxSize(1280, 720), true); + break; +#endif + case kMetal: +#if defined(ENABLE_METAL) + m_render_canvas = new MetalCanvas(m_game_panel, wxSize(1280, 720), true); + break; +#endif + default: + cemu_assert(false && "Invalid graphics API selected"); + break; + } cemu_assert(m_render_canvas != nullptr); From 8d8722a264228d43853d0e976b9ce58d258ab365 Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 01:34:53 +0100 Subject: [PATCH 16/32] pragma once the LatteRingBuffer header --- src/Cafe/HW/Latte/Core/LatteRingBuffer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Cafe/HW/Latte/Core/LatteRingBuffer.h b/src/Cafe/HW/Latte/Core/LatteRingBuffer.h index ce28c483..325836cc 100644 --- a/src/Cafe/HW/Latte/Core/LatteRingBuffer.h +++ b/src/Cafe/HW/Latte/Core/LatteRingBuffer.h @@ -1,3 +1,4 @@ +#pragma once typedef struct { From 238323b9fe2e7c4a061a1b3da5a496682541a274 Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 01:49:22 +0100 Subject: [PATCH 17/32] whoopsies misplaced my bracket --- src/gui/wxgui/GeneralSettings2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/wxgui/GeneralSettings2.cpp b/src/gui/wxgui/GeneralSettings2.cpp index d7a3d0e8..671e78ad 100644 --- a/src/gui/wxgui/GeneralSettings2.cpp +++ b/src/gui/wxgui/GeneralSettings2.cpp @@ -1843,8 +1843,8 @@ void GeneralSettings2::HandleGraphicsApiSelection() } break; } - } #endif + } } void GeneralSettings2::ApplyConfig() From e98a725c0b8462973e5625cdf32ba75e809be966 Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 01:50:35 +0100 Subject: [PATCH 18/32] remove "Currently required" from ENABLE_OPENGL in build.md --- BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index 1e7b7336..7fcf9a65 100644 --- a/BUILD.md +++ b/BUILD.md @@ -240,7 +240,7 @@ Example usage: `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DENABLE_SDL=ON - | CEMU_CXX_FLAGS | | Flags passed straight to the compiler, e.g. `-march=native`, `-Wall`, `/W3` | "" | | | ENABLE_CUBEB | | Enable cubeb audio backend | ON | | | ENABLE_DISCORD_RPC | | Enable Discord Rich presence support | ON | | -| ENABLE_OPENGL | | Enable OpenGL graphics backend | ON | Currently required | +| ENABLE_OPENGL | | Enable OpenGL graphics backend | ON | | | ENABLE_HIDAPI | | Enable HIDAPI (used for Wiimote controller API) | ON | | | ENABLE_SDL | | Enable SDLController controller API | ON | Currently required | | ENABLE_VCPKG | | Use VCPKG package manager to obtain dependencies | ON | | From 46ab3966ff6eb3f956c8854b315044ee8188abbf Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 02:15:56 +0100 Subject: [PATCH 19/32] build macos with no opengl as default --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index adc78b44..f6f914bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,11 +106,13 @@ endif() if (APPLE) set(ENABLE_METAL_DEFAULT ON) + set(ENABLE_OPENGL_DEFAULT OFF) else() set(ENABLE_METAL_DEFAULT OFF) + set(ENABLE_OPENGL_DEFAULT ON) endif() -option(ENABLE_OPENGL "Enables the OpenGL backend" ON) +option(ENABLE_OPENGL "Enables the OpenGL backend" ${ENABLE_OPENGL_DEFAULT}) option(ENABLE_VULKAN "Enables the Vulkan backend" ON) option(ENABLE_METAL "Enables the Metal backend" ${ENABLE_METAL_DEFAULT}) option(ENABLE_DISCORD_RPC "Enables the Discord Rich Presence feature" ON) From b6bcb954c461e3704745d6871fd60587ed31fb64 Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 02:59:35 +0100 Subject: [PATCH 20/32] give consistent config values for selecting graphic apis --- src/gui/wxgui/GeneralSettings2.cpp | 11 ++++++-- src/gui/wxgui/MainWindow.cpp | 41 +++++------------------------- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/src/gui/wxgui/GeneralSettings2.cpp b/src/gui/wxgui/GeneralSettings2.cpp index 671e78ad..12535eb8 100644 --- a/src/gui/wxgui/GeneralSettings2.cpp +++ b/src/gui/wxgui/GeneralSettings2.cpp @@ -1230,7 +1230,7 @@ void GeneralSettings2::StoreConfig() } // graphics - config.graphic_api = (GraphicAPI)m_graphic_api->GetSelection(); + config.graphic_api = m_api_map[m_graphic_api->GetSelection()]; selection = m_graphic_device->GetSelection(); #ifdef ENABLE_VULKAN @@ -1898,7 +1898,14 @@ void GeneralSettings2::ApplyConfig() } // graphics - m_graphic_api->SetSelection((int)config.graphic_api); + for (int i = 0; i < (int)m_api_map.size(); ++i) + { + if (m_api_map[i] == config.graphic_api) + { + m_graphic_api->SetSelection(i); + break; + } + } m_vsync->SetSelection(config.vsync); m_overrideGamma->SetValue(config.overrideAppGammaPreference); m_overrideGammaValue->SetValue(config.overrideGammaValue); diff --git a/src/gui/wxgui/MainWindow.cpp b/src/gui/wxgui/MainWindow.cpp index ddb95419..7dd8ed8f 100644 --- a/src/gui/wxgui/MainWindow.cpp +++ b/src/gui/wxgui/MainWindow.cpp @@ -1606,47 +1606,18 @@ void MainWindow::CreateCanvas() m_game_panel->SetSizer(sizer); this->GetSizer()->Add(m_game_panel, 1, wxEXPAND); - GraphicAPI available_apis[GRAPHIC_API_COUNT]; - int count = 0; -#ifdef ENABLE_OPENGL - if (count < GRAPHIC_API_COUNT) available_apis[count++] = kOpenGL; -#endif -#ifdef ENABLE_VULKAN - if (count < GRAPHIC_API_COUNT) available_apis[count++] = kVulkan; -#endif -#ifdef ENABLE_METAL - if (count < GRAPHIC_API_COUNT) available_apis[count++] = kMetal; -#endif - cemu_assert(count > 0); - - GraphicAPI selected = ActiveSettings::GetGraphicsAPI(); - bool found = false; - - for (int i = 0; i < count; i++) - { - if (available_apis[i] == selected) - { - printf("Selected graphics API: %d\n", selected); - found = true; - break; - } - } - - if (!found) - selected = available_apis[0]; - // create canvas - switch (selected) + switch (ActiveSettings::GetGraphicsAPI()) { - case kVulkan: -#if defined(ENABLE_VULKAN) - m_render_canvas = new VulkanCanvas(m_game_panel, wxSize(1280, 720), true); - break; -#endif case kOpenGL: #if defined(ENABLE_OPENGL) m_render_canvas = GLCanvas_Create(m_game_panel, wxSize(1280, 720), true); break; +#endif + case kVulkan: +#if defined(ENABLE_VULKAN) + m_render_canvas = new VulkanCanvas(m_game_panel, wxSize(1280, 720), true); + break; #endif case kMetal: #if defined(ENABLE_METAL) From 53fe038e82d2622f0383b3e81c6acfdf0bf48f2e Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 02:59:52 +0100 Subject: [PATCH 21/32] change default graphic api values depending on what's enabled --- src/config/CemuConfig.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/config/CemuConfig.h b/src/config/CemuConfig.h index dafad429..94f6c4ed 100644 --- a/src/config/CemuConfig.h +++ b/src/config/CemuConfig.h @@ -430,7 +430,13 @@ struct CemuConfig ConfigValueBounds console_language{ CafeConsoleLanguage::EN }; // graphics +#if defined(ENABLE_VULKAN) ConfigValue graphic_api{ kVulkan }; +#elif defined(ENABLE_METAL) + ConfigValue graphic_api{ kMetal }; +#elif defined(ENABLE_OPENGL) + ConfigValue graphic_api{ kOpenGL }; +#endif std::array legacy_graphic_device_uuid{}; // placeholder option for backwards compatibility with settings from 2.6 and before (renamed to "vkDevice") std::array vk_graphic_device_uuid; uint64 mtl_graphic_device_uuid{ 0 }; From 5ede01ac6dc3670cd8b733d35c481d8b1922252c Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Tue, 21 Apr 2026 10:54:19 +0200 Subject: [PATCH 22/32] also remove empty if statement when vulkan is disabled on macOS --- src/Cafe/HW/Latte/Core/LatteBufferData.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/LatteBufferData.cpp b/src/Cafe/HW/Latte/Core/LatteBufferData.cpp index 9d606e72..33d148bb 100644 --- a/src/Cafe/HW/Latte/Core/LatteBufferData.cpp +++ b/src/Cafe/HW/Latte/Core/LatteBufferData.cpp @@ -198,10 +198,9 @@ bool LatteBufferCache_Sync(uint32 minIndex, uint32 maxIndex, uint32 baseInstance fixedBufferSize += 128; -#if BOOST_OS_MACOS +#if BOOST_OS_MACOS && defined(ENABLE_VULKAN) if(bufferStride % 4 != 0) { - #ifdef ENABLE_VULKAN if (g_renderer->GetType() == RendererAPI::Vulkan) { if (VulkanRenderer* vkRenderer = VulkanRenderer::GetInstance()) @@ -211,7 +210,6 @@ bool LatteBufferCache_Sync(uint32 minIndex, uint32 maxIndex, uint32 baseInstance continue; } } - #endif } #endif From db4b8f3a9d4a758f502d1a3a94323d77f49aab4d Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 12:06:57 +0100 Subject: [PATCH 23/32] move Common/CommonRendererCore -> RendererCore --- .../Renderer/OpenGL/OpenGLRendererCore.cpp | 38 +++++++++---------- ...ommonRendererCore.cpp => RendererCore.cpp} | 25 ++++++------ .../CommonRendererCore.h => RendererCore.h} | 18 ++++----- 3 files changed, 41 insertions(+), 40 deletions(-) rename src/Cafe/HW/Latte/Renderer/{Common/CommonRendererCore.cpp => RendererCore.cpp} (89%) rename src/Cafe/HW/Latte/Renderer/{Common/CommonRendererCore.h => RendererCore.h} (74%) diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp index 94620cda..bcac9199 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp @@ -27,7 +27,7 @@ extern bool hasValidFramebufferAttached; void LatteDraw_resetAttributePointerCache() { - CommonRenderer_resetAttributePointerCache(); + RendererCore_resetAttributePointerCache(); } void _setAttributeBufferPointerRaw(uint32 attributeShaderLoc, uint8* buffer, uint32 bufferSize, uint32 stride, LatteParsedFetchShaderAttribute_t* attrib, uint8* vboOutput, uint32 vboStride) @@ -36,7 +36,7 @@ void _setAttributeBufferPointerRaw(uint32 attributeShaderLoc, uint8* buffer, uin bool isSigned = attrib->isSigned != 0; uint8 nfa = attrib->nfa; // don't call glVertexAttribIPointer if parameters have not changed - bool attributePointerChanged = CommonRenderer_checkIfAttributePointerCacheChanged(attributeShaderLoc, vboOutput, vboStride, dataFormat, nfa, isSigned); + bool attributePointerChanged = RendererCore_checkIfAttributePointerCacheChanged(attributeShaderLoc, vboOutput, vboStride, dataFormat, nfa, isSigned); if (!attributePointerChanged) { return; } @@ -139,7 +139,7 @@ void OpenGLRenderer::SetAttributeArrayState(uint32 index, bool isEnabled, sint32 // Sets the currently active element array buffer and binds it void OpenGLRenderer::SetArrayElementBuffer(GLuint arrayElementBuffer) { - indexState_t* indexState = CommonRenderer_getIndexState(); + indexState_t* indexState = RendererCore_getIndexState(); if (arrayElementBuffer == indexState->glActiveElementArrayBuffer) return; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrayElementBuffer); @@ -150,7 +150,7 @@ void _decodeAndUploadIndexData(indexDataCacheEntry2_t* cacheEntry) { uint32 count = cacheEntry->key.count; uint32 primitiveRestartIndex = cacheEntry->key.primitiveRestartIndex; - indexState_t *indexState = CommonRenderer_getIndexState(); + indexState_t *indexState = RendererCore_getIndexState(); if (cacheEntry->indexType == _INDEX_TYPE::U16_BE) { // 16bit indices @@ -227,16 +227,16 @@ void _decodeAndUploadIndexData(indexDataCacheEntry2_t* cacheEntry) void LatteDrawGL_removeLeastRecentlyUsedIndexCacheEntries(sint32 count) { - indexState_t *indexState = CommonRenderer_getIndexState(); - indexDataCacheEntry2_t** indexDataCacheFirst = CommonRenderer_getIndexDataCacheFirst(); + indexState_t *indexState = RendererCore_getIndexState(); + indexDataCacheEntry2_t** indexDataCacheFirst = RendererCore_getIndexDataCacheFirst(); while (*indexDataCacheFirst && count > 0) { indexDataCacheEntry2_t* entry = *indexDataCacheFirst; // remove entry virtualBufferHeap_free(indexState->indexBufferVirtualHeap, entry->heapEntry); - CommonRenderer_removeFromUsageLinkedList(entry); - CommonRenderer_removeFromBucket(entry); + RendererCore_removeFromUsageLinkedList(entry); + RendererCore_removeFromBucket(entry); free(entry); count--; } @@ -274,8 +274,8 @@ uint32 LatteDrawGL_calculateIndexDataHash(uint8* data, uint32 size) // todo - Outdated cache implementation. Update OpenGL renderer to use the generic implementation that is also used by the Vulkan renderer void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE indexType, sint32 count, sint32 primitiveMode) { - indexState_t* indexState = CommonRenderer_getIndexState(); - indexDataCacheEntry2_t** indexDataCacheFirst = CommonRenderer_getIndexDataCacheFirst(); + indexState_t* indexState = RendererCore_getIndexState(); + indexDataCacheEntry2_t** indexDataCacheFirst = RendererCore_getIndexDataCacheFirst(); if (indexType == _INDEX_TYPE::AUTO) { @@ -289,7 +289,7 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde uint32 indexDataBucketIdx = (uint32)((indexDataMPTR + count) ^ (indexDataMPTR >> 16)) % INDEX_DATA_CACHE_BUCKETS; // find matching entry uint32 primitiveRestartIndex = LatteGPUState.contextNew.VGT_MULTI_PRIM_IB_RESET_INDX.get_RESTART_INDEX(); - indexDataCacheEntry2_t* cacheEntryItr = *CommonRenderer_getIndexDataCacheBucket(indexDataBucketIdx); + indexDataCacheEntry2_t* cacheEntryItr = *RendererCore_getIndexDataCacheBucket(indexDataBucketIdx); indexDataCacheKey_t compareKey; compareKey.physAddr = indexDataMPTR; compareKey.count = count; @@ -317,8 +317,8 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde cacheEntryItr->hash = h; } // move entry to the front - CommonRenderer_removeFromUsageLinkedList(cacheEntryItr); - CommonRenderer_appendToUsageLinkedList(cacheEntryItr); + RendererCore_removeFromUsageLinkedList(cacheEntryItr); + RendererCore_appendToUsageLinkedList(cacheEntryItr); return; } // calculate size of index data in cache @@ -356,15 +356,15 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde cacheEntry->heapEntry = heapEntry; cacheEntry->lastAccessFrameCount = LatteGPUState.frameCounter; // append entry in bucket list - indexDataCacheEntry2_t** bucket = CommonRenderer_getIndexDataCacheBucket(indexDataBucketIdx); + indexDataCacheEntry2_t** bucket = RendererCore_getIndexDataCacheBucket(indexDataBucketIdx); cacheEntry->nextInBucket = *bucket; *bucket = cacheEntry; // append as most recently used entry - CommonRenderer_appendToUsageLinkedList(cacheEntry); + RendererCore_appendToUsageLinkedList(cacheEntry); // decode and upload the data _decodeAndUploadIndexData(cacheEntry); - sint32* indexDataCacheEntryCount = CommonRenderer_getIndexDataCacheEntryCount(); + sint32* indexDataCacheEntryCount = RendererCore_getIndexDataCacheEntryCount(); (*indexDataCacheEntryCount)++; indexState->minIndex = cacheEntry->minIndex; indexState->maxIndex = cacheEntry->maxIndex; @@ -373,7 +373,7 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde void LatteDrawGL_doDraw(_INDEX_TYPE indexType, uint32 baseVertex, uint32 baseInstance, uint32 instanceCount, uint32 count) { - indexState_t* indexState = CommonRenderer_getIndexState(); + indexState_t* indexState = RendererCore_getIndexState(); if (indexType == _INDEX_TYPE::U16_BE) { // 16bit index, big endian @@ -824,7 +824,7 @@ void OpenGLRenderer::draw_genericDrawHandler(uint32 baseVertex, uint32 baseInsta endPerfMonProfiling(performanceMonitor.gpuTime_dcStageIndexMgr); // synchronize vertex and uniform buffers - indexState_t *indexState = CommonRenderer_getIndexState(); + indexState_t *indexState = RendererCore_getIndexState(); LatteBufferCache_Sync(indexState->minIndex + baseVertex, indexState->maxIndex + baseVertex, baseInstance, instanceCount); _setupVertexAttributes(); @@ -1016,7 +1016,7 @@ void OpenGLRenderer::draw_endSequence() void OpenGLRenderer::draw_init() { - indexState_t* indexState = CommonRenderer_getIndexState(); + indexState_t* indexState = RendererCore_getIndexState(); if (indexState->initialized) return; indexState->initialized = true; diff --git a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/RendererCore.cpp similarity index 89% rename from src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp rename to src/Cafe/HW/Latte/Renderer/RendererCore.cpp index 19690550..4a6a82d5 100644 --- a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/RendererCore.cpp @@ -1,4 +1,4 @@ -#include "CommonRendererCore.h" +#include "RendererCore.h" #include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Cafe/HW/Latte/ISA/RegDefines.h" #include "config/CemuConfig.h" @@ -16,7 +16,7 @@ indexDataCacheEntry2_t* indexDataCacheFirst = nullptr; // points to least recent indexDataCacheEntry2_t* indexDataCacheLast = nullptr; // points to most recently used item sint32 indexDataCacheEntryCount = 0; -void CommonRenderer_resetAttributePointerCache() +void RendererCore_resetAttributePointerCache() { for (sint32 i = 0; i < LATTE_VS_ATTRIBUTE_LIMIT; i++) { @@ -25,7 +25,7 @@ void CommonRenderer_resetAttributePointerCache() } } -bool CommonRenderer_checkIfAttributePointerCacheChanged(uint32 attributeShaderLoc, uint8* vboOutput, uint32 vboStride, uint8 dataFormat, uint8 nfa, bool isSigned) +bool RendererCore_checkIfAttributePointerCacheChanged(uint32 attributeShaderLoc, uint8* vboOutput, uint32 vboStride, uint8 dataFormat, uint8 nfa, bool isSigned) { // don't call glVertexAttribPointer if parameters have not changed if ( @@ -47,27 +47,27 @@ bool CommonRenderer_checkIfAttributePointerCacheChanged(uint32 attributeShaderLo return true; } -indexState_t* CommonRenderer_getIndexState() +indexState_t* RendererCore_getIndexState() { return &indexState; } -indexDataCacheEntry2_t** CommonRenderer_getIndexDataCacheFirst() +indexDataCacheEntry2_t** RendererCore_getIndexDataCacheFirst() { return &indexDataCacheFirst; } -indexDataCacheEntry2_t** CommonRenderer_getIndexDataCacheBucket(uint32 bucketIdx) +indexDataCacheEntry2_t** RendererCore_getIndexDataCacheBucket(uint32 bucketIdx) { return &indexDataCacheBucket[bucketIdx]; } -sint32* CommonRenderer_getIndexDataCacheEntryCount() +sint32* RendererCore_getIndexDataCacheEntryCount() { return &indexDataCacheEntryCount; } -void CommonRenderer_appendToUsageLinkedList(indexDataCacheEntry2_t* entry) +void RendererCore_appendToUsageLinkedList(indexDataCacheEntry2_t* entry) { if (indexDataCacheLast == nullptr) { @@ -85,7 +85,7 @@ void CommonRenderer_appendToUsageLinkedList(indexDataCacheEntry2_t* entry) } } -void CommonRenderer_removeFromUsageLinkedList(indexDataCacheEntry2_t* entry) +void RendererCore_removeFromUsageLinkedList(indexDataCacheEntry2_t* entry) { if (entry->prevInMostRecentUsage) { @@ -103,7 +103,7 @@ void CommonRenderer_removeFromUsageLinkedList(indexDataCacheEntry2_t* entry) entry->nextInMostRecentUsage = nullptr; } -void CommonRenderer_removeFromBucket(indexDataCacheEntry2_t* entry) +void RendererCore_removeFromBucket(indexDataCacheEntry2_t* entry) { uint32 indexDataBucketIdx = (uint32)((entry->key.physAddr + entry->key.count) ^ (entry->key.physAddr >> 16)) % INDEX_DATA_CACHE_BUCKETS; if (indexDataCacheBucket[indexDataBucketIdx] == entry) @@ -137,8 +137,8 @@ void LatteDraw_cleanupAfterFrame() break; // remove entry virtualBufferHeap_free(indexState.indexBufferVirtualHeap, entry->heapEntry); - CommonRenderer_removeFromUsageLinkedList(entry); - CommonRenderer_removeFromBucket(entry); + RendererCore_removeFromUsageLinkedList(entry); + RendererCore_removeFromBucket(entry); free(entry); } } @@ -200,6 +200,7 @@ void LatteDraw_handleSpecialState8_clearAsDepth() //cemu_assert_debug(false); // implement g_renderer->texture_clearColorSlice properly for OpenGL renderer if (glClearTexSubImage) glClearTexSubImage(((LatteTextureViewGL*)view)->glTexId, mipIndex, 0, 0, 0, effectiveClearWidth, effectiveClearHeight, 1, GL_RGBA, GL_UNSIGNED_BYTE, clearColor); + break; } #endif default: diff --git a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h b/src/Cafe/HW/Latte/Renderer/RendererCore.h similarity index 74% rename from src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h rename to src/Cafe/HW/Latte/Renderer/RendererCore.h index 1866c30c..1c681373 100644 --- a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h +++ b/src/Cafe/HW/Latte/Renderer/RendererCore.h @@ -77,16 +77,16 @@ typedef struct _indexDataCacheEntry_t _indexDataCacheEntry_t* prevInMostRecentUsage; // points to element which was used less recently }indexDataCacheEntry2_t; -void CommonRenderer_resetAttributePointerCache(); -bool CommonRenderer_checkIfAttributePointerCacheChanged(uint32 attributeShaderLoc, uint8* vboOutput, uint32 vboStride, uint8 dataFormat, uint8 nfa, bool isSigned); +void RendererCore_resetAttributePointerCache(); +bool RendererCore_checkIfAttributePointerCacheChanged(uint32 attributeShaderLoc, uint8* vboOutput, uint32 vboStride, uint8 dataFormat, uint8 nfa, bool isSigned); -indexState_t* CommonRenderer_getIndexState(); -indexDataCacheEntry2_t** CommonRenderer_getIndexDataCacheFirst(); -indexDataCacheEntry2_t** CommonRenderer_getIndexDataCacheBucket(uint32 bucketIdx); -sint32* CommonRenderer_getIndexDataCacheEntryCount(); +indexState_t* RendererCore_getIndexState(); +indexDataCacheEntry2_t** RendererCore_getIndexDataCacheFirst(); +indexDataCacheEntry2_t** RendererCore_getIndexDataCacheBucket(uint32 bucketIdx); +sint32* RendererCore_getIndexDataCacheEntryCount(); -void CommonRenderer_appendToUsageLinkedList(indexDataCacheEntry2_t* entry); -void CommonRenderer_removeFromUsageLinkedList(indexDataCacheEntry2_t* entry); -void CommonRenderer_removeFromBucket(indexDataCacheEntry2_t* entry); +void RendererCore_appendToUsageLinkedList(indexDataCacheEntry2_t* entry); +void RendererCore_removeFromUsageLinkedList(indexDataCacheEntry2_t* entry); +void RendererCore_removeFromBucket(indexDataCacheEntry2_t* entry); void LatteDraw_cleanupAfterFrame(); void LatteDraw_handleSpecialState8_clearAsDepth(); \ No newline at end of file From 6e7d95714a28766c014c194a92f06d98cd314112 Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 12:20:54 +0100 Subject: [PATCH 24/32] fix cmakelists --- src/Cafe/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index 828f87f2..dc4f8ae8 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -162,12 +162,12 @@ add_library(CemuCafe HW/Latte/LegacyShaderDecompiler/LatteDecompilerRegisterDataTypeTracker.cpp HW/Latte/Renderer/Renderer.cpp HW/Latte/Renderer/Renderer.h + HW/Latte/Renderer/RendererCore.cpp + HW/Latte/Renderer/RendererCore.h HW/Latte/Renderer/RendererOuputShader.cpp HW/Latte/Renderer/RendererOuputShader.h HW/Latte/Renderer/RendererShader.cpp HW/Latte/Renderer/RendererShader.h - HW/Latte/Renderer/Common/CommonRendererCore.cpp - HW/Latte/Renderer/Common/CommonRendererCore.h HW/Latte/ShaderInfo/ShaderDescription.cpp HW/Latte/ShaderInfo/ShaderInfo.h HW/Latte/ShaderInfo/ShaderInstanceInfo.cpp From 594f377671aa97368252d889134d00a9c642cfbe Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 12:26:33 +0100 Subject: [PATCH 25/32] isolate more stuffs to opengl/vulkan only --- src/Cafe/HW/Latte/Core/FetchShader.cpp | 11 +++- src/Cafe/HW/Latte/Core/LatteShader.cpp | 12 +++- src/Cafe/HW/Latte/Core/LatteShaderCache.cpp | 13 +++- src/Cafe/HW/Latte/Core/LatteTexture.cpp | 3 + src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp | 5 +- .../HW/Latte/Renderer/RendererOuputShader.cpp | 60 ++++++++++++++----- 6 files changed, 79 insertions(+), 25 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/FetchShader.cpp b/src/Cafe/HW/Latte/Core/FetchShader.cpp index 7d724e13..3018474d 100644 --- a/src/Cafe/HW/Latte/Core/FetchShader.cpp +++ b/src/Cafe/HW/Latte/Core/FetchShader.cpp @@ -108,15 +108,22 @@ void LatteShader_calculateFSKey(LatteFetchShader* fetchShader) key = std::rotl(key, 8); key += (uint64)attrib->semanticId; key = std::rotl(key, 8); - if (g_renderer->GetType() == RendererAPI::Metal) + switch(g_renderer->GetType()) + { +#if ENABLE_METAL + case RendererAPI::Metal: { key += (uint64)attrib->offset; key = std::rotl(key, 7); + break; } - else +#endif + default: { key += (uint64)(attrib->offset & 3); key = std::rotl(key, 2); + break; + } } } } diff --git a/src/Cafe/HW/Latte/Core/LatteShader.cpp b/src/Cafe/HW/Latte/Core/LatteShader.cpp index 2f9bac94..4f916619 100644 --- a/src/Cafe/HW/Latte/Core/LatteShader.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShader.cpp @@ -552,7 +552,7 @@ void LatteSHRC_UpdateVSBaseHash(uint8* vertexShaderPtr, uint32 vertexShaderSize, vsHash += 51ULL; // Vertex fetch - if (_activeFetchShader->mtlFetchVertexManually) + if (_activeFetchShader->mtlFetchVertexManually) vsHash += 349ULL; } } @@ -807,12 +807,12 @@ void LatteShader_GetDecompilerOptions(LatteDecompilerOptions& options, LatteCons options.usesGeometryShader = geometryShaderEnabled; options.spirvInstrinsics.hasRoundingModeRTEFloat32 = false; options.useTFViaSSBO = g_renderer->UseTFViaSSBO(); - #ifdef ENABLE_VULKAN +#ifdef ENABLE_VULKAN if (g_renderer->GetType() == RendererAPI::Vulkan) { options.spirvInstrinsics.hasRoundingModeRTEFloat32 = VulkanRenderer::GetInstance()->HasSPRIVRoundingModeRTE32(); } - #endif +#endif options.strictMul = g_current_game_profile->GetAccurateShaderMul() != AccurateShaderMulOption::False; } @@ -888,12 +888,14 @@ LatteDecompilerShader* LatteShader_CompileSeparableVertexShader(uint64 baseHash, LatteShader_CreateRendererShader(vertexShader, false); performanceMonitor.numCompiledVS++; +#ifdef ENABLE_OPENGL if (g_renderer->GetType() == RendererAPI::OpenGL) { if (vertexShader->shader) vertexShader->shader->PreponeCompilation(true); LatteShader_FinishCompilation(vertexShader); } +#endif LatteSHRC_RegisterShader(vertexShader, vertexShader->baseHash, vertexShader->auxHash); return vertexShader; @@ -917,12 +919,14 @@ LatteDecompilerShader* LatteShader_CompileSeparableGeometryShader(uint64 baseHas LatteShader_CreateRendererShader(geometryShader, false); performanceMonitor.numCompiledGS++; +#ifdef ENABLE_OPENGL if (g_renderer->GetType() == RendererAPI::OpenGL) { if (geometryShader->shader) geometryShader->shader->PreponeCompilation(true); LatteShader_FinishCompilation(geometryShader); } +#endif LatteSHRC_RegisterShader(geometryShader, geometryShader->baseHash, geometryShader->auxHash); return geometryShader; @@ -946,12 +950,14 @@ LatteDecompilerShader* LatteShader_CompileSeparablePixelShader(uint64 baseHash, LatteShaderCache_writeSeparablePixelShader(_shaderBaseHash_ps, psAuxHash, pixelShaderPtr, pixelShaderSize, LatteGPUState.contextRegister, usesGeometryShader); } +#ifdef ENABLE_OPENGL if (g_renderer->GetType() == RendererAPI::OpenGL) { if (pixelShader->shader) pixelShader->shader->PreponeCompilation(true); LatteShader_FinishCompilation(pixelShader); } +#endif LatteSHRC_RegisterShader(pixelShader, _shaderBaseHash_ps, psAuxHash); return pixelShader; diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index 2f9b3f13..94dc838a 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -394,10 +394,17 @@ void LatteShaderCache_Load() // get cache file name fs::path pathGeneric; - if (g_renderer->GetType() == RendererAPI::Metal) + switch(g_renderer->GetType()) + { +#if ENABLE_METAL + case RendererAPI::Metal: pathGeneric = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}_mtlshaders.bin", cacheTitleId); - else + break; +#endif + default: pathGeneric = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}_shaders.bin", cacheTitleId); + break; + } // calculate extraVersion for transferable and precompiled shader cache uint32 transferableExtraVersion = SHADER_CACHE_GENERIC_EXTRA_VERSION; @@ -495,8 +502,10 @@ void LatteShaderCache_Load() #endif LatteShaderCache_finish(); // if Vulkan or Metal then also load pipeline cache +#if defined(ENABLE_VULKAN) || ENABLE_METAL if (g_renderer->GetType() == RendererAPI::Vulkan || g_renderer->GetType() == RendererAPI::Metal) LatteShaderCache_LoadPipelineCache(cacheTitleId); +#endif g_renderer->BeginFrame(true); diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.cpp b/src/Cafe/HW/Latte/Core/LatteTexture.cpp index 4445fb26..82dd1fbf 100644 --- a/src/Cafe/HW/Latte/Core/LatteTexture.cpp +++ b/src/Cafe/HW/Latte/Core/LatteTexture.cpp @@ -567,6 +567,8 @@ bool __LatteTexture_IsBlockedFormatRelation(LatteTexture* texture1, LatteTexture if (texture1->format == Latte::E_GX2SURFFMT::D32_FLOAT && Latte::GetHWFormat(texture2->format) == Latte::E_HWSURFFMT::HWFMT_8_8_8_8) return true; } + +#ifdef ENABLE_VULKAN // Vulkan has stricter rules if (g_renderer->GetType() == RendererAPI::Vulkan) { @@ -574,6 +576,7 @@ bool __LatteTexture_IsBlockedFormatRelation(LatteTexture* texture1, LatteTexture if (texture1->format == Latte::E_GX2SURFFMT::D32_FLOAT && Latte::GetHWFormat(texture2->format) == Latte::E_HWSURFFMT::HWFMT_8_24) return true; } +#endif return false; } diff --git a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp index f54cf064..7b8a0b7b 100644 --- a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp +++ b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp @@ -194,7 +194,7 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u LatteGPUState.repeatTextureInitialization = true; } - #ifdef ENABLE_OPENGL +#ifdef ENABLE_OPENGL if (g_renderer->GetType() == RendererAPI::OpenGL) { // on OpenGL, texture views and sampler parameters are tied together (we are avoiding sampler objects due to driver bugs) @@ -217,7 +217,8 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u textureView->lastTextureBindIndex = LatteGPUState.textureBindCounter; rendererGL->renderstate_updateTextureSettingsGL(shaderContext, textureView, textureIndex + glBackendBaseTexUnit, word4, textureIndex, isDepthSampler); } - #endif +#endif + g_renderer->texture_setLatteTexture(textureView, textureIndex + glBackendBaseTexUnit); // update if data changed bool swizzleChanged = false; diff --git a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp index 3c417e2b..5fc6c176 100644 --- a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp +++ b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp @@ -250,10 +250,17 @@ fragment float4 main0(VertexOut in [[stage_in]], texture2d textureSrc [[t RendererOutputShader::RendererOutputShader(const std::string& vertex_source, const std::string& fragment_source) { std::string finalFragmentSrc; - if (g_renderer->GetType() == RendererAPI::Metal) - finalFragmentSrc = fragment_source; - else - finalFragmentSrc = PrependFragmentPreamble(fragment_source); + switch(g_renderer->GetType()) + { +#if defined(ENABLE_METAL) + case RendererAPI::Metal: + finalFragmentSrc = fragment_source; + break; +#endif + default: + finalFragmentSrc = PrependFragmentPreamble(fragment_source); + break; + } m_vertex_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kVertex, 0, 0, vertex_source, false, false)); m_fragment_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kFragment, 0, 0, finalFragmentSrc, false, false)); @@ -488,7 +495,10 @@ void main() } void RendererOutputShader::InitializeStatic() { - if (g_renderer->GetType() == RendererAPI::Metal) + switch(g_renderer->GetType()) + { +#if ENABLE_METAL + case RendererAPI::Metal: { std::string vertex_source = GetMetalVertexSource(false); std::string vertex_source_ud = GetMetalVertexSource(true); @@ -501,21 +511,17 @@ void RendererOutputShader::InitializeStatic() s_hermit_shader = new RendererOutputShader(vertex_source, s_hermite_shader_source_mtl); s_hermit_shader_ud = new RendererOutputShader(vertex_source_ud, s_hermite_shader_source_mtl); + break; } - else +#endif +#ifdef ENABLE_OPENGL + case RendererAPI::OpenGL: { std::string vertex_source, vertex_source_ud; // vertex shader - if (g_renderer->GetType() == RendererAPI::OpenGL) - { - vertex_source = GetOpenGlVertexSource(false); - vertex_source_ud = GetOpenGlVertexSource(true); - } - else if (g_renderer->GetType() == RendererAPI::Vulkan) - { - vertex_source = GetVulkanVertexSource(false); - vertex_source_ud = GetVulkanVertexSource(true); - } + vertex_source = GetOpenGlVertexSource(false); + vertex_source_ud = GetOpenGlVertexSource(true); + s_copy_shader = new RendererOutputShader(vertex_source, s_copy_shader_source); s_copy_shader_ud = new RendererOutputShader(vertex_source_ud, s_copy_shader_source); @@ -524,7 +530,29 @@ void RendererOutputShader::InitializeStatic() s_hermit_shader = new RendererOutputShader(vertex_source, s_hermite_shader_source); s_hermit_shader_ud = new RendererOutputShader(vertex_source_ud, s_hermite_shader_source); + break; } +#endif +#ifdef ENABLE_VULKAN + case RendererAPI::Vulkan: + { + std::string vertex_source, vertex_source_ud; + // vertex shader + vertex_source = GetVulkanVertexSource(false); + vertex_source_ud = GetVulkanVertexSource(true); + + s_copy_shader = new RendererOutputShader(vertex_source, s_copy_shader_source); + s_copy_shader_ud = new RendererOutputShader(vertex_source_ud, s_copy_shader_source); + + s_bicubic_shader = new RendererOutputShader(vertex_source, s_bicubic_shader_source); + s_bicubic_shader_ud = new RendererOutputShader(vertex_source_ud, s_bicubic_shader_source); + + s_hermit_shader = new RendererOutputShader(vertex_source, s_hermite_shader_source); + s_hermit_shader_ud = new RendererOutputShader(vertex_source_ud, s_hermite_shader_source); + break; + } +#endif + } } void RendererOutputShader::ShutdownStatic() From d0852812cc9ba727b5e2436980950aa78130b995 Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:20:52 +0200 Subject: [PATCH 26/32] fix linux build without openGL --- src/Cafe/CMakeLists.txt | 2 +- src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp | 2 +- src/Cafe/HW/Latte/Core/LatteShader.cpp | 2 ++ src/Cafe/HW/Latte/Core/LatteShaderGL.cpp | 2 -- src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index dc4f8ae8..5de8a085 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -125,7 +125,6 @@ add_library(CemuCafe HW/Latte/Core/LatteShaderCache.cpp HW/Latte/Core/LatteShaderCache.h HW/Latte/Core/LatteShader.cpp - HW/Latte/Core/LatteShaderGL.cpp HW/Latte/Core/LatteShader.h HW/Latte/Core/LatteSoftware.cpp HW/Latte/Core/LatteSoftware.h @@ -497,6 +496,7 @@ if (ENABLE_OPENGL) target_sources(CemuCafe PRIVATE HW/Latte/Core/LatteDefaultShaders.cpp HW/Latte/Core/LatteDefaultShaders.h + HW/Latte/Core/LatteShaderGL.cpp HW/Latte/Renderer/OpenGL/CachedFBOGL.h HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp HW/Latte/Renderer/OpenGL/LatteTextureGL.h diff --git a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp index b5053df8..96b7316b 100644 --- a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp +++ b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp @@ -10,7 +10,7 @@ #include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h" #include "Cafe/GraphicPack/GraphicPack2.h" -#include "HW/Latte/Renderer/Common/CommonRendererCore.h" +#include "HW/Latte/Renderer/RendererCore.h" #include "config/ActiveSettings.h" #include "WindowSystem.h" #include "Cafe/OS/libs/erreula/erreula.h" diff --git a/src/Cafe/HW/Latte/Core/LatteShader.cpp b/src/Cafe/HW/Latte/Core/LatteShader.cpp index 4f916619..bc379659 100644 --- a/src/Cafe/HW/Latte/Core/LatteShader.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShader.cpp @@ -378,7 +378,9 @@ void LatteShader_FinishCompilation(LatteDecompilerShader* shader) } shader->shader->WaitForCompiled(); +#ifdef ENABLE_OPENGL LatteShader_prepareSeparableUniforms(shader); +#endif LatteShader_CleanupAfterCompile(shader); } diff --git a/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp b/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp index f708f53a..09c484e6 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp @@ -26,7 +26,6 @@ bool gxShader_checkIfSuccessfullyLinked(GLuint glProgram) void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader) { -#ifdef ENABLE_OPENGL if (g_renderer->GetType() != RendererAPI::OpenGL) return; @@ -66,7 +65,6 @@ void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader) shader->uniform.list_ufTexRescale.push_back(entry); } } -#endif } GLuint gpu7ShaderGLDepr_compileShader(const std::string& source, uint32_t type) { diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp index bcac9199..8e190743 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp @@ -13,7 +13,7 @@ #include "Cafe/HW/Latte/Renderer/OpenGL/CachedFBOGL.h" #include "Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h" -#include "Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h" +#include "Cafe/HW/Latte/Renderer/RendererCore.h" #include "Cafe/HW/Latte/ISA/RegDefines.h" #include "Cafe/OS/libs/gx2/GX2.h" From df997bc9c8eb79963b708be1000d706ad7b6b91e Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 12:38:30 +0100 Subject: [PATCH 27/32] use #ifdef for ENABLE_METAL too to be consistent --- CMakeLists.txt | 2 +- src/Cafe/CafeSystem.cpp | 2 +- src/Cafe/GameProfile/GameProfile.cpp | 8 +++--- src/Cafe/GameProfile/GameProfile.h | 4 +-- src/Cafe/HW/Latte/Core/FetchShader.cpp | 12 ++++----- src/Cafe/HW/Latte/Core/FetchShader.h | 2 +- src/Cafe/HW/Latte/Core/LatteShader.cpp | 10 +++---- src/Cafe/HW/Latte/Core/LatteShaderCache.cpp | 20 +++++++------- .../LatteDecompiler.cpp | 2 +- .../LatteDecompilerAnalyzer.cpp | 10 +++---- .../LatteDecompilerInternal.h | 2 +- .../HW/Latte/Renderer/RendererOuputShader.cpp | 4 +-- src/config/CemuConfig.cpp | 8 +++--- src/config/CemuConfig.h | 4 +-- src/gui/wxgui/GameProfileWindow.cpp | 8 +++--- src/gui/wxgui/GameProfileWindow.h | 2 +- src/gui/wxgui/GeneralSettings2.cpp | 26 +++++++++---------- src/gui/wxgui/GeneralSettings2.h | 4 +-- src/gui/wxgui/MainWindow.cpp | 14 +++++----- src/gui/wxgui/PadViewFrame.cpp | 4 +-- src/gui/wxgui/wxWindowSystem.cpp | 2 +- 21 files changed, 75 insertions(+), 75 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f6f914bd..5ebfdca3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,7 +198,7 @@ endif() if (ENABLE_METAL) include_directories(${CMAKE_SOURCE_DIR}/dependencies/metal-cpp) - add_definitions(-DENABLE_METAL=1) + add_compile_definitions(ENABLE_METAL) endif() if (ENABLE_DISCORD_RPC) diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp index f016773c..fc0d1ae6 100644 --- a/src/Cafe/CafeSystem.cpp +++ b/src/Cafe/CafeSystem.cpp @@ -251,7 +251,7 @@ void InfoLog_PrintActiveSettings() if (!GetConfig().vk_accurate_barriers.GetValue()) cemuLog_log(LogType::Force, "Accurate barriers are disabled!"); } -#if ENABLE_METAL +#ifdef ENABLE_METAL else if (ActiveSettings::GetGraphicsAPI() == GraphicAPI::kMetal) { cemuLog_log(LogType::Force, "Async compile: {}", GetConfig().async_compile.GetValue() ? "true" : "false"); diff --git a/src/Cafe/GameProfile/GameProfile.cpp b/src/Cafe/GameProfile/GameProfile.cpp index 9ee0a696..5c15d7c3 100644 --- a/src/Cafe/GameProfile/GameProfile.cpp +++ b/src/Cafe/GameProfile/GameProfile.cpp @@ -226,7 +226,7 @@ bool GameProfile::Load(uint64_t title_id) m_graphics_api = (GraphicAPI)graphicsApi.value; gameProfile_loadEnumOption(iniParser, "accurateShaderMul", m_accurateShaderMul); -#if ENABLE_METAL +#ifdef ENABLE_METAL gameProfile_loadBooleanOption2(iniParser, "shaderFastMath", m_shaderFastMath); gameProfile_loadEnumOption(iniParser, "metalBufferCacheMode2", m_metalBufferCacheMode); gameProfile_loadEnumOption(iniParser, "positionInvariance2", m_positionInvariance); @@ -311,7 +311,7 @@ void GameProfile::Save(uint64_t title_id) fs->writeLine("[Graphics]"); WRITE_ENTRY(accurateShaderMul); -#if ENABLE_METAL +#ifdef ENABLE_METAL WRITE_ENTRY(shaderFastMath); WRITE_ENTRY_NUMBERED(metalBufferCacheMode, 2); WRITE_ENTRY_NUMBERED(positionInvariance, 2); @@ -346,7 +346,7 @@ void GameProfile::ResetOptional() // graphic settings m_accurateShaderMul = AccurateShaderMulOption::True; -#if ENABLE_METAL +#ifdef ENABLE_METAL m_shaderFastMath = true; m_metalBufferCacheMode = MetalBufferCacheMode::Auto; m_positionInvariance = PositionInvariance::Auto; @@ -371,7 +371,7 @@ void GameProfile::Reset() // graphic settings m_accurateShaderMul = AccurateShaderMulOption::True; -#if ENABLE_METAL +#ifdef ENABLE_METAL m_shaderFastMath = true; m_metalBufferCacheMode = MetalBufferCacheMode::Auto; m_positionInvariance = PositionInvariance::Auto; diff --git a/src/Cafe/GameProfile/GameProfile.h b/src/Cafe/GameProfile/GameProfile.h index 5155beac..06c2a13b 100644 --- a/src/Cafe/GameProfile/GameProfile.h +++ b/src/Cafe/GameProfile/GameProfile.h @@ -29,7 +29,7 @@ public: [[nodiscard]] const std::optional& GetGraphicsAPI() const { return m_graphics_api; } [[nodiscard]] const AccurateShaderMulOption& GetAccurateShaderMul() const { return m_accurateShaderMul; } -#if ENABLE_METAL +#ifdef ENABLE_METAL [[nodiscard]] bool GetShaderFastMath() const { return m_shaderFastMath; } [[nodiscard]] MetalBufferCacheMode GetBufferCacheMode() const { return m_metalBufferCacheMode; } [[nodiscard]] PositionInvariance GetPositionInvariance() const { return m_positionInvariance; } @@ -57,7 +57,7 @@ private: // graphic settings std::optional m_graphics_api{}; AccurateShaderMulOption m_accurateShaderMul = AccurateShaderMulOption::True; -#if ENABLE_METAL +#ifdef ENABLE_METAL bool m_shaderFastMath = true; MetalBufferCacheMode m_metalBufferCacheMode = MetalBufferCacheMode::Auto; PositionInvariance m_positionInvariance = PositionInvariance::Auto; diff --git a/src/Cafe/HW/Latte/Core/FetchShader.cpp b/src/Cafe/HW/Latte/Core/FetchShader.cpp index 3018474d..4ea633ba 100644 --- a/src/Cafe/HW/Latte/Core/FetchShader.cpp +++ b/src/Cafe/HW/Latte/Core/FetchShader.cpp @@ -11,7 +11,7 @@ #include "HW/Latte/Renderer/Renderer.h" #include "util/containers/LookupTableL3.h" #include "util/helpers/fspinlock.h" -#if ENABLE_METAL +#ifdef ENABLE_METAL #include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h" #endif #include /* SHA1_DIGEST_LENGTH */ @@ -110,7 +110,7 @@ void LatteShader_calculateFSKey(LatteFetchShader* fetchShader) key = std::rotl(key, 8); switch(g_renderer->GetType()) { -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: { key += (uint64)attrib->offset; @@ -129,7 +129,7 @@ void LatteShader_calculateFSKey(LatteFetchShader* fetchShader) } // todo - also hash invalid buffer groups? -#if ENABLE_METAL +#ifdef ENABLE_METAL if (g_renderer->GetType() == RendererAPI::Metal) { for (sint32 g = 0; g < fetchShader->bufferGroups.size(); g++) @@ -178,7 +178,7 @@ void LatteFetchShader::CalculateFetchShaderVkHash() this->vkPipelineHashFragment = h; } -#if ENABLE_METAL +#ifdef ENABLE_METAL void LatteFetchShader::CheckIfVerticesNeedManualFetchMtl(uint32* contextRegister) { for (sint32 g = 0; g < bufferGroups.size(); g++) @@ -383,7 +383,7 @@ LatteFetchShader* LatteShaderRecompiler_createFetchShader(LatteFetchShader::Cach // these only make sense when vertex shader does not call FS? LatteShader_calculateFSKey(newFetchShader); newFetchShader->CalculateFetchShaderVkHash(); -#if ENABLE_METAL +#ifdef ENABLE_METAL newFetchShader->CheckIfVerticesNeedManualFetchMtl(contextRegister); #endif return newFetchShader; @@ -445,7 +445,7 @@ LatteFetchShader* LatteShaderRecompiler_createFetchShader(LatteFetchShader::Cach } LatteShader_calculateFSKey(newFetchShader); newFetchShader->CalculateFetchShaderVkHash(); -#if ENABLE_METAL +#ifdef ENABLE_METAL newFetchShader->CheckIfVerticesNeedManualFetchMtl(contextRegister); #endif diff --git a/src/Cafe/HW/Latte/Core/FetchShader.h b/src/Cafe/HW/Latte/Core/FetchShader.h index 54cf6ada..db72987b 100644 --- a/src/Cafe/HW/Latte/Core/FetchShader.h +++ b/src/Cafe/HW/Latte/Core/FetchShader.h @@ -55,7 +55,7 @@ struct LatteFetchShader void CalculateFetchShaderVkHash(); -#if ENABLE_METAL +#ifdef ENABLE_METAL void CheckIfVerticesNeedManualFetchMtl(uint32* contextRegister); #endif diff --git a/src/Cafe/HW/Latte/Core/LatteShader.cpp b/src/Cafe/HW/Latte/Core/LatteShader.cpp index bc379659..c2730821 100644 --- a/src/Cafe/HW/Latte/Core/LatteShader.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShader.cpp @@ -17,7 +17,7 @@ #include "config/ActiveSettings.h" #include "Cafe/GameProfile/GameProfile.h" #include "util/containers/flat_hash_map.hpp" -#if ENABLE_METAL +#ifdef ENABLE_METAL #include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h" #endif #include @@ -529,7 +529,7 @@ void LatteSHRC_UpdateVSBaseHash(uint8* vertexShaderPtr, uint32 vertexShaderSize, if (LatteGPUState.contextNew.PA_CL_CLIP_CNTL.get_DX_CLIP_SPACE_DEF()) vsHash += 0x1537; -#if ENABLE_METAL +#ifdef ENABLE_METAL if (g_renderer->GetType() == RendererAPI::Metal) { bool isRectVertexShader = (primitiveType == Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::RECTS); @@ -654,7 +654,7 @@ uint64 LatteSHRC_CalcPSAuxHash(LatteDecompilerShader* pixelShader, uint32* conte auxHash += (uint64)dim; } -#if ENABLE_METAL +#ifdef ENABLE_METAL if (g_renderer->GetType() == RendererAPI::Metal) { // Textures as render targets @@ -744,7 +744,7 @@ LatteDecompilerShader* LatteShader_CreateShaderFromDecompilerOutput(LatteDecompi shader->resourceMapping = decompilerOutput.resourceMappingVK; break; #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: shader->resourceMapping = decompilerOutput.resourceMappingMTL; break; @@ -770,7 +770,7 @@ LatteDecompilerShader* LatteShader_CreateShaderFromDecompilerOutput(LatteDecompi InitUniformLayoutFromDecompiler(shader, decompilerOutput); break; #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: InitUniformLayoutFromDecompiler(shader, decompilerOutput); break; diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index 94dc838a..a1b0e777 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -16,7 +16,7 @@ #include "Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h" #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.h" #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL #include "Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h" #endif @@ -289,7 +289,7 @@ void LatteShaderCache_finish() RendererShaderGL::ShaderCacheLoading_end(); return; #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: RendererShaderMtl::ShaderCacheLoading_end(); return; @@ -385,7 +385,7 @@ void LatteShaderCache_Load() RendererShaderGL::ShaderCacheLoading_begin(cacheTitleId); break; #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: RendererShaderMtl::ShaderCacheLoading_begin(cacheTitleId); break; @@ -396,7 +396,7 @@ void LatteShaderCache_Load() fs::path pathGeneric; switch(g_renderer->GetType()) { -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: pathGeneric = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}_mtlshaders.bin", cacheTitleId); break; @@ -502,7 +502,7 @@ void LatteShaderCache_Load() #endif LatteShaderCache_finish(); // if Vulkan or Metal then also load pipeline cache -#if defined(ENABLE_VULKAN) || ENABLE_METAL +#if defined(ENABLE_VULKAN) || defined(ENABLE_METAL) if (g_renderer->GetType() == RendererAPI::Vulkan || g_renderer->GetType() == RendererAPI::Metal) LatteShaderCache_LoadPipelineCache(cacheTitleId); #endif @@ -674,7 +674,7 @@ void LatteShaderCache_LoadPipelineCache(uint64 cacheTitleId) g_shaderCacheLoaderState.pipelineFileCount = VulkanPipelineStableCache::GetInstance().BeginLoading(cacheTitleId); break; #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: g_shaderCacheLoaderState.pipelineFileCount = MetalPipelineCache::GetInstance().BeginLoading(cacheTitleId); break; @@ -691,7 +691,7 @@ void LatteShaderCache_LoadPipelineCache(uint64 cacheTitleId) VulkanPipelineStableCache::GetInstance().EndLoading(); break; #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: MetalPipelineCache::GetInstance().EndLoading(); break; @@ -708,7 +708,7 @@ bool LatteShaderCache_updatePipelineLoadingProgress() case RendererAPI::Vulkan: return VulkanPipelineStableCache::GetInstance().UpdateLoading(g_shaderCacheLoaderState.loadedPipelines, pipelinesMissingShaders); #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: return MetalPipelineCache::GetInstance().UpdateLoading(g_shaderCacheLoaderState.loadedPipelines, pipelinesMissingShaders); #endif @@ -984,7 +984,7 @@ void LatteShaderCache_Close() RendererShaderGL::ShaderCacheLoading_Close(); break; #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: RendererShaderMtl::ShaderCacheLoading_Close(); break; @@ -999,7 +999,7 @@ void LatteShaderCache_Close() VulkanPipelineStableCache::GetInstance().Close(); break; #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: MetalPipelineCache::GetInstance().Close(); break; diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp index 028ac359..6b358150 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp @@ -1083,7 +1083,7 @@ void _LatteDecompiler_Process(LatteDecompilerShaderContext* shaderContext, uint8 LatteDecompiler_emitGLSLShader(shaderContext, shaderContext->shader); break; #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: LatteDecompiler_emitMSLShader(shaderContext, shaderContext->shader); break; diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp index 18cba4b4..7739943b 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp @@ -10,7 +10,7 @@ #include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Common/MemPtr.h" #include "HW/Latte/ISA/LatteReg.h" -#if ENABLE_METAL +#ifdef ENABLE_METAL #include "HW/Latte/Renderer/Metal/MetalCommon.h" #endif @@ -403,7 +403,7 @@ void LatteDecompiler_analyzeExport(LatteDecompilerShaderContext* shaderContext, } else if (cfInstruction->exportType == 0 && cfInstruction->exportArrayBase == 61) { -#if ENABLE_METAL +#ifdef ENABLE_METAL // Only check for depth buffer mask on Metal, as its not in the PS hash on other backends if (g_renderer->GetType() != RendererAPI::Metal || LatteMRT::GetActiveDepthBufferMask(*shaderContext->contextRegistersNew)) shader->depthMask = true; @@ -512,7 +512,7 @@ namespace LatteDecompiler } } -#if ENABLE_METAL +#ifdef ENABLE_METAL void _initTextureBindingPointsMTL(LatteDecompilerShaderContext* decompilerContext) { // for Vulkan we use consecutive indices @@ -563,7 +563,7 @@ namespace LatteDecompiler { decompilerContext->hasUniformVarBlock = true; // uf_verticesPerInstance and uf_streamoutBufferBase* } -#if ENABLE_METAL +#ifdef ENABLE_METAL if (g_renderer->GetType() == RendererAPI::Metal) { bool usesGeometryShader = UseGeometryShader(*decompilerContext->contextRegistersNew, decompilerContext->options->usesGeometryShader); @@ -1113,7 +1113,7 @@ void LatteDecompiler_analyze(LatteDecompilerShaderContext* shaderContext, LatteD shaderContext->output->resourceMappingVK.setIndex = 2; LatteDecompiler::_initTextureBindingPointsGL(shaderContext); LatteDecompiler::_initTextureBindingPointsVK(shaderContext); -#if ENABLE_METAL +#ifdef ENABLE_METAL LatteDecompiler::_initTextureBindingPointsMTL(shaderContext); #endif LatteDecompiler::_initUniformBindingPoints(shaderContext); diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h index 4c6b158a..0b19bcae 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h @@ -266,7 +266,7 @@ struct LatteDecompilerShaderContext void LatteDecompiler_analyze(LatteDecompilerShaderContext* shaderContext, LatteDecompilerShader* shader); void LatteDecompiler_analyzeDataTypes(LatteDecompilerShaderContext* shaderContext); void LatteDecompiler_emitGLSLShader(LatteDecompilerShaderContext* shaderContext, LatteDecompilerShader* shader); -#if ENABLE_METAL +#ifdef ENABLE_METAL void LatteDecompiler_emitMSLShader(LatteDecompilerShaderContext* shaderContext, LatteDecompilerShader* shader); #endif diff --git a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp index 5fc6c176..1acb4f47 100644 --- a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp +++ b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp @@ -252,7 +252,7 @@ RendererOutputShader::RendererOutputShader(const std::string& vertex_source, con std::string finalFragmentSrc; switch(g_renderer->GetType()) { -#if defined(ENABLE_METAL) +#ifdef ENABLE_METAL case RendererAPI::Metal: finalFragmentSrc = fragment_source; break; @@ -497,7 +497,7 @@ void RendererOutputShader::InitializeStatic() { switch(g_renderer->GetType()) { -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: { std::string vertex_source = GetMetalVertexSource(false); diff --git a/src/config/CemuConfig.cpp b/src/config/CemuConfig.cpp index 097587f8..17a67af0 100644 --- a/src/config/CemuConfig.cpp +++ b/src/config/CemuConfig.cpp @@ -144,7 +144,7 @@ XMLConfigParser CemuConfig::Load(XMLConfigParser& parser) fullscreen_scaling = graphic.get("FullscreenScaling", kKeepAspectRatio); async_compile = graphic.get("AsyncCompile", async_compile); vk_accurate_barriers = graphic.get("vkAccurateBarriers", true); // this used to be "VulkanAccurateBarriers" but because we changed the default to true in 1.27.1 the option name had to be changed -#if ENABLE_METAL +#ifdef ENABLE_METAL force_mesh_shaders = graphic.get("ForceMeshShaders", false); #endif @@ -273,7 +273,7 @@ XMLConfigParser CemuConfig::Load(XMLConfigParser& parser) crash_dump = debug.get("CrashDumpUnix", crash_dump); #endif gdb_port = debug.get("GDBPort", 1337); -#if ENABLE_METAL +#ifdef ENABLE_METAL gpu_capture_dir = debug.get("GPUCaptureDir", ""); framebuffer_fetch = debug.get("FramebufferFetch", true); #endif @@ -368,7 +368,7 @@ XMLConfigParser CemuConfig::Save(XMLConfigParser& parser) graphic.set("OverrideGammaValue", overrideGammaValue); graphic.set("UserDisplayGamma", userDisplayGamma); graphic.set("GX2DrawdoneSync", gx2drawdone_sync); -#if ENABLE_METAL +#ifdef ENABLE_METAL graphic.set("ForceMeshShaders", force_mesh_shaders); #endif //graphic.set("PrecompiledShaders", precompiled_shaders.GetValue()); @@ -437,7 +437,7 @@ XMLConfigParser CemuConfig::Save(XMLConfigParser& parser) debug.set("CrashDumpUnix", crash_dump.GetValue()); #endif debug.set("GDBPort", gdb_port); -#if ENABLE_METAL +#ifdef ENABLE_METAL debug.set("GPUCaptureDir", gpu_capture_dir); debug.set("FramebufferFetch", framebuffer_fetch); #endif diff --git a/src/config/CemuConfig.h b/src/config/CemuConfig.h index 94f6c4ed..152c2c3f 100644 --- a/src/config/CemuConfig.h +++ b/src/config/CemuConfig.h @@ -444,7 +444,7 @@ struct CemuConfig ConfigValue gx2drawdone_sync { true }; ConfigValue render_upside_down{ false }; ConfigValue async_compile{ true }; -#if ENABLE_METAL +#ifdef ENABLE_METAL ConfigValue force_mesh_shaders{ false }; #endif @@ -510,7 +510,7 @@ struct CemuConfig // debug ConfigValueBounds crash_dump{ CrashDump::Disabled }; ConfigValue gdb_port{ 1337 }; -#if ENABLE_METAL +#ifdef ENABLE_METAL ConfigValue gpu_capture_dir{ "" }; ConfigValue framebuffer_fetch{ true }; #endif diff --git a/src/gui/wxgui/GameProfileWindow.cpp b/src/gui/wxgui/GameProfileWindow.cpp index 37fac6bc..5962133e 100644 --- a/src/gui/wxgui/GameProfileWindow.cpp +++ b/src/gui/wxgui/GameProfileWindow.cpp @@ -113,7 +113,7 @@ GameProfileWindow::GameProfileWindow(wxWindow* parent, uint64_t title_id) first_row->Add(new wxStaticText(panel, wxID_ANY, _("Graphics API")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); wxString gapi_values[] = { "", "OpenGL", "Vulkan", -#if ENABLE_METAL +#ifdef ENABLE_METAL "Metal" #endif }; @@ -127,7 +127,7 @@ GameProfileWindow::GameProfileWindow(wxWindow* parent, uint64_t title_id) m_shader_mul_accuracy->SetToolTip(_("EXPERT OPTION\nControls the accuracy of floating point multiplication in shaders.\n\nRecommended: true")); first_row->Add(m_shader_mul_accuracy, 0, wxALL, 5); -#if ENABLE_METAL +#ifdef ENABLE_METAL first_row->Add(new wxStaticText(panel, wxID_ANY, _("Shader fast math")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); wxString math_values[] = { _("false"), _("true") }; @@ -296,7 +296,7 @@ void GameProfileWindow::ApplyProfile() else m_graphic_api->SetSelection(1 + m_game_profile.m_graphics_api.value()); // "", OpenGL, Vulkan, Metal m_shader_mul_accuracy->SetSelection((int)m_game_profile.m_accurateShaderMul); -#if ENABLE_METAL +#ifdef ENABLE_METAL m_shader_fast_math->SetSelection((int)m_game_profile.m_shaderFastMath); m_metal_buffer_cache_mode->SetSelection((int)m_game_profile.m_metalBufferCacheMode); m_position_invariance->SetSelection((int)m_game_profile.m_positionInvariance); @@ -362,7 +362,7 @@ void GameProfileWindow::SaveProfile() m_game_profile.m_accurateShaderMul = (AccurateShaderMulOption)m_shader_mul_accuracy->GetSelection(); if (m_game_profile.m_accurateShaderMul != AccurateShaderMulOption::False && m_game_profile.m_accurateShaderMul != AccurateShaderMulOption::True) m_game_profile.m_accurateShaderMul = AccurateShaderMulOption::True; // force a legal value -#if ENABLE_METAL +#ifdef ENABLE_METAL m_game_profile.m_shaderFastMath = (bool)m_shader_fast_math->GetSelection(); m_game_profile.m_metalBufferCacheMode = (MetalBufferCacheMode)m_metal_buffer_cache_mode->GetSelection(); m_game_profile.m_positionInvariance = (PositionInvariance)m_position_invariance->GetSelection(); diff --git a/src/gui/wxgui/GameProfileWindow.h b/src/gui/wxgui/GameProfileWindow.h index 3cb381d9..fe6150dc 100644 --- a/src/gui/wxgui/GameProfileWindow.h +++ b/src/gui/wxgui/GameProfileWindow.h @@ -40,7 +40,7 @@ private: wxChoice* m_graphic_api; wxChoice* m_shader_mul_accuracy; -#if ENABLE_METAL +#ifdef ENABLE_METAL wxChoice* m_shader_fast_math; wxChoice* m_metal_buffer_cache_mode; wxChoice* m_position_invariance; diff --git a/src/gui/wxgui/GeneralSettings2.cpp b/src/gui/wxgui/GeneralSettings2.cpp index 12535eb8..f556809e 100644 --- a/src/gui/wxgui/GeneralSettings2.cpp +++ b/src/gui/wxgui/GeneralSettings2.cpp @@ -31,7 +31,7 @@ #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h" #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h" #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL #include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h" #endif #include "Cafe/Account/Account.h" @@ -102,7 +102,7 @@ private: }; #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL class wxMetalUUID : public wxClientData { public: @@ -370,7 +370,7 @@ wxPanel* GeneralSettings2::AddGraphicsPage(wxNotebook* notebook) m_api_map.push_back(GraphicAPI::kVulkan); } #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL choices[api_size++] = "Metal"; m_api_map.push_back(GraphicAPI::kMetal); #endif @@ -414,7 +414,7 @@ wxPanel* GeneralSettings2::AddGraphicsPage(wxNotebook* notebook) m_gx2drawdone_sync->SetToolTip(_("If synchronization is requested by the game, the emulated CPU will wait for the GPU to finish all operations.\nThis is more accurate behavior, but may cause lower performance")); graphic_misc_row->Add(m_gx2drawdone_sync, 0, wxALL, 5); -#if ENABLE_METAL +#ifdef ENABLE_METAL m_force_mesh_shaders = new wxCheckBox(box, wxID_ANY, _("Force mesh shaders")); m_force_mesh_shaders->SetToolTip(_("Force mesh shaders on all GPUs that support them. Mesh shaders are disabled by default on Intel GPUs due to potential stability issues.\nMetal only")); graphic_misc_row->Add(m_force_mesh_shaders, 0, wxALL, 5); @@ -1042,7 +1042,7 @@ wxPanel* GeneralSettings2::AddDebugPage(wxNotebook* notebook) debug_panel_sizer->Add(debug_row, 0, wxALL | wxEXPAND, 5); } -#if ENABLE_METAL +#ifdef ENABLE_METAL { auto* debug_row = new wxFlexGridSizer(0, 2, 0, 0); debug_row->SetFlexibleDirection(wxBOTH); @@ -1248,7 +1248,7 @@ void GeneralSettings2::StoreConfig() config.vk_graphic_device_uuid = {}; } #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL if (config.graphic_api == GraphicAPI::kMetal) { if (selection != wxNOT_FOUND) @@ -1266,7 +1266,7 @@ void GeneralSettings2::StoreConfig() config.gx2drawdone_sync = m_gx2drawdone_sync->IsChecked(); -#if ENABLE_METAL +#ifdef ENABLE_METAL config.force_mesh_shaders = m_force_mesh_shaders->IsChecked(); #endif config.async_compile = m_async_compile->IsChecked(); @@ -1297,7 +1297,7 @@ void GeneralSettings2::StoreConfig() // debug config.crash_dump = (CrashDump)m_crash_dump->GetSelection(); config.gdb_port = m_gdb_port->GetValue(); -#if ENABLE_METAL +#ifdef ENABLE_METAL config.gpu_capture_dir = m_gpu_capture_dir->GetValue().utf8_string(); config.framebuffer_fetch = m_framebuffer_fetch->IsChecked(); #endif @@ -1757,7 +1757,7 @@ void GeneralSettings2::HandleGraphicsApiSelection() m_gx2drawdone_sync->Enable(); m_async_compile->Disable(); -#if ENABLE_METAL +#ifdef ENABLE_METAL m_force_mesh_shaders->Disable(); #endif break; @@ -1769,7 +1769,7 @@ void GeneralSettings2::HandleGraphicsApiSelection() // Vulkan m_gx2drawdone_sync->Disable(); m_async_compile->Enable(); -#if ENABLE_METAL +#ifdef ENABLE_METAL m_force_mesh_shaders->Disable(); #endif @@ -1806,7 +1806,7 @@ void GeneralSettings2::HandleGraphicsApiSelection() break; } #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL case GraphicAPI::kMetal: { // Metal @@ -1918,7 +1918,7 @@ void GeneralSettings2::ApplyConfig() } m_async_compile->SetValue(config.async_compile); m_gx2drawdone_sync->SetValue(config.gx2drawdone_sync); -#if ENABLE_METAL +#ifdef ENABLE_METAL m_force_mesh_shaders->SetValue(config.force_mesh_shaders); #endif m_upscale_filter->SetSelection(config.upscale_filter); @@ -2057,7 +2057,7 @@ void GeneralSettings2::ApplyConfig() // debug m_crash_dump->SetSelection((int)config.crash_dump.GetValue()); m_gdb_port->SetValue(config.gdb_port.GetValue()); -#if ENABLE_METAL +#ifdef ENABLE_METAL m_gpu_capture_dir->SetValue(wxString::FromUTF8(config.gpu_capture_dir.GetValue())); m_framebuffer_fetch->SetValue(config.framebuffer_fetch); #endif diff --git a/src/gui/wxgui/GeneralSettings2.h b/src/gui/wxgui/GeneralSettings2.h index 5615b433..2f7e3b68 100644 --- a/src/gui/wxgui/GeneralSettings2.h +++ b/src/gui/wxgui/GeneralSettings2.h @@ -73,7 +73,7 @@ private: wxCheckBox* m_userDisplayisSRGB; wxCheckBox *m_async_compile, *m_gx2drawdone_sync; -#if ENABLE_METAL +#ifdef ENABLE_METAL wxCheckBox *m_force_mesh_shaders; #endif wxRadioBox* m_upscale_filter, *m_downscale_filter, *m_fullscreen_scaling; @@ -101,7 +101,7 @@ private: // Debug wxChoice* m_crash_dump; wxSpinCtrl* m_gdb_port; -#if ENABLE_METAL +#ifdef ENABLE_METAL wxTextCtrl* m_gpu_capture_dir; wxCheckBox* m_framebuffer_fetch; #endif diff --git a/src/gui/wxgui/MainWindow.cpp b/src/gui/wxgui/MainWindow.cpp index 7dd8ed8f..94bdb004 100644 --- a/src/gui/wxgui/MainWindow.cpp +++ b/src/gui/wxgui/MainWindow.cpp @@ -17,7 +17,7 @@ #ifdef ENABLE_VULKAN #include "wxgui/canvas/VulkanCanvas.h" #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL #include "wxgui/canvas/MetalCanvas.h" #endif #include "Cafe/OS/libs/nfc/nfc.h" @@ -72,7 +72,7 @@ #include "gamemode_client.h" #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL #include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h" #endif @@ -1043,7 +1043,7 @@ void MainWindow::OnDebugSetting(wxCommandEvent& event) if(!GetConfig().vk_accurate_barriers) wxMessageBox(_("Warning: Disabling the accurate barriers option will lead to flickering graphics but may improve performance. It is highly recommended to leave it turned on."), _("Accurate barriers are off"), wxOK); } -#if ENABLE_METAL +#ifdef ENABLE_METAL else if (event.GetId() == MAINFRAME_MENU_ID_DEBUG_GPU_CAPTURE) { cemu_assert_debug(g_renderer->GetType() == RendererAPI::Metal); @@ -1610,17 +1610,17 @@ void MainWindow::CreateCanvas() switch (ActiveSettings::GetGraphicsAPI()) { case kOpenGL: -#if defined(ENABLE_OPENGL) +#ifdef ENABLE_OPENGL m_render_canvas = GLCanvas_Create(m_game_panel, wxSize(1280, 720), true); break; #endif case kVulkan: -#if defined(ENABLE_VULKAN) +#ifdef ENABLE_VULKAN m_render_canvas = new VulkanCanvas(m_game_panel, wxSize(1280, 720), true); break; #endif case kMetal: -#if defined(ENABLE_METAL) +#ifdef ENABLE_METAL m_render_canvas = new MetalCanvas(m_game_panel, wxSize(1280, 720), true); break; #endif @@ -2370,7 +2370,7 @@ void MainWindow::RecreateMenu() auto accurateBarriers = debugMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_VK_ACCURATE_BARRIERS, _("&Accurate barriers (Vulkan)")); accurateBarriers->Check(GetConfig().vk_accurate_barriers); -#if ENABLE_METAL +#ifdef ENABLE_METAL auto gpuCapture = debugMenu->Append(MAINFRAME_MENU_ID_DEBUG_GPU_CAPTURE, _("&GPU capture (Metal)")); gpuCapture->Enable(m_game_launched && g_renderer->GetType() == RendererAPI::Metal); #endif diff --git a/src/gui/wxgui/PadViewFrame.cpp b/src/gui/wxgui/PadViewFrame.cpp index 6bcdb079..b2e55a92 100644 --- a/src/gui/wxgui/PadViewFrame.cpp +++ b/src/gui/wxgui/PadViewFrame.cpp @@ -12,7 +12,7 @@ #ifdef ENABLE_VULKAN #include "wxgui/canvas/VulkanCanvas.h" #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL #include "wxgui/canvas/MetalCanvas.h" #endif #include "config/CemuConfig.h" @@ -91,7 +91,7 @@ void PadViewFrame::InitializeRenderCanvas() m_render_canvas = GLCanvas_Create(this, wxSize(854, 480), false); #endif } -#if ENABLE_METAL +#ifdef ENABLE_METAL else m_render_canvas = new MetalCanvas(this, wxSize(854, 480), false); #endif diff --git a/src/gui/wxgui/wxWindowSystem.cpp b/src/gui/wxgui/wxWindowSystem.cpp index d35e0ee8..b9e760ed 100644 --- a/src/gui/wxgui/wxWindowSystem.cpp +++ b/src/gui/wxgui/wxWindowSystem.cpp @@ -105,7 +105,7 @@ void WindowSystem::UpdateWindowTitles(bool isIdle, bool isLoading, double fps) renderer = "[Vulkan]"; break; #endif -#if ENABLE_METAL +#ifdef ENABLE_METAL case RendererAPI::Metal: renderer = "[Metal]"; break; From 3b0e5cef002f513da93be81f186c675adba0795e Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 12:43:28 +0100 Subject: [PATCH 28/32] fix LatteDecompilerAnalyzer checking for metal and then refusing metal lol --- .../HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp index 7739943b..e8d5d490 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp @@ -403,11 +403,9 @@ void LatteDecompiler_analyzeExport(LatteDecompilerShaderContext* shaderContext, } else if (cfInstruction->exportType == 0 && cfInstruction->exportArrayBase == 61) { -#ifdef ENABLE_METAL // Only check for depth buffer mask on Metal, as its not in the PS hash on other backends if (g_renderer->GetType() != RendererAPI::Metal || LatteMRT::GetActiveDepthBufferMask(*shaderContext->contextRegistersNew)) shader->depthMask = true; -#endif } else debugBreakpoint(); From a9f8e6430d2f0d6b1efb9bc5e5c8f7cbf6c0a4de Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:50:38 +0200 Subject: [PATCH 29/32] fix linux build without vulkan --- src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp | 2 + .../Renderer/OpenGL/OpenGLRendererCore.cpp | 281 ++++++++++++++---- src/Cafe/HW/Latte/Renderer/RendererCore.cpp | 191 ++++-------- src/Cafe/HW/Latte/Renderer/RendererCore.h | 86 ------ .../Vulkan/VulkanPipelineCompiler.cpp | 50 ---- src/main.cpp | 2 +- 6 files changed, 274 insertions(+), 338 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp index 96b7316b..2edcf4ea 100644 --- a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp +++ b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp @@ -695,7 +695,9 @@ void LatteRenderTarget_itHLESwapScanBuffer() performanceMonitor.gpuTime_frameTime.beginMeasuring(); LatteTC_CleanupUnusedTextures(); +#ifdef ENABLE_OPENGL LatteDraw_cleanupAfterFrame(); +#endif LatteQuery_CancelActiveGPU7Queries(); LatteBufferCache_notifySwapTVScanBuffer(); LattePerformanceMonitor_frameBegin(); diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp index 8e190743..2338201d 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp @@ -13,21 +13,73 @@ #include "Cafe/HW/Latte/Renderer/OpenGL/CachedFBOGL.h" #include "Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h" -#include "Cafe/HW/Latte/Renderer/RendererCore.h" - #include "Cafe/HW/Latte/ISA/RegDefines.h" #include "Cafe/OS/libs/gx2/GX2.h" #include "Cafe/GameProfile/GameProfile.h" +#include "HW/Latte/Renderer/RendererCore.h" #include "config/ActiveSettings.h" + +using _INDEX_TYPE = Latte::LATTE_VGT_DMA_INDEX_TYPE::E_INDEX_TYPE; + GLenum sGLActiveDrawMode = 0; extern bool hasValidFramebufferAttached; +#define INDEX_CACHE_ENTRIES (8) + +typedef struct +{ + MPTR prevIndexDataMPTR; + sint32 prevIndexType; + sint32 prevCount; + // index data + uint8* indexData; + uint8* indexData2; + uint32 indexBufferOffset; + sint32 indexDataSize; // current size + sint32 indexDataLimit; // maximum size + // info + uint32 maxIndex; + uint32 minIndex; +}indexDataCacheEntry_t; + +struct +{ + indexDataCacheEntry_t indexCacheEntry[INDEX_CACHE_ENTRIES]; + sint32 nextCacheEntryIndex; + // info about currently used index data + uint32 maxIndex; + uint32 minIndex; + uint8* indexData; + // buffer + GLuint glIndexCacheBuffer; + VirtualBufferHeap_t* indexBufferVirtualHeap; + uint8* mappedIndexBuffer; + LatteRingBuffer_t* indexRingBuffer; + uint8* tempIndexStorage; + // misc + bool initialized; + GLuint glActiveElementArrayBuffer; +}indexState = { 0 }; + +struct +{ + uint8* vboOutput; + uint32 vboStride; + uint8 dataFormat; + uint8 nfa; + bool isSigned; +}activeAttributePointer[LATTE_VS_ATTRIBUTE_LIMIT] = { 0 }; + void LatteDraw_resetAttributePointerCache() { - RendererCore_resetAttributePointerCache(); + for (sint32 i = 0; i < LATTE_VS_ATTRIBUTE_LIMIT; i++) + { + activeAttributePointer[i].vboOutput = (uint8*)-1; + activeAttributePointer[i].vboStride = (uint32)-1; + } } void _setAttributeBufferPointerRaw(uint32 attributeShaderLoc, uint8* buffer, uint32 bufferSize, uint32 stride, LatteParsedFetchShaderAttribute_t* attrib, uint8* vboOutput, uint32 vboStride) @@ -36,11 +88,15 @@ void _setAttributeBufferPointerRaw(uint32 attributeShaderLoc, uint8* buffer, uin bool isSigned = attrib->isSigned != 0; uint8 nfa = attrib->nfa; // don't call glVertexAttribIPointer if parameters have not changed - bool attributePointerChanged = RendererCore_checkIfAttributePointerCacheChanged(attributeShaderLoc, vboOutput, vboStride, dataFormat, nfa, isSigned); - if (!attributePointerChanged) { + if (activeAttributePointer[attributeShaderLoc].vboOutput == vboOutput && activeAttributePointer[attributeShaderLoc].vboStride == vboStride && activeAttributePointer[attributeShaderLoc].dataFormat == dataFormat && activeAttributePointer[attributeShaderLoc].nfa == nfa && activeAttributePointer[attributeShaderLoc].isSigned == isSigned) + { return; } - + activeAttributePointer[attributeShaderLoc].vboOutput = vboOutput; + activeAttributePointer[attributeShaderLoc].vboStride = vboStride; + activeAttributePointer[attributeShaderLoc].dataFormat = dataFormat; + activeAttributePointer[attributeShaderLoc].nfa = nfa; + activeAttributePointer[attributeShaderLoc].isSigned = isSigned; // setup attribute pointer if (dataFormat == FMT_32_32_32_32_FLOAT || dataFormat == FMT_32_32_32_32) { @@ -139,23 +195,111 @@ void OpenGLRenderer::SetAttributeArrayState(uint32 index, bool isEnabled, sint32 // Sets the currently active element array buffer and binds it void OpenGLRenderer::SetArrayElementBuffer(GLuint arrayElementBuffer) { - indexState_t* indexState = RendererCore_getIndexState(); - if (arrayElementBuffer == indexState->glActiveElementArrayBuffer) + if (arrayElementBuffer == indexState.glActiveElementArrayBuffer) return; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrayElementBuffer); - indexState->glActiveElementArrayBuffer = arrayElementBuffer; + indexState.glActiveElementArrayBuffer = arrayElementBuffer; +} + +typedef struct +{ + MPTR physAddr; + sint32 count; + uint32 primitiveRestartIndex; + uint32 primitiveMode; +}indexDataCacheKey_t; + +typedef struct _indexDataCacheEntry_t +{ + indexDataCacheKey_t key; + _indexDataCacheEntry_t* nextInBucket; // points to next element in same bucket + uint32 physSize; + uint32 hash; + _INDEX_TYPE indexType; + //sint32 indexType; + uint32 minIndex; + uint32 maxIndex; + uint32 lastAccessFrameCount; + VirtualBufferHeapEntry_t* heapEntry; + _indexDataCacheEntry_t* nextInMostRecentUsage; // points to element which was used more recently + _indexDataCacheEntry_t* prevInMostRecentUsage; // points to element which was used less recently +}indexDataCacheEntry2_t; + +#define INDEX_DATA_CACHE_BUCKETS (1783) + +indexDataCacheEntry2_t* indexDataCacheBucket[INDEX_DATA_CACHE_BUCKETS] = { 0 }; +indexDataCacheEntry2_t* indexDataCacheFirst = nullptr; // points to least recently used item +indexDataCacheEntry2_t* indexDataCacheLast = nullptr; // points to most recently used item +sint32 indexDataCacheEntryCount = 0; + +void _appendToUsageLinkedList(indexDataCacheEntry2_t* entry) +{ + if (indexDataCacheLast == nullptr) + { + indexDataCacheLast = entry; + indexDataCacheFirst = entry; + entry->nextInMostRecentUsage = nullptr; + entry->prevInMostRecentUsage = nullptr; + } + else + { + indexDataCacheLast->nextInMostRecentUsage = entry; + entry->prevInMostRecentUsage = indexDataCacheLast; + entry->nextInMostRecentUsage = nullptr; + indexDataCacheLast = entry; + } +} + +void _removeFromUsageLinkedList(indexDataCacheEntry2_t* entry) +{ + if (entry->prevInMostRecentUsage) + { + entry->prevInMostRecentUsage->nextInMostRecentUsage = entry->nextInMostRecentUsage; + } + else + indexDataCacheFirst = entry->nextInMostRecentUsage; + if (entry->nextInMostRecentUsage) + { + entry->nextInMostRecentUsage->prevInMostRecentUsage = entry->prevInMostRecentUsage; + } + else + indexDataCacheLast = entry->prevInMostRecentUsage; + entry->prevInMostRecentUsage = nullptr; + entry->nextInMostRecentUsage = nullptr; +} + +void _removeFromBucket(indexDataCacheEntry2_t* entry) +{ + uint32 indexDataBucketIdx = (uint32)((entry->key.physAddr + entry->key.count) ^ (entry->key.physAddr >> 16)) % INDEX_DATA_CACHE_BUCKETS; + if (indexDataCacheBucket[indexDataBucketIdx] == entry) + { + indexDataCacheBucket[indexDataBucketIdx] = entry->nextInBucket; + entry->nextInBucket = nullptr; + return; + } + indexDataCacheEntry2_t* cacheEntryItr = indexDataCacheBucket[indexDataBucketIdx]; + while (cacheEntryItr) + { + if (cacheEntryItr->nextInBucket == entry) + { + cacheEntryItr->nextInBucket = entry->nextInBucket; + entry->nextInBucket = nullptr; + return; + } + // next + cacheEntryItr = cacheEntryItr->nextInBucket; + } } void _decodeAndUploadIndexData(indexDataCacheEntry2_t* cacheEntry) { uint32 count = cacheEntry->key.count; uint32 primitiveRestartIndex = cacheEntry->key.primitiveRestartIndex; - indexState_t *indexState = RendererCore_getIndexState(); if (cacheEntry->indexType == _INDEX_TYPE::U16_BE) { // 16bit indices uint16* indexInputU16 = (uint16*)memory_getPointerFromPhysicalOffset(cacheEntry->key.physAddr); - uint16* indexOutputU16 = (uint16*)indexState->tempIndexStorage; + uint16* indexOutputU16 = (uint16*)indexState.tempIndexStorage; cemu_assert_debug(count != 0); uint16 indexMinU16 = 0xFFFF; uint16 indexMaxU16 = 0; @@ -191,14 +335,14 @@ void _decodeAndUploadIndexData(indexDataCacheEntry2_t* cacheEntry) } cacheEntry->minIndex = indexMinU16; cacheEntry->maxIndex = indexMaxU16; - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, cacheEntry->heapEntry->startOffset, count * sizeof(uint16), indexState->tempIndexStorage); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, cacheEntry->heapEntry->startOffset, count * sizeof(uint16), indexState.tempIndexStorage); performanceMonitor.cycle[performanceMonitor.cycleIndex].indexDataUploaded += (count * sizeof(uint16)); } else if(cacheEntry->indexType == _INDEX_TYPE::U32_BE) { // 32bit indices uint32* indexInputU32 = (uint32*)memory_getPointerFromPhysicalOffset(cacheEntry->key.physAddr); - uint32* indexOutputU32 = (uint32*)indexState->tempIndexStorage; + uint32* indexOutputU32 = (uint32*)indexState.tempIndexStorage; cemu_assert_debug(count != 0); uint32 indexMinU32 = _swapEndianU32(*indexInputU32); uint32 indexMaxU32 = _swapEndianU32(*indexInputU32); @@ -216,7 +360,7 @@ void _decodeAndUploadIndexData(indexDataCacheEntry2_t* cacheEntry) } cacheEntry->minIndex = indexMinU32; cacheEntry->maxIndex = indexMaxU32; - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, cacheEntry->heapEntry->startOffset, count * sizeof(uint32), indexState->tempIndexStorage); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, cacheEntry->heapEntry->startOffset, count * sizeof(uint32), indexState.tempIndexStorage); performanceMonitor.cycle[performanceMonitor.cycleIndex].indexDataUploaded += (count * sizeof(uint32)); } else @@ -225,18 +369,35 @@ void _decodeAndUploadIndexData(indexDataCacheEntry2_t* cacheEntry) } } + +void LatteDraw_cleanupAfterFrame() +{ + if (g_renderer->GetType() != RendererAPI::OpenGL) + return; + // drop everything from cache that is older than 30 frames + uint32 frameCounter = LatteGPUState.frameCounter; + while (indexDataCacheFirst) + { + indexDataCacheEntry2_t* entry = indexDataCacheFirst; + if ((frameCounter - entry->lastAccessFrameCount) < 30) + break; + // remove entry + virtualBufferHeap_free(indexState.indexBufferVirtualHeap, entry->heapEntry); + _removeFromUsageLinkedList(entry); + _removeFromBucket(entry); + free(entry); + } +} + void LatteDrawGL_removeLeastRecentlyUsedIndexCacheEntries(sint32 count) { - indexState_t *indexState = RendererCore_getIndexState(); - indexDataCacheEntry2_t** indexDataCacheFirst = RendererCore_getIndexDataCacheFirst(); - - while (*indexDataCacheFirst && count > 0) + while (indexDataCacheFirst && count > 0) { - indexDataCacheEntry2_t* entry = *indexDataCacheFirst; + indexDataCacheEntry2_t* entry = indexDataCacheFirst; // remove entry - virtualBufferHeap_free(indexState->indexBufferVirtualHeap, entry->heapEntry); - RendererCore_removeFromUsageLinkedList(entry); - RendererCore_removeFromBucket(entry); + virtualBufferHeap_free(indexState.indexBufferVirtualHeap, entry->heapEntry); + _removeFromUsageLinkedList(entry); + _removeFromBucket(entry); free(entry); count--; } @@ -274,22 +435,19 @@ uint32 LatteDrawGL_calculateIndexDataHash(uint8* data, uint32 size) // todo - Outdated cache implementation. Update OpenGL renderer to use the generic implementation that is also used by the Vulkan renderer void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE indexType, sint32 count, sint32 primitiveMode) { - indexState_t* indexState = RendererCore_getIndexState(); - indexDataCacheEntry2_t** indexDataCacheFirst = RendererCore_getIndexDataCacheFirst(); - if (indexType == _INDEX_TYPE::AUTO) { - indexState->minIndex = 0; - indexState->maxIndex = count - 1; + indexState.minIndex = 0; + indexState.maxIndex = count - 1; // since no indices are used we don't need to unbind the element array buffer return; // automatic indices } - OpenGLRenderer::SetArrayElementBuffer(indexState->glIndexCacheBuffer); + OpenGLRenderer::SetArrayElementBuffer(indexState.glIndexCacheBuffer); uint32 indexDataBucketIdx = (uint32)((indexDataMPTR + count) ^ (indexDataMPTR >> 16)) % INDEX_DATA_CACHE_BUCKETS; // find matching entry uint32 primitiveRestartIndex = LatteGPUState.contextNew.VGT_MULTI_PRIM_IB_RESET_INDX.get_RESTART_INDEX(); - indexDataCacheEntry2_t* cacheEntryItr = *RendererCore_getIndexDataCacheBucket(indexDataBucketIdx); + indexDataCacheEntry2_t* cacheEntryItr = indexDataCacheBucket[indexDataBucketIdx]; indexDataCacheKey_t compareKey; compareKey.physAddr = indexDataMPTR; compareKey.count = count; @@ -304,9 +462,9 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde continue; } // entry found - indexState->minIndex = cacheEntryItr->minIndex; - indexState->maxIndex = cacheEntryItr->maxIndex; - indexState->indexData = (uint8*)(size_t)cacheEntryItr->heapEntry->startOffset; + indexState.minIndex = cacheEntryItr->minIndex; + indexState.maxIndex = cacheEntryItr->maxIndex; + indexState.indexData = (uint8*)(size_t)cacheEntryItr->heapEntry->startOffset; cacheEntryItr->lastAccessFrameCount = LatteGPUState.frameCounter; // check if the data changed uint32 h = LatteDrawGL_calculateIndexDataHash(memory_getPointerFromPhysicalOffset(indexDataMPTR), cacheEntryItr->physSize); @@ -317,8 +475,8 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde cacheEntryItr->hash = h; } // move entry to the front - RendererCore_removeFromUsageLinkedList(cacheEntryItr); - RendererCore_appendToUsageLinkedList(cacheEntryItr); + _removeFromUsageLinkedList(cacheEntryItr); + _appendToUsageLinkedList(cacheEntryItr); return; } // calculate size of index data in cache @@ -328,16 +486,16 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde else cacheIndexDataSize = count * sizeof(uint32); // no matching entry, create new one - VirtualBufferHeapEntry_t* heapEntry = virtualBufferHeap_allocate(indexState->indexBufferVirtualHeap, cacheIndexDataSize); + VirtualBufferHeapEntry_t* heapEntry = virtualBufferHeap_allocate(indexState.indexBufferVirtualHeap, cacheIndexDataSize); if (heapEntry == nullptr) { while (true) { LatteDrawGL_removeLeastRecentlyUsedIndexCacheEntries(10); - heapEntry = virtualBufferHeap_allocate(indexState->indexBufferVirtualHeap, cacheIndexDataSize); + heapEntry = virtualBufferHeap_allocate(indexState.indexBufferVirtualHeap, cacheIndexDataSize); if (heapEntry != nullptr) break; - if (*indexDataCacheFirst == nullptr) + if (indexDataCacheFirst == nullptr) { cemuLog_log(LogType::Force, "Unable to allocate entry in index cache"); assert_dbg(); @@ -356,37 +514,34 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde cacheEntry->heapEntry = heapEntry; cacheEntry->lastAccessFrameCount = LatteGPUState.frameCounter; // append entry in bucket list - indexDataCacheEntry2_t** bucket = RendererCore_getIndexDataCacheBucket(indexDataBucketIdx); - cacheEntry->nextInBucket = *bucket; - *bucket = cacheEntry; + cacheEntry->nextInBucket = indexDataCacheBucket[indexDataBucketIdx]; + indexDataCacheBucket[indexDataBucketIdx] = cacheEntry; // append as most recently used entry - RendererCore_appendToUsageLinkedList(cacheEntry); + _appendToUsageLinkedList(cacheEntry); // decode and upload the data _decodeAndUploadIndexData(cacheEntry); - sint32* indexDataCacheEntryCount = RendererCore_getIndexDataCacheEntryCount(); - (*indexDataCacheEntryCount)++; - indexState->minIndex = cacheEntry->minIndex; - indexState->maxIndex = cacheEntry->maxIndex; - indexState->indexData = (uint8*)(size_t)cacheEntry->heapEntry->startOffset; + indexDataCacheEntryCount++; + indexState.minIndex = cacheEntry->minIndex; + indexState.maxIndex = cacheEntry->maxIndex; + indexState.indexData = (uint8*)(size_t)cacheEntry->heapEntry->startOffset; } void LatteDrawGL_doDraw(_INDEX_TYPE indexType, uint32 baseVertex, uint32 baseInstance, uint32 instanceCount, uint32 count) { - indexState_t* indexState = RendererCore_getIndexState(); if (indexType == _INDEX_TYPE::U16_BE) { // 16bit index, big endian if (instanceCount > 1 || baseInstance != 0) { - glDrawElementsInstancedBaseVertexBaseInstance(sGLActiveDrawMode, count, GL_UNSIGNED_SHORT, indexState->indexData, instanceCount, baseVertex, baseInstance); + glDrawElementsInstancedBaseVertexBaseInstance(sGLActiveDrawMode, count, GL_UNSIGNED_SHORT, indexState.indexData, instanceCount, baseVertex, baseInstance); } else { if (baseVertex != 0) - glDrawRangeElementsBaseVertex(sGLActiveDrawMode, indexState->minIndex, indexState->maxIndex, count, GL_UNSIGNED_SHORT, indexState->indexData, baseVertex); + glDrawRangeElementsBaseVertex(sGLActiveDrawMode, indexState.minIndex, indexState.maxIndex, count, GL_UNSIGNED_SHORT, indexState.indexData, baseVertex); else - glDrawRangeElements(sGLActiveDrawMode, indexState->minIndex, indexState->maxIndex, count, GL_UNSIGNED_SHORT, indexState->indexData); + glDrawRangeElements(sGLActiveDrawMode, indexState.minIndex, indexState.maxIndex, count, GL_UNSIGNED_SHORT, indexState.indexData); } } else if (indexType == _INDEX_TYPE::U32_BE) @@ -395,11 +550,11 @@ void LatteDrawGL_doDraw(_INDEX_TYPE indexType, uint32 baseVertex, uint32 baseIns if (instanceCount > 1 || baseInstance != 0) { //debug_printf("Render instanced\n"); - glDrawElementsInstancedBaseVertexBaseInstance(sGLActiveDrawMode, count, GL_UNSIGNED_INT, indexState->indexData, instanceCount, baseVertex, baseInstance); + glDrawElementsInstancedBaseVertexBaseInstance(sGLActiveDrawMode, count, GL_UNSIGNED_INT, indexState.indexData, instanceCount, baseVertex, baseInstance); } else { - glDrawRangeElementsBaseVertex(sGLActiveDrawMode, indexState->minIndex, indexState->maxIndex, count, GL_UNSIGNED_INT, indexState->indexData, baseVertex); + glDrawRangeElementsBaseVertex(sGLActiveDrawMode, indexState.minIndex, indexState.maxIndex, count, GL_UNSIGNED_INT, indexState.indexData, baseVertex); } } else if (indexType == _INDEX_TYPE::AUTO) @@ -824,8 +979,7 @@ void OpenGLRenderer::draw_genericDrawHandler(uint32 baseVertex, uint32 baseInsta endPerfMonProfiling(performanceMonitor.gpuTime_dcStageIndexMgr); // synchronize vertex and uniform buffers - indexState_t *indexState = RendererCore_getIndexState(); - LatteBufferCache_Sync(indexState->minIndex + baseVertex, indexState->maxIndex + baseVertex, baseInstance, instanceCount); + LatteBufferCache_Sync(indexState.minIndex + baseVertex, indexState.maxIndex + baseVertex, baseInstance, instanceCount); _setupVertexAttributes(); @@ -1016,24 +1170,23 @@ void OpenGLRenderer::draw_endSequence() void OpenGLRenderer::draw_init() { - indexState_t* indexState = RendererCore_getIndexState(); - if (indexState->initialized) + if (indexState.initialized) return; - indexState->initialized = true; + indexState.initialized = true; // create index buffer - glGenBuffers(1, &indexState->glIndexCacheBuffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexState->glIndexCacheBuffer); + glGenBuffers(1, &indexState.glIndexCacheBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexState.glIndexCacheBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR, NULL, GL_DYNAMIC_DRAW); #if BOOST_OS_WINDOWS - indexState->mappedIndexBuffer = (uint8*)_aligned_malloc(GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR, 256); + indexState.mappedIndexBuffer = (uint8*)_aligned_malloc(GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR, 256); #else - indexState->mappedIndexBuffer = (uint8*)aligned_alloc(256, GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR); + indexState.mappedIndexBuffer = (uint8*)aligned_alloc(256, GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR); #endif glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - indexState->indexRingBuffer = LatteRingBuffer_create(indexState->mappedIndexBuffer, GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR); - indexState->tempIndexStorage = (uint8*)malloc(1024 * 1024 * 8); + indexState.indexRingBuffer = LatteRingBuffer_create(indexState.mappedIndexBuffer, GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR); + indexState.tempIndexStorage = (uint8*)malloc(1024 * 1024 * 8); // create virtual heap for index buffer - indexState->indexBufferVirtualHeap = virtualBufferHeap_create(GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR); + indexState.indexBufferVirtualHeap = virtualBufferHeap_create(GPU7_INDEX_BUFFER_CACHE_SIZE_DEPR); } void OpenGLRenderer::bufferCache_upload(uint8* buffer, sint32 size, uint32 bufferOffset) diff --git a/src/Cafe/HW/Latte/Renderer/RendererCore.cpp b/src/Cafe/HW/Latte/Renderer/RendererCore.cpp index 4a6a82d5..96d7b7c2 100644 --- a/src/Cafe/HW/Latte/Renderer/RendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/RendererCore.cpp @@ -1,6 +1,7 @@ #include "RendererCore.h" #include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Cafe/HW/Latte/ISA/RegDefines.h" +#include "HW/Latte/Core/LatteShader.h" #include "config/CemuConfig.h" #ifdef ENABLE_OPENGL @@ -8,142 +9,6 @@ #include "Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.h" #endif -indexState_t indexState = { 0 }; -AttributePointerCacheEntry_t activeAttributePointer[LATTE_VS_ATTRIBUTE_LIMIT] = { 0 }; - -indexDataCacheEntry2_t* indexDataCacheBucket[INDEX_DATA_CACHE_BUCKETS] = { 0 }; -indexDataCacheEntry2_t* indexDataCacheFirst = nullptr; // points to least recently used item -indexDataCacheEntry2_t* indexDataCacheLast = nullptr; // points to most recently used item -sint32 indexDataCacheEntryCount = 0; - -void RendererCore_resetAttributePointerCache() -{ - for (sint32 i = 0; i < LATTE_VS_ATTRIBUTE_LIMIT; i++) - { - activeAttributePointer[i].vboOutput = (uint8*)-1; - activeAttributePointer[i].vboStride = (uint32)-1; - } -} - -bool RendererCore_checkIfAttributePointerCacheChanged(uint32 attributeShaderLoc, uint8* vboOutput, uint32 vboStride, uint8 dataFormat, uint8 nfa, bool isSigned) -{ - // don't call glVertexAttribPointer if parameters have not changed - if ( - activeAttributePointer[attributeShaderLoc].vboOutput == vboOutput && - activeAttributePointer[attributeShaderLoc].vboStride == vboStride && - activeAttributePointer[attributeShaderLoc].dataFormat == dataFormat && - activeAttributePointer[attributeShaderLoc].nfa == nfa && - activeAttributePointer[attributeShaderLoc].isSigned == isSigned - ) - { - return false; - } - activeAttributePointer[attributeShaderLoc].vboOutput = vboOutput; - activeAttributePointer[attributeShaderLoc].vboStride = vboStride; - activeAttributePointer[attributeShaderLoc].dataFormat = dataFormat; - activeAttributePointer[attributeShaderLoc].nfa = nfa; - activeAttributePointer[attributeShaderLoc].isSigned = isSigned; - - return true; -} - -indexState_t* RendererCore_getIndexState() -{ - return &indexState; -} - -indexDataCacheEntry2_t** RendererCore_getIndexDataCacheFirst() -{ - return &indexDataCacheFirst; -} - -indexDataCacheEntry2_t** RendererCore_getIndexDataCacheBucket(uint32 bucketIdx) -{ - return &indexDataCacheBucket[bucketIdx]; -} - -sint32* RendererCore_getIndexDataCacheEntryCount() -{ - return &indexDataCacheEntryCount; -} - -void RendererCore_appendToUsageLinkedList(indexDataCacheEntry2_t* entry) -{ - if (indexDataCacheLast == nullptr) - { - indexDataCacheLast = entry; - indexDataCacheFirst = entry; - entry->nextInMostRecentUsage = nullptr; - entry->prevInMostRecentUsage = nullptr; - } - else - { - indexDataCacheLast->nextInMostRecentUsage = entry; - entry->prevInMostRecentUsage = indexDataCacheLast; - entry->nextInMostRecentUsage = nullptr; - indexDataCacheLast = entry; - } -} - -void RendererCore_removeFromUsageLinkedList(indexDataCacheEntry2_t* entry) -{ - if (entry->prevInMostRecentUsage) - { - entry->prevInMostRecentUsage->nextInMostRecentUsage = entry->nextInMostRecentUsage; - } - else - indexDataCacheFirst = entry->nextInMostRecentUsage; - if (entry->nextInMostRecentUsage) - { - entry->nextInMostRecentUsage->prevInMostRecentUsage = entry->prevInMostRecentUsage; - } - else - indexDataCacheLast = entry->prevInMostRecentUsage; - entry->prevInMostRecentUsage = nullptr; - entry->nextInMostRecentUsage = nullptr; -} - -void RendererCore_removeFromBucket(indexDataCacheEntry2_t* entry) -{ - uint32 indexDataBucketIdx = (uint32)((entry->key.physAddr + entry->key.count) ^ (entry->key.physAddr >> 16)) % INDEX_DATA_CACHE_BUCKETS; - if (indexDataCacheBucket[indexDataBucketIdx] == entry) - { - indexDataCacheBucket[indexDataBucketIdx] = entry->nextInBucket; - entry->nextInBucket = nullptr; - return; - } - indexDataCacheEntry2_t* cacheEntryItr = indexDataCacheBucket[indexDataBucketIdx]; - while (cacheEntryItr) - { - if (cacheEntryItr->nextInBucket == entry) - { - cacheEntryItr->nextInBucket = entry->nextInBucket; - entry->nextInBucket = nullptr; - return; - } - // next - cacheEntryItr = cacheEntryItr->nextInBucket; - } -} - -void LatteDraw_cleanupAfterFrame() -{ - // drop everything from cache that is older than 30 frames - uint32 frameCounter = LatteGPUState.frameCounter; - while (indexDataCacheFirst) - { - indexDataCacheEntry2_t* entry = indexDataCacheFirst; - if ((frameCounter - entry->lastAccessFrameCount) < 30) - break; - // remove entry - virtualBufferHeap_free(indexState.indexBufferVirtualHeap, entry->heapEntry); - RendererCore_removeFromUsageLinkedList(entry); - RendererCore_removeFromBucket(entry); - free(entry); - } -} - - void LatteDraw_handleSpecialState8_clearAsDepth() { if (LatteGPUState.contextNew.GetSpecialStateValues()[0] == 0) @@ -212,4 +77,56 @@ void LatteDraw_handleSpecialState8_clearAsDepth() } } } -} \ No newline at end of file +} + +/* rects emulation */ + +void rectsEmulationGS_outputSingleVertex(std::string& gsSrc, LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, sint32 vIdx, const LatteContextRegister& latteRegister) +{ + auto parameterMask = vertexShader->outputParameterMask; + for (uint32 i = 0; i < 32; i++) + { + if ((parameterMask & (1 << i)) == 0) + continue; + sint32 vsSemanticId = psInputTable->getVertexShaderOutParamSemanticId(latteRegister.GetRawView(), i); + if (vsSemanticId < 0) + continue; + // make sure PS has matching input + if (!psInputTable->hasPSImportForSemanticId(vsSemanticId)) + continue; + gsSrc.append(fmt::format("passParameterSem{}Out = passParameterSem{}In[{}];\r\n", vsSemanticId, vsSemanticId, vIdx)); + } + gsSrc.append(fmt::format("gl_Position = gl_in[{}].gl_Position;\r\n", vIdx)); + gsSrc.append("EmitVertex();\r\n"); +} + +void rectsEmulationGS_outputGeneratedVertex(std::string& gsSrc, LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, const char* variant, const LatteContextRegister& latteRegister) +{ + auto parameterMask = vertexShader->outputParameterMask; + for (uint32 i = 0; i < 32; i++) + { + if ((parameterMask & (1 << i)) == 0) + continue; + sint32 vsSemanticId = psInputTable->getVertexShaderOutParamSemanticId(latteRegister.GetRawView(), i); + if (vsSemanticId < 0) + continue; + // make sure PS has matching input + if (!psInputTable->hasPSImportForSemanticId(vsSemanticId)) + continue; + gsSrc.append(fmt::format("passParameterSem{}Out = gen4thVertex{}(passParameterSem{}In[0], passParameterSem{}In[1], passParameterSem{}In[2]);\r\n", vsSemanticId, variant, vsSemanticId, vsSemanticId, vsSemanticId)); + } + gsSrc.append(fmt::format("gl_Position = gen4thVertex{}(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_in[2].gl_Position);\r\n", variant)); + gsSrc.append("EmitVertex();\r\n"); +} + +void rectsEmulationGS_outputVerticesCode(std::string& gsSrc, LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, sint32 p0, sint32 p1, sint32 p2, sint32 p3, const char* variant, const LatteContextRegister& latteRegister) +{ + sint32 pList[4] = { p0, p1, p2, p3 }; + for (sint32 i = 0; i < 4; i++) + { + if (pList[i] == 3) + rectsEmulationGS_outputGeneratedVertex(gsSrc, vertexShader, psInputTable, variant, latteRegister); + else + rectsEmulationGS_outputSingleVertex(gsSrc, vertexShader, psInputTable, pList[i], latteRegister); + } +} diff --git a/src/Cafe/HW/Latte/Renderer/RendererCore.h b/src/Cafe/HW/Latte/Renderer/RendererCore.h index 1c681373..c88b20b5 100644 --- a/src/Cafe/HW/Latte/Renderer/RendererCore.h +++ b/src/Cafe/HW/Latte/Renderer/RendererCore.h @@ -3,90 +3,4 @@ #include "Cafe/HW/Latte/Core/LatteRingBuffer.h" #include "Cafe/HW/Latte/Core/Latte.h" -using _INDEX_TYPE = Latte::LATTE_VGT_DMA_INDEX_TYPE::E_INDEX_TYPE; - -#define INDEX_CACHE_ENTRIES (8) - -typedef struct -{ - MPTR prevIndexDataMPTR; - sint32 prevIndexType; - sint32 prevCount; - // index data - uint8* indexData; - uint8* indexData2; - uint32 indexBufferOffset; - sint32 indexDataSize; // current size - sint32 indexDataLimit; // maximum size - // info - uint32 maxIndex; - uint32 minIndex; -}indexDataCacheEntry_t; - -typedef struct -{ - indexDataCacheEntry_t indexCacheEntry[INDEX_CACHE_ENTRIES]; - sint32 nextCacheEntryIndex; - // info about currently used index data - uint32 maxIndex; - uint32 minIndex; - uint8* indexData; - // buffer - unsigned int glIndexCacheBuffer; - VirtualBufferHeap_t* indexBufferVirtualHeap; - uint8* mappedIndexBuffer; - LatteRingBuffer_t* indexRingBuffer; - uint8* tempIndexStorage; - // misc - bool initialized; - unsigned int glActiveElementArrayBuffer; -}indexState_t; - -typedef struct -{ - uint8* vboOutput; - uint32 vboStride; - uint8 dataFormat; - uint8 nfa; - bool isSigned; -} AttributePointerCacheEntry_t; - -#define INDEX_DATA_CACHE_BUCKETS (1783) - -typedef struct -{ - MPTR physAddr; - sint32 count; - uint32 primitiveRestartIndex; - uint32 primitiveMode; -}indexDataCacheKey_t; - -typedef struct _indexDataCacheEntry_t -{ - indexDataCacheKey_t key; - _indexDataCacheEntry_t* nextInBucket; // points to next element in same bucket - uint32 physSize; - uint32 hash; - _INDEX_TYPE indexType; - //sint32 indexType; - uint32 minIndex; - uint32 maxIndex; - uint32 lastAccessFrameCount; - VirtualBufferHeapEntry_t* heapEntry; - _indexDataCacheEntry_t* nextInMostRecentUsage; // points to element which was used more recently - _indexDataCacheEntry_t* prevInMostRecentUsage; // points to element which was used less recently -}indexDataCacheEntry2_t; - -void RendererCore_resetAttributePointerCache(); -bool RendererCore_checkIfAttributePointerCacheChanged(uint32 attributeShaderLoc, uint8* vboOutput, uint32 vboStride, uint8 dataFormat, uint8 nfa, bool isSigned); - -indexState_t* RendererCore_getIndexState(); -indexDataCacheEntry2_t** RendererCore_getIndexDataCacheFirst(); -indexDataCacheEntry2_t** RendererCore_getIndexDataCacheBucket(uint32 bucketIdx); -sint32* RendererCore_getIndexDataCacheEntryCount(); - -void RendererCore_appendToUsageLinkedList(indexDataCacheEntry2_t* entry); -void RendererCore_removeFromUsageLinkedList(indexDataCacheEntry2_t* entry); -void RendererCore_removeFromBucket(indexDataCacheEntry2_t* entry); -void LatteDraw_cleanupAfterFrame(); void LatteDraw_handleSpecialState8_clearAsDepth(); \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp index 55b2330e..6ac2150f 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp @@ -10,57 +10,7 @@ #include "util/helpers/Serializer.h" #include "Cafe/HW/Latte/Common/RegisterSerializer.h" -/* rects emulation */ -void rectsEmulationGS_outputSingleVertex(std::string& gsSrc, LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, sint32 vIdx, const LatteContextRegister& latteRegister) -{ - auto parameterMask = vertexShader->outputParameterMask; - for (uint32 i = 0; i < 32; i++) - { - if ((parameterMask & (1 << i)) == 0) - continue; - sint32 vsSemanticId = psInputTable->getVertexShaderOutParamSemanticId(latteRegister.GetRawView(), i); - if (vsSemanticId < 0) - continue; - // make sure PS has matching input - if (!psInputTable->hasPSImportForSemanticId(vsSemanticId)) - continue; - gsSrc.append(fmt::format("passParameterSem{}Out = passParameterSem{}In[{}];\r\n", vsSemanticId, vsSemanticId, vIdx)); - } - gsSrc.append(fmt::format("gl_Position = gl_in[{}].gl_Position;\r\n", vIdx)); - gsSrc.append("EmitVertex();\r\n"); -} - -void rectsEmulationGS_outputGeneratedVertex(std::string& gsSrc, LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, const char* variant, const LatteContextRegister& latteRegister) -{ - auto parameterMask = vertexShader->outputParameterMask; - for (uint32 i = 0; i < 32; i++) - { - if ((parameterMask & (1 << i)) == 0) - continue; - sint32 vsSemanticId = psInputTable->getVertexShaderOutParamSemanticId(latteRegister.GetRawView(), i); - if (vsSemanticId < 0) - continue; - // make sure PS has matching input - if (!psInputTable->hasPSImportForSemanticId(vsSemanticId)) - continue; - gsSrc.append(fmt::format("passParameterSem{}Out = gen4thVertex{}(passParameterSem{}In[0], passParameterSem{}In[1], passParameterSem{}In[2]);\r\n", vsSemanticId, variant, vsSemanticId, vsSemanticId, vsSemanticId)); - } - gsSrc.append(fmt::format("gl_Position = gen4thVertex{}(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_in[2].gl_Position);\r\n", variant)); - gsSrc.append("EmitVertex();\r\n"); -} - -void rectsEmulationGS_outputVerticesCode(std::string& gsSrc, LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, sint32 p0, sint32 p1, sint32 p2, sint32 p3, const char* variant, const LatteContextRegister& latteRegister) -{ - sint32 pList[4] = { p0, p1, p2, p3 }; - for (sint32 i = 0; i < 4; i++) - { - if (pList[i] == 3) - rectsEmulationGS_outputGeneratedVertex(gsSrc, vertexShader, psInputTable, variant, latteRegister); - else - rectsEmulationGS_outputSingleVertex(gsSrc, vertexShader, psInputTable, pList[i], latteRegister); - } -} RendererShaderVk* rectsEmulationGS_generate(LatteDecompilerShader* vertexShader, const LatteContextRegister& latteRegister) { diff --git a/src/main.cpp b/src/main.cpp index a4e44115..fc632921 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -265,7 +265,7 @@ int main(int argc, char* argv[]) int BreathOfTheWildChildProcessMain(); int main(int argc, char *argv[]) { -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX && defined(ENABLE_VULKAN) if (getenv("CEMU_DETECT_RADV") != nullptr) return BreathOfTheWildChildProcessMain(); #endif From b5dccb20e6ed2eba4223a9fef88d5a6220483973 Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:58:41 +0200 Subject: [PATCH 30/32] fix linux builds with vulkan enabled --- src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp | 4 ---- src/Cafe/HW/Latte/Renderer/RendererCore.h | 7 ++++++- .../HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp | 3 +-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp index 2338201d..c9437353 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp @@ -694,10 +694,6 @@ void OpenGLRenderer::_setupVertexAttributes() } } -void rectsEmulationGS_outputSingleVertex(std::string& gsSrc, LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, sint32 vIdx); -void rectsEmulationGS_outputGeneratedVertex(std::string& gsSrc, LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, const char* variant); -void rectsEmulationGS_outputVerticesCode(std::string& gsSrc, LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, sint32 p0, sint32 p1, sint32 p2, sint32 p3, const char* variant, const LatteContextRegister& latteRegister); - std::map g_mapGLRectEmulationGS; RendererShaderGL* rectsEmulationGS_generateShaderGL(LatteDecompilerShader* vertexShader) diff --git a/src/Cafe/HW/Latte/Renderer/RendererCore.h b/src/Cafe/HW/Latte/Renderer/RendererCore.h index c88b20b5..aaffec56 100644 --- a/src/Cafe/HW/Latte/Renderer/RendererCore.h +++ b/src/Cafe/HW/Latte/Renderer/RendererCore.h @@ -3,4 +3,9 @@ #include "Cafe/HW/Latte/Core/LatteRingBuffer.h" #include "Cafe/HW/Latte/Core/Latte.h" -void LatteDraw_handleSpecialState8_clearAsDepth(); \ No newline at end of file +void LatteDraw_handleSpecialState8_clearAsDepth(); + +class LatteShaderPSInputTable; +void rectsEmulationGS_outputSingleVertex(std::string& gsSrc, LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, sint32 vIdx); +void rectsEmulationGS_outputGeneratedVertex(std::string& gsSrc, LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, const char* variant); +void rectsEmulationGS_outputVerticesCode(std::string& gsSrc, LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, sint32 p0, sint32 p1, sint32 p2, sint32 p3, const char* variant, const LatteContextRegister& latteRegister); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp index 6ac2150f..ca166e69 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp @@ -9,8 +9,7 @@ #include "util/helpers/helpers.h" #include "util/helpers/Serializer.h" #include "Cafe/HW/Latte/Common/RegisterSerializer.h" - - +#include "HW/Latte/Renderer/RendererCore.h" RendererShaderVk* rectsEmulationGS_generate(LatteDecompilerShader* vertexShader, const LatteContextRegister& latteRegister) { From 68951b43b9ea743d746aaf6659b3ac2290ab5979 Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 13:28:26 +0100 Subject: [PATCH 31/32] move LatteShaderGL to Renderer/OpenGL and move LatteDefaultShaders to Renderer/OpenGL/LatteSurfaceCopy --- src/Cafe/CMakeLists.txt | 4 +- .../HW/Latte/Core/LatteDefaultShaders.cpp | 87 ------------------ src/Cafe/HW/Latte/Core/LatteDefaultShaders.h | 13 --- src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp | 1 - .../OpenGL}/LatteShaderGL.cpp | 0 .../Renderer/OpenGL/OpenGLSurfaceCopy.cpp | 89 ++++++++++++++++++- .../Latte/Renderer/OpenGL/OpenGLSurfaceCopy.h | 14 +++ 7 files changed, 101 insertions(+), 107 deletions(-) delete mode 100644 src/Cafe/HW/Latte/Core/LatteDefaultShaders.cpp delete mode 100644 src/Cafe/HW/Latte/Core/LatteDefaultShaders.h rename src/Cafe/HW/Latte/{Core => Renderer/OpenGL}/LatteShaderGL.cpp (100%) create mode 100644 src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.h diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index 5de8a085..0df1e847 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -494,10 +494,8 @@ add_library(CemuCafe if (ENABLE_OPENGL) target_sources(CemuCafe PRIVATE - HW/Latte/Core/LatteDefaultShaders.cpp - HW/Latte/Core/LatteDefaultShaders.h - HW/Latte/Core/LatteShaderGL.cpp HW/Latte/Renderer/OpenGL/CachedFBOGL.h + HW/Latte/Renderer/OpenGL/LatteShaderGL.cpp HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp HW/Latte/Renderer/OpenGL/LatteTextureGL.h HW/Latte/Renderer/OpenGL/LatteTextureViewGL.cpp diff --git a/src/Cafe/HW/Latte/Core/LatteDefaultShaders.cpp b/src/Cafe/HW/Latte/Core/LatteDefaultShaders.cpp deleted file mode 100644 index 7c590dbb..00000000 --- a/src/Cafe/HW/Latte/Core/LatteDefaultShaders.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "Cafe/HW/Latte/Core/Latte.h" -#include "Cafe/HW/Latte/Core/LatteDraw.h" -#include "Cafe/HW/Latte/Core/LatteShader.h" -#include "Cafe/HW/Latte/Core/LatteDefaultShaders.h" -#include "util/helpers/StringBuf.h" - -LatteDefaultShader_t* _copyShader_depthToColor; -LatteDefaultShader_t* _copyShader_colorToDepth; - -void LatteDefaultShader_pixelCopyShader_generateVSBody(StringBuf* vs) -{ - vs->add("#version 420\r\n"); - vs->add("out vec2 passUV;\r\n"); - vs->add("uniform vec4 uf_vertexOffsets[4];\r\n"); - vs->add("\r\n"); - vs->add("void main(){\r\n"); - vs->add("int vID = gl_VertexID;\r\n"); - vs->add("passUV = uf_vertexOffsets[vID].zw;\r\n"); - vs->add("gl_Position = vec4(uf_vertexOffsets[vID].xy, 0.0, 1.0);\r\n"); - vs->add("}\r\n"); -} - -GLuint gxShaderDepr_compileRaw(StringBuf* strSourceVS, StringBuf* strSourceFS); -GLuint gxShaderDepr_compileRaw(const std::string& vertex_source, const std::string& fragment_source); - -LatteDefaultShader_t* LatteDefaultShader_getPixelCopyShader_depthToColor() -{ - if (_copyShader_depthToColor != 0) - return _copyShader_depthToColor; - catchOpenGLError(); - LatteDefaultShader_t* defaultShader = (LatteDefaultShader_t*)malloc(sizeof(LatteDefaultShader_t)); - memset(defaultShader, 0, sizeof(LatteDefaultShader_t)); - - StringBuf fCStr_vertexShader(1024 * 16); - LatteDefaultShader_pixelCopyShader_generateVSBody(&fCStr_vertexShader); - - StringBuf fCStr_defaultFragShader(1024 * 16); - fCStr_defaultFragShader.add("#version 420\r\n"); - fCStr_defaultFragShader.add("in vec2 passUV;\r\n"); - fCStr_defaultFragShader.add("uniform sampler2D textureSrc;\r\n"); - fCStr_defaultFragShader.add("layout(location = 0) out vec4 colorOut0;\r\n"); - fCStr_defaultFragShader.add("\r\n"); - fCStr_defaultFragShader.add("void main(){\r\n"); - fCStr_defaultFragShader.add("colorOut0 = vec4(texture(textureSrc, passUV).r,0.0,0.0,1.0);\r\n"); - fCStr_defaultFragShader.add("}\r\n"); - - defaultShader->glProgamId = gxShaderDepr_compileRaw(&fCStr_vertexShader, &fCStr_defaultFragShader); - catchOpenGLError(); - - defaultShader->copyShaderUniforms.uniformLoc_textureSrc = glGetUniformLocation(defaultShader->glProgamId, "textureSrc"); - defaultShader->copyShaderUniforms.uniformLoc_vertexOffsets = glGetUniformLocation(defaultShader->glProgamId, "uf_vertexOffsets"); - - _copyShader_depthToColor = defaultShader; - catchOpenGLError(); - return defaultShader; -} - -LatteDefaultShader_t* LatteDefaultShader_getPixelCopyShader_colorToDepth() -{ - if (_copyShader_colorToDepth != 0) - return _copyShader_colorToDepth; - catchOpenGLError(); - LatteDefaultShader_t* defaultShader = (LatteDefaultShader_t*)malloc(sizeof(LatteDefaultShader_t)); - memset(defaultShader, 0, sizeof(LatteDefaultShader_t)); - - StringBuf fCStr_vertexShader(1024 * 16); - LatteDefaultShader_pixelCopyShader_generateVSBody(&fCStr_vertexShader); - - StringBuf fCStr_defaultFragShader(1024 * 16); - fCStr_defaultFragShader.add("#version 420\r\n"); - fCStr_defaultFragShader.add("in vec2 passUV;\r\n"); - fCStr_defaultFragShader.add("uniform sampler2D textureSrc;\r\n"); - fCStr_defaultFragShader.add("layout(location = 0) out vec4 colorOut0;\r\n"); - fCStr_defaultFragShader.add("\r\n"); - fCStr_defaultFragShader.add("void main(){\r\n"); - fCStr_defaultFragShader.add("gl_FragDepth = texture(textureSrc, passUV).r;\r\n"); - fCStr_defaultFragShader.add("}\r\n"); - - - defaultShader->glProgamId = gxShaderDepr_compileRaw(&fCStr_vertexShader, &fCStr_defaultFragShader); - defaultShader->copyShaderUniforms.uniformLoc_textureSrc = glGetUniformLocation(defaultShader->glProgamId, "textureSrc"); - defaultShader->copyShaderUniforms.uniformLoc_vertexOffsets = glGetUniformLocation(defaultShader->glProgamId, "uf_vertexOffsets"); - - _copyShader_colorToDepth = defaultShader; - catchOpenGLError(); - return defaultShader; -} \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Core/LatteDefaultShaders.h b/src/Cafe/HW/Latte/Core/LatteDefaultShaders.h deleted file mode 100644 index 3776a3d2..00000000 --- a/src/Cafe/HW/Latte/Core/LatteDefaultShaders.h +++ /dev/null @@ -1,13 +0,0 @@ - -typedef struct -{ - GLuint glProgamId; - struct - { - GLuint uniformLoc_textureSrc; - GLuint uniformLoc_vertexOffsets; - }copyShaderUniforms; -}LatteDefaultShader_t; - -LatteDefaultShader_t* LatteDefaultShader_getPixelCopyShader_depthToColor(); -LatteDefaultShader_t* LatteDefaultShader_getPixelCopyShader_colorToDepth(); \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp b/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp index 45be6843..5e61e8df 100644 --- a/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp +++ b/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp @@ -1,7 +1,6 @@ #include "Cafe/HW/Latte/Core/Latte.h" #include "Cafe/HW/Latte/Core/LatteDraw.h" #include "Cafe/HW/Latte/Core/LatteShader.h" -#include "Cafe/HW/Latte/Core/LatteDefaultShaders.h" #include "Cafe/HW/Latte/Core/LatteTexture.h" #include "Cafe/HW/Latte/Renderer/Renderer.h" diff --git a/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteShaderGL.cpp similarity index 100% rename from src/Cafe/HW/Latte/Core/LatteShaderGL.cpp rename to src/Cafe/HW/Latte/Renderer/OpenGL/LatteShaderGL.cpp diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp index d578b842..de1e1222 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp @@ -1,6 +1,7 @@ #include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h" #include "Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h" #include "Cafe/HW/Latte/Renderer/OpenGL/CachedFBOGL.h" +#include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.h" #include "Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.h" #include "Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.h" @@ -8,7 +9,7 @@ #include "Cafe/HW/Latte/Core/LatteShader.h" #include "Cafe/HW/Latte/Core/LatteDraw.h" -#include "Cafe/HW/Latte/Core/LatteDefaultShaders.h" +#include "util/helpers/StringBuf.h" void LatteDraw_resetAttributePointerCache(); @@ -66,9 +67,9 @@ void OpenGLRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* s if (destinationTexture->isDepth) renderstate_setAlwaysWriteDepth(); // bind format specific copy shader - LatteDefaultShader_t* copyShader = LatteDefaultShader_getPixelCopyShader_depthToColor(); + LatteGLDefaultShader_t* copyShader = LatteGLDefaultShader_getPixelCopyShader_depthToColor(); if (destinationTexture->isDepth) - copyShader = LatteDefaultShader_getPixelCopyShader_colorToDepth(); + copyShader = LatteGLDefaultShader_getPixelCopyShader_colorToDepth(); glUseProgram(copyShader->glProgamId); catchOpenGLError(); // setup uniforms @@ -113,4 +114,86 @@ void OpenGLRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* s LatteGPUState.repeatTextureInitialization = true; glUseProgram(0); +} + +LatteGLDefaultShader_t* _copyShader_depthToColor; +LatteGLDefaultShader_t* _copyShader_colorToDepth; + +void LatteGLDefaultShader_pixelCopyShader_generateVSBody(StringBuf* vs) +{ + vs->add("#version 420\r\n"); + vs->add("out vec2 passUV;\r\n"); + vs->add("uniform vec4 uf_vertexOffsets[4];\r\n"); + vs->add("\r\n"); + vs->add("void main(){\r\n"); + vs->add("int vID = gl_VertexID;\r\n"); + vs->add("passUV = uf_vertexOffsets[vID].zw;\r\n"); + vs->add("gl_Position = vec4(uf_vertexOffsets[vID].xy, 0.0, 1.0);\r\n"); + vs->add("}\r\n"); +} + +GLuint gxShaderDepr_compileRaw(StringBuf* strSourceVS, StringBuf* strSourceFS); +GLuint gxShaderDepr_compileRaw(const std::string& vertex_source, const std::string& fragment_source); + +LatteGLDefaultShader_t* LatteGLDefaultShader_getPixelCopyShader_depthToColor() +{ + if (_copyShader_depthToColor != 0) + return _copyShader_depthToColor; + catchOpenGLError(); + LatteGLDefaultShader_t* defaultShader = (LatteGLDefaultShader_t*)malloc(sizeof(LatteGLDefaultShader_t)); + memset(defaultShader, 0, sizeof(LatteGLDefaultShader_t)); + + StringBuf fCStr_vertexShader(1024 * 16); + LatteGLDefaultShader_pixelCopyShader_generateVSBody(&fCStr_vertexShader); + + StringBuf fCStr_defaultFragShader(1024 * 16); + fCStr_defaultFragShader.add("#version 420\r\n"); + fCStr_defaultFragShader.add("in vec2 passUV;\r\n"); + fCStr_defaultFragShader.add("uniform sampler2D textureSrc;\r\n"); + fCStr_defaultFragShader.add("layout(location = 0) out vec4 colorOut0;\r\n"); + fCStr_defaultFragShader.add("\r\n"); + fCStr_defaultFragShader.add("void main(){\r\n"); + fCStr_defaultFragShader.add("colorOut0 = vec4(texture(textureSrc, passUV).r,0.0,0.0,1.0);\r\n"); + fCStr_defaultFragShader.add("}\r\n"); + + defaultShader->glProgamId = gxShaderDepr_compileRaw(&fCStr_vertexShader, &fCStr_defaultFragShader); + catchOpenGLError(); + + defaultShader->copyShaderUniforms.uniformLoc_textureSrc = glGetUniformLocation(defaultShader->glProgamId, "textureSrc"); + defaultShader->copyShaderUniforms.uniformLoc_vertexOffsets = glGetUniformLocation(defaultShader->glProgamId, "uf_vertexOffsets"); + + _copyShader_depthToColor = defaultShader; + catchOpenGLError(); + return defaultShader; +} + +LatteGLDefaultShader_t* LatteGLDefaultShader_getPixelCopyShader_colorToDepth() +{ + if (_copyShader_colorToDepth != 0) + return _copyShader_colorToDepth; + catchOpenGLError(); + LatteGLDefaultShader_t* defaultShader = (LatteGLDefaultShader_t*)malloc(sizeof(LatteGLDefaultShader_t)); + memset(defaultShader, 0, sizeof(LatteGLDefaultShader_t)); + + StringBuf fCStr_vertexShader(1024 * 16); + LatteGLDefaultShader_pixelCopyShader_generateVSBody(&fCStr_vertexShader); + + StringBuf fCStr_defaultFragShader(1024 * 16); + fCStr_defaultFragShader.add("#version 420\r\n"); + fCStr_defaultFragShader.add("in vec2 passUV;\r\n"); + fCStr_defaultFragShader.add("uniform sampler2D textureSrc;\r\n"); + fCStr_defaultFragShader.add("layout(location = 0) out vec4 colorOut0;\r\n"); + fCStr_defaultFragShader.add("\r\n"); + fCStr_defaultFragShader.add("void main(){\r\n"); + fCStr_defaultFragShader.add("gl_FragDepth = texture(textureSrc, passUV).r;\r\n"); + fCStr_defaultFragShader.add("}\r\n"); + + + defaultShader->glProgamId = gxShaderDepr_compileRaw(&fCStr_vertexShader, &fCStr_defaultFragShader); + defaultShader->copyShaderUniforms.uniformLoc_textureSrc = glGetUniformLocation(defaultShader->glProgamId, "textureSrc"); + defaultShader->copyShaderUniforms.uniformLoc_vertexOffsets = glGetUniformLocation(defaultShader->glProgamId, "uf_vertexOffsets"); + + _copyShader_colorToDepth = defaultShader; + catchOpenGLError(); + return defaultShader; } \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.h b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.h new file mode 100644 index 00000000..3c6e4c25 --- /dev/null +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.h @@ -0,0 +1,14 @@ +#pragma once + +typedef struct +{ + GLuint glProgamId; + struct + { + GLuint uniformLoc_textureSrc; + GLuint uniformLoc_vertexOffsets; + }copyShaderUniforms; +}LatteGLDefaultShader_t; + +LatteGLDefaultShader_t* LatteGLDefaultShader_getPixelCopyShader_depthToColor(); +LatteGLDefaultShader_t* LatteGLDefaultShader_getPixelCopyShader_colorToDepth(); \ No newline at end of file From ca8ca2172408affa3e7140d7c25a445ca4352df4 Mon Sep 17 00:00:00 2001 From: emiyl Date: Tue, 21 Apr 2026 15:38:22 +0100 Subject: [PATCH 32/32] fix update.sh only being included in the .app if vulkan was enabled ?? --- src/CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 271bf00a..af7d4c9c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -131,10 +131,12 @@ if (MACOS_BUNDLE) endif () add_custom_command (TARGET CemuBin POST_BUILD - COMMAND ${CMAKE_COMMAND} ARGS -E copy "${MOLTENVK_PATH}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib" - COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_SOURCE_DIR}/src/resource/update.sh" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/update.sh" - COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}") + COMMAND ${CMAKE_COMMAND} ARGS -E copy "${MOLTENVK_PATH}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib") endif() + + add_custom_command (TARGET CemuBin POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_SOURCE_DIR}/src/resource/update.sh" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/update.sh" + COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}") else() if(APPLE) if (ENABLE_VULKAN)