Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Cafe/CafeSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ void InfoLog_PrintActiveSettings()
else if (ActiveSettings::GetGraphicsAPI() == GraphicAPI::kMetal)
{
cemuLog_log(LogType::Force, "Async compile: {}", GetConfig().async_compile.GetValue() ? "true" : "false");
cemuLog_log(LogType::Force, "Force mesh shaders: {}", GetConfig().force_mesh_shaders.GetValue() ? "true" : "false");
cemuLog_log(LogType::Force, "Fast math: {}", g_current_game_profile->GetFastMath() ? "true" : "false");
cemuLog_log(LogType::Force, "Buffer cache type: {}", g_current_game_profile->GetBufferCacheMode());
cemuLog_log(LogType::Force, "Position invariance: {}", g_current_game_profile->GetPositionInvariance());
Expand Down
8 changes: 5 additions & 3 deletions src/Cafe/HW/Latte/Core/LatteShader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ void LatteSHRC_UpdateVSBaseHash(uint8* vertexShaderPtr, uint32 vertexShaderSize,
vsHash += tmp;

auto primitiveType = LatteGPUState.contextNew.VGT_PRIMITIVE_TYPE.get_PRIMITIVE_MODE();
// TODO: include always in the hash in case of geometry shader or rect shader
// TODO: include always in the hash in case of geometry shader or rect shader on Metal
if (primitiveType == Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::RECTS)
{
vsHash += 13ULL;
Expand All @@ -528,7 +528,9 @@ void LatteSHRC_UpdateVSBaseHash(uint8* vertexShaderPtr, uint32 vertexShaderSize,
#if ENABLE_METAL
if (g_renderer->GetType() == RendererAPI::Metal)
{
if (usesGeometryShader || _activeFetchShader->mtlFetchVertexManually)
bool isRectVertexShader = (primitiveType == Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::RECTS);

if ((usesGeometryShader || isRectVertexShader) || _activeFetchShader->mtlFetchVertexManually)
{
for (sint32 g = 0; g < _activeFetchShader->bufferGroups.size(); g++)
{
Expand All @@ -542,7 +544,7 @@ void LatteSHRC_UpdateVSBaseHash(uint8* vertexShaderPtr, uint32 vertexShaderSize,
}
}

if (!usesGeometryShader)
if (!(usesGeometryShader || isRectVertexShader))
{
if (LatteGPUState.contextNew.IsRasterizationEnabled())
vsHash += 51ULL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#include "Cafe/HW/Latte/Renderer/Renderer.h"
#include "Common/MemPtr.h"
#include "HW/Latte/ISA/LatteReg.h"
#if ENABLE_METAL
#include "HW/Latte/Renderer/Metal/MetalCommon.h"
#endif

// Defined in LatteTextureLegacy.cpp
Latte::E_GX2SURFFMT LatteTexture_ReconstructGX2Format(const Latte::LATTE_SQ_TEX_RESOURCE_WORD1_N& texUnitWord1, const Latte::LATTE_SQ_TEX_RESOURCE_WORD4_N& texUnitWord4);
Expand Down Expand Up @@ -557,9 +560,9 @@ namespace LatteDecompiler
}
if (g_renderer->GetType() == RendererAPI::Metal)
{
bool isRectVertexShader = (static_cast<LattePrimitiveMode>(decompilerContext->contextRegisters[mmVGT_PRIMITIVE_TYPE]) == LattePrimitiveMode::RECTS);
bool usesGeometryShader = UseGeometryShader(*decompilerContext->contextRegistersNew, decompilerContext->options->usesGeometryShader);

if (decompilerContext->shaderType == LatteConst::ShaderType::Vertex && (decompilerContext->options->usesGeometryShader || isRectVertexShader))
if (decompilerContext->shaderType == LatteConst::ShaderType::Vertex && usesGeometryShader)
decompilerContext->hasUniformVarBlock = true; // uf_verticesPerInstance
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3933,8 +3933,8 @@ static void LatteDecompiler_emitAttributeImport(LatteDecompilerShaderContext* sh

void LatteDecompiler_emitMSLShader(LatteDecompilerShaderContext* shaderContext, LatteDecompilerShader* shader)
{
bool isRectVertexShader = (static_cast<LattePrimitiveMode>(shaderContext->contextRegisters[mmVGT_PRIMITIVE_TYPE]) == LattePrimitiveMode::RECTS);
bool usesGeometryShader = (shaderContext->options->usesGeometryShader || isRectVertexShader);
bool isRectVertexShader = UseRectEmulation(*shaderContext->contextRegistersNew);
bool usesGeometryShader = UseGeometryShader(*shaderContext->contextRegistersNew, shaderContext->options->usesGeometryShader);
bool fetchVertexManually = (usesGeometryShader || (shaderContext->fetchShader && shaderContext->fetchShader->mtlFetchVertexManually));

// Rasterization
Expand All @@ -3953,7 +3953,7 @@ void LatteDecompiler_emitMSLShader(LatteDecompilerShaderContext* shaderContext,
src->add("#include <metal_stdlib>" _CRLF);
src->add("using namespace metal;" _CRLF);
// header part (definitions for inputs and outputs)
LatteDecompiler::emitHeader(shaderContext, isRectVertexShader, fetchVertexManually, rasterizationEnabled);
LatteDecompiler::emitHeader(shaderContext, isRectVertexShader, usesGeometryShader, fetchVertexManually, rasterizationEnabled);
// helper functions
LatteDecompiler_emitHelperFunctions(shaderContext, src);
const char* functionType = "";
Expand Down Expand Up @@ -4131,7 +4131,7 @@ void LatteDecompiler_emitMSLShader(LatteDecompilerShaderContext* shaderContext,
}
// start of main
src->addFmt("{} {} main0(", functionType, outputTypeName);
LatteDecompiler::emitInputs(shaderContext, isRectVertexShader, fetchVertexManually);
LatteDecompiler::emitInputs(shaderContext, isRectVertexShader, usesGeometryShader, fetchVertexManually);
src->add(") {" _CRLF);
if (fetchVertexManually && (shader->shaderType == LatteConst::ShaderType::Vertex || shader->shaderType == LatteConst::ShaderType::Geometry))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace LatteDecompiler
{
static void _emitUniformVariables(LatteDecompilerShaderContext* decompilerContext, bool isRectVertexShader)
static void _emitUniformVariables(LatteDecompilerShaderContext* decompilerContext, bool usesGeometryShader)
{
auto src = decompilerContext->shaderSource;

Expand Down Expand Up @@ -87,7 +87,7 @@ namespace LatteDecompiler
}
// define verticesPerInstance + streamoutBufferBaseX
if ((shader->shaderType == LatteConst::ShaderType::Vertex &&
(decompilerContext->options->usesGeometryShader || isRectVertexShader)) ||
usesGeometryShader) ||
(decompilerContext->analyzer.useSSBOForStreamout &&
(shader->shaderType == LatteConst::ShaderType::Vertex && !decompilerContext->options->usesGeometryShader) ||
(shader->shaderType == LatteConst::ShaderType::Geometry)))
Expand Down Expand Up @@ -270,7 +270,7 @@ namespace LatteDecompiler
src->add("};" _CRLF _CRLF);
}

static void _emitInputsAndOutputs(LatteDecompilerShaderContext* decompilerContext, bool isRectVertexShader, bool fetchVertexManually, bool rasterizationEnabled)
static void _emitInputsAndOutputs(LatteDecompilerShaderContext* decompilerContext, bool isRectVertexShader, bool usesGeometryShader, bool fetchVertexManually, bool rasterizationEnabled)
{
auto src = decompilerContext->shaderSource;

Expand Down Expand Up @@ -304,7 +304,7 @@ namespace LatteDecompiler
src->add("};" _CRLF _CRLF);
}

if (!decompilerContext->options->usesGeometryShader)
if (!usesGeometryShader || isRectVertexShader)
{
if (decompilerContext->shaderType == LatteConst::ShaderType::Vertex && rasterizationEnabled)
_emitVSOutputs(decompilerContext, isRectVertexShader);
Expand Down Expand Up @@ -357,11 +357,11 @@ namespace LatteDecompiler
}
}

static void emitHeader(LatteDecompilerShaderContext* decompilerContext, bool isRectVertexShader, bool fetchVertexManually, bool rasterizationEnabled)
static void emitHeader(LatteDecompilerShaderContext* decompilerContext, bool isRectVertexShader, bool usesGeometryShader, bool fetchVertexManually, bool rasterizationEnabled)
{
auto src = decompilerContext->shaderSource;

if ((decompilerContext->options->usesGeometryShader || isRectVertexShader) && (decompilerContext->shaderType == LatteConst::ShaderType::Vertex || decompilerContext->shaderType == LatteConst::ShaderType::Geometry))
if (usesGeometryShader && (decompilerContext->shaderType == LatteConst::ShaderType::Vertex || decompilerContext->shaderType == LatteConst::ShaderType::Geometry))
{
LattePrimitiveMode vsOutPrimType = decompilerContext->contextRegistersNew->VGT_PRIMITIVE_TYPE.get_PRIMITIVE_MODE();
src->addFmt("#define VERTICES_PER_VERTEX_PRIMITIVE {}" _CRLF, GetVerticesPerPrimitive(vsOutPrimType));
Expand Down Expand Up @@ -399,11 +399,11 @@ namespace LatteDecompiler
if(dump_shaders_enabled)
decompilerContext->shaderSource->add("// start of shader inputs/outputs, predetermined by Cemu. Do not touch" _CRLF);
// uniform variables
_emitUniformVariables(decompilerContext, isRectVertexShader);
_emitUniformVariables(decompilerContext, usesGeometryShader);
// uniform buffers
_emitUniformBuffers(decompilerContext);
// inputs and outputs
_emitInputsAndOutputs(decompilerContext, isRectVertexShader, fetchVertexManually, rasterizationEnabled);
_emitInputsAndOutputs(decompilerContext, isRectVertexShader, usesGeometryShader, fetchVertexManually, rasterizationEnabled);

if (dump_shaders_enabled)
decompilerContext->shaderSource->add("// end of shader inputs/outputs" _CRLF);
Expand Down Expand Up @@ -491,14 +491,14 @@ namespace LatteDecompiler
}
}

static void emitInputs(LatteDecompilerShaderContext* decompilerContext, bool isRectVertexShader, bool fetchVertexManually)
static void emitInputs(LatteDecompilerShaderContext* decompilerContext, bool isRectVertexShader, bool usesGeometryShader, bool fetchVertexManually)
{
auto src = decompilerContext->shaderSource;

switch (decompilerContext->shaderType)
{
case LatteConst::ShaderType::Vertex:
if (decompilerContext->options->usesGeometryShader || isRectVertexShader)
if (usesGeometryShader)
{
src->add("object_data ObjectPayload& objectPayload [[payload]]");
src->add(", mesh_grid_properties meshGridProperties");
Expand Down
9 changes: 9 additions & 0 deletions src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,12 @@ inline bool PrimitiveRequiresConnection(LattePrimitiveMode primitiveMode)
else
return false;
}

inline bool UseRectEmulation(const LatteContextRegister& lcr) {
const LattePrimitiveMode primitiveMode = lcr.VGT_PRIMITIVE_TYPE.get_PRIMITIVE_MODE();
return (primitiveMode == Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::RECTS);
}

inline bool UseGeometryShader(const LatteContextRegister& lcr, bool hasGeometryShader) {
return hasGeometryShader || UseRectEmulation(lcr);
}
16 changes: 9 additions & 7 deletions src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,16 +283,15 @@ MetalPipelineCompiler::~MetalPipelineCompiler()

m_binaryArchiveURL->release();
*/
m_pipelineDescriptor->release();
if (m_pipelineDescriptor)
m_pipelineDescriptor->release();
}

void MetalPipelineCompiler::InitFromState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr)
{
// Check if the pipeline uses a geometry shader
const LattePrimitiveMode primitiveMode = static_cast<LattePrimitiveMode>(lcr.VGT_PRIMITIVE_TYPE.get_PRIMITIVE_MODE());
bool isPrimitiveRect = (primitiveMode == Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::RECTS);

m_usesGeometryShader = (geometryShader != nullptr || isPrimitiveRect);
m_usesGeometryShader = UseGeometryShader(lcr, geometryShader != nullptr);
if (m_usesGeometryShader && !m_mtlr->SupportsMeshShaders())
return;

// Rasterization
m_rasterizationEnabled = lcr.IsRasterizationEnabled();
Expand All @@ -301,7 +300,7 @@ void MetalPipelineCompiler::InitFromState(const LatteFetchShader* fetchShader, c
m_vertexShaderMtl = static_cast<RendererShaderMtl*>(vertexShader->shader);
if (geometryShader)
m_geometryShaderMtl = static_cast<RendererShaderMtl*>(geometryShader->shader);
else if (isPrimitiveRect)
else if (UseRectEmulation(lcr))
m_geometryShaderMtl = rectsEmulationGS_generate(m_mtlr, vertexShader, lcr);
else
m_geometryShaderMtl = nullptr;
Expand All @@ -315,6 +314,9 @@ void MetalPipelineCompiler::InitFromState(const LatteFetchShader* fetchShader, c

bool MetalPipelineCompiler::Compile(bool forceCompile, bool isRenderThread, bool showInOverlay)
{
if (m_usesGeometryShader && !m_mtlr->SupportsMeshShaders())
return false;

if (forceCompile)
{
// if some shader stages are not compiled yet, compile them now
Expand Down
2 changes: 1 addition & 1 deletion src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class MetalPipelineCompiler
bool m_usesGeometryShader;
bool m_rasterizationEnabled;

NS::Object* m_pipelineDescriptor;
NS::Object* m_pipelineDescriptor = nullptr;

void InitFromStateRender(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const class MetalAttachmentsInfo& lastUsedAttachmentsInfo, const class MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr);

Expand Down
12 changes: 7 additions & 5 deletions src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "Cemu/Logging/CemuLogging.h"
#include "Cafe/HW/Latte/Core/FetchShader.h"
#include "Cafe/HW/Latte/Core/LatteConst.h"
#include "HW/Latte/Renderer/Metal/MetalCommon.h"
#include "config/CemuConfig.h"
#include "gui/guiWrapper.h"

Expand Down Expand Up @@ -171,6 +170,7 @@ MetalRenderer::MetalRenderer()
m_supportsFramebufferFetch = GetConfig().framebuffer_fetch.GetValue() ? m_device->supportsFamily(MTL::GPUFamilyApple2) : false;
m_hasUnifiedMemory = m_device->hasUnifiedMemory();
m_supportsMetal3 = m_device->supportsFamily(MTL::GPUFamilyMetal3);
m_supportsMeshShaders = (m_supportsMetal3 && (m_vendor != GfxVendor::Intel || GetConfig().force_mesh_shaders.GetValue())); // Intel GPUs have issues with mesh shaders
m_recommendedMaxVRAMUsage = m_device->recommendedMaxWorkingSetSize();
m_pixelFormatSupport = MetalPixelFormatSupport(m_device);

Expand Down Expand Up @@ -1134,9 +1134,11 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
// Primitive type
const LattePrimitiveMode primitiveMode = LatteGPUState.contextNew.VGT_PRIMITIVE_TYPE.get_PRIMITIVE_MODE();
auto mtlPrimitiveType = GetMtlPrimitiveType(primitiveMode);
bool isPrimitiveRect = (primitiveMode == Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::RECTS);

bool usesGeometryShader = (geometryShader != nullptr || isPrimitiveRect);
bool usesGeometryShader = UseGeometryShader(LatteGPUState.contextNew, geometryShader != nullptr);
if (usesGeometryShader && !m_supportsMeshShaders)
return;

bool fetchVertexManually = (usesGeometryShader || fetchShader->mtlFetchVertexManually);

// Index buffer
Expand Down Expand Up @@ -1293,7 +1295,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32

// todo - how does culling behave with rects?
// right now we just assume that their winding is always CW
if (isPrimitiveRect)
if (primitiveMode == Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::RECTS)
{
if (frontFace == Latte::LATTE_PA_SU_SC_MODE_CNTL::E_FRONTFACE::CW)
cullFront = cullBack;
Expand Down Expand Up @@ -1380,7 +1382,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32

// Uniform buffers, textures and samplers
BindStageResources(renderCommandEncoder, vertexShader, usesGeometryShader);
if (geometryShader)
if (usesGeometryShader && geometryShader)
BindStageResources(renderCommandEncoder, geometryShader, usesGeometryShader);
BindStageResources(renderCommandEncoder, pixelShader, usesGeometryShader);

Expand Down
7 changes: 6 additions & 1 deletion src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include "Cafe/HW/Latte/Renderer/Metal/MetalPerformanceMonitor.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalOutputShaderCache.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h"
#include "Foundation/NSAutoreleasePool.hpp"

enum MetalGeneralShaderType
{
Expand Down Expand Up @@ -385,6 +384,11 @@ class MetalRenderer : public Renderer
return m_supportsMetal3;
}

bool SupportsMeshShaders() const
{
return m_supportsMeshShaders;
}

//MTL::StorageMode GetOptimalTextureStorageMode() const
//{
// return (m_isAppleGPU ? MTL::StorageModeShared : MTL::StorageModePrivate);
Expand Down Expand Up @@ -483,6 +487,7 @@ class MetalRenderer : public Renderer
bool m_supportsFramebufferFetch;
bool m_hasUnifiedMemory;
bool m_supportsMetal3;
bool m_supportsMeshShaders;
uint32 m_recommendedMaxVRAMUsage;
MetalPixelFormatSupport m_pixelFormatSupport;

Expand Down
2 changes: 2 additions & 0 deletions src/config/CemuConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ void 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
force_mesh_shaders = graphic.get("ForceMeshShaders", false);

auto overlay_node = graphic.get("Overlay");
if(overlay_node.valid())
Expand Down Expand Up @@ -477,6 +478,7 @@ void CemuConfig::Save(XMLConfigParser& parser)
graphic.set("mtlDevice", mtl_graphic_device_uuid);
graphic.set("VSync", vsync);
graphic.set("GX2DrawdoneSync", gx2drawdone_sync);
graphic.set("ForceMeshShaders", force_mesh_shaders);
//graphic.set("PrecompiledShaders", precompiled_shaders.GetValue());
graphic.set("UpscaleFilter", upscale_filter);
graphic.set("DownscaleFilter", downscale_filter);
Expand Down
1 change: 1 addition & 0 deletions src/config/CemuConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ struct CemuConfig
ConfigValue<bool> gx2drawdone_sync { true };
ConfigValue<bool> render_upside_down{ false };
ConfigValue<bool> async_compile{ true };
ConfigValue<bool> force_mesh_shaders{ false };

ConfigValue<bool> vk_accurate_barriers{ true };

Expand Down
13 changes: 10 additions & 3 deletions src/gui/GeneralSettings2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,10 @@ 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);

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"));
graphic_misc_row->Add(m_force_mesh_shaders, 0, wxALL, 5);

box_sizer->Add(graphic_misc_row, 1, wxEXPAND, 5);
graphics_panel_sizer->Add(box_sizer, 0, wxEXPAND | wxALL, 5);
}
Expand Down Expand Up @@ -1100,6 +1104,7 @@ void GeneralSettings2::StoreConfig()

config.vsync = m_vsync->GetSelection();
config.gx2drawdone_sync = m_gx2drawdone_sync->IsChecked();
config.force_mesh_shaders = m_force_mesh_shaders->IsChecked();
config.async_compile = m_async_compile->IsChecked();

config.upscale_filter = m_upscale_filter->GetSelection();
Expand Down Expand Up @@ -1580,12 +1585,14 @@ void GeneralSettings2::HandleGraphicsApiSelection()

m_gx2drawdone_sync->Enable();
m_async_compile->Disable();
m_force_mesh_shaders->Disable();
}
else if (m_graphic_api->GetSelection() == 1)
{
// Vulkan
m_gx2drawdone_sync->Disable();
m_async_compile->Enable();
m_force_mesh_shaders->Disable();

m_vsync->AppendString(_("Off"));
m_vsync->AppendString(_("Double buffering"));
Expand Down Expand Up @@ -1623,11 +1630,10 @@ void GeneralSettings2::HandleGraphicsApiSelection()
// Metal
m_gx2drawdone_sync->Disable();
m_async_compile->Enable();
m_force_mesh_shaders->Enable();

// TODO: vsync options
m_vsync->AppendString(_("Off"));
m_vsync->AppendString(_("Double buffering"));
m_vsync->AppendString(_("Triple buffering"));
m_vsync->AppendString(_("On"));

m_vsync->Select(selection);

Expand Down Expand Up @@ -1708,6 +1714,7 @@ void GeneralSettings2::ApplyConfig()
m_vsync->SetSelection(config.vsync);
m_async_compile->SetValue(config.async_compile);
m_gx2drawdone_sync->SetValue(config.gx2drawdone_sync);
m_force_mesh_shaders->SetValue(config.force_mesh_shaders);
m_upscale_filter->SetSelection(config.upscale_filter);
m_downscale_filter->SetSelection(config.downscale_filter);
m_fullscreen_scaling->SetSelection(config.fullscreen_scaling);
Expand Down
2 changes: 1 addition & 1 deletion src/gui/GeneralSettings2.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class GeneralSettings2 : public wxDialog
// Graphics
wxChoice* m_graphic_api, * m_graphic_device;
wxChoice* m_vsync;
wxCheckBox *m_async_compile, *m_gx2drawdone_sync;
wxCheckBox *m_async_compile, *m_gx2drawdone_sync, *m_force_mesh_shaders;
wxRadioBox* m_upscale_filter, *m_downscale_filter, *m_fullscreen_scaling;
wxChoice* m_overlay_position, *m_notification_position, *m_overlay_scale, *m_notification_scale;
wxCheckBox* m_controller_profile_name, *m_controller_low_battery, *m_shader_compiling, *m_friends_data;
Expand Down
Loading