mirror of https://github.com/cemu-project/Cemu.git
add an option to select gpu for metal
This commit is contained in:
parent
79290eae3f
commit
08ea28f56e
|
@ -36,10 +36,51 @@ float supportBufferData[512 * 4];
|
|||
// Defined in the OpenGL renderer
|
||||
void LatteDraw_handleSpecialState8_clearAsDepth();
|
||||
|
||||
std::vector<MetalRenderer::DeviceInfo> MetalRenderer::GetDevices()
|
||||
{
|
||||
auto devices = MTL::CopyAllDevices();
|
||||
std::vector<MetalRenderer::DeviceInfo> result;
|
||||
result.reserve(devices->count());
|
||||
for (uint32 i = 0; i < devices->count(); i++)
|
||||
{
|
||||
MTL::Device* device = static_cast<MTL::Device*>(devices->object(i));
|
||||
result.emplace_back(std::string(device->name()->utf8String()), device->registryID());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MetalRenderer::MetalRenderer()
|
||||
{
|
||||
m_device = MTL::CreateSystemDefaultDevice();
|
||||
m_commandQueue = m_device->newCommandQueue();
|
||||
// Pick a device
|
||||
auto& config = GetConfig();
|
||||
const bool hasDeviceSet = config.mtl_graphic_device_uuid != 0;
|
||||
|
||||
// If a device is set, try to find it
|
||||
if (hasDeviceSet)
|
||||
{
|
||||
auto devices = MTL::CopyAllDevices();
|
||||
for (uint32 i = 0; i < devices->count(); i++)
|
||||
{
|
||||
MTL::Device* device = static_cast<MTL::Device*>(devices->object(i));
|
||||
if (device->registryID() == config.mtl_graphic_device_uuid)
|
||||
{
|
||||
m_device = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_device)
|
||||
{
|
||||
if (hasDeviceSet)
|
||||
{
|
||||
cemuLog_log(LogType::Force, "The selected GPU ({}) could not be found. Using the system default device.", config.mtl_graphic_device_uuid);
|
||||
config.mtl_graphic_device_uuid = 0;
|
||||
}
|
||||
// Use the system default device
|
||||
m_device = MTL::CreateSystemDefaultDevice();
|
||||
}
|
||||
|
||||
// Feature support
|
||||
m_isAppleGPU = m_device->supportsFamily(MTL::GPUFamilyApple1);
|
||||
|
@ -50,6 +91,9 @@ MetalRenderer::MetalRenderer()
|
|||
|
||||
CheckForPixelFormatSupport(m_pixelFormatSupport);
|
||||
|
||||
// Command queue
|
||||
m_commandQueue = m_device->newCommandQueue();
|
||||
|
||||
// Synchronization resources
|
||||
m_event = m_device->newEvent();
|
||||
|
||||
|
|
|
@ -155,6 +155,14 @@ public:
|
|||
static constexpr uint32 OCCLUSION_QUERY_POOL_SIZE = 1024;
|
||||
static constexpr uint32 TEXTURE_READBACK_SIZE = 32 * 1024 * 1024; // 32 MB
|
||||
|
||||
struct DeviceInfo
|
||||
{
|
||||
std::string name;
|
||||
uint64 uuid;
|
||||
};
|
||||
|
||||
static std::vector<DeviceInfo> GetDevices();
|
||||
|
||||
MetalRenderer();
|
||||
~MetalRenderer() override;
|
||||
|
||||
|
|
|
@ -389,8 +389,8 @@ VulkanRenderer::VulkanRenderer()
|
|||
auto surface = CreateFramebufferSurface(m_instance, gui_getWindowInfo().window_main);
|
||||
|
||||
auto& config = GetConfig();
|
||||
decltype(config.graphic_device_uuid) zero{};
|
||||
const bool has_device_set = config.graphic_device_uuid != zero;
|
||||
decltype(config.vk_graphic_device_uuid) zero{};
|
||||
const bool has_device_set = config.vk_graphic_device_uuid != zero;
|
||||
|
||||
VkPhysicalDevice fallbackDevice = VK_NULL_HANDLE;
|
||||
|
||||
|
@ -410,7 +410,7 @@ VulkanRenderer::VulkanRenderer()
|
|||
physDeviceProps.pNext = &physDeviceIDProps;
|
||||
vkGetPhysicalDeviceProperties2(device, &physDeviceProps);
|
||||
|
||||
if (memcmp(config.graphic_device_uuid.data(), physDeviceIDProps.deviceUUID, VK_UUID_SIZE) != 0)
|
||||
if (memcmp(config.vk_graphic_device_uuid.data(), physDeviceIDProps.deviceUUID, VK_UUID_SIZE) != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -423,7 +423,7 @@ VulkanRenderer::VulkanRenderer()
|
|||
{
|
||||
cemuLog_log(LogType::Force, "The selected GPU could not be found or is not suitable. Falling back to first available device instead");
|
||||
m_physicalDevice = fallbackDevice;
|
||||
config.graphic_device_uuid = {}; // resetting device selection
|
||||
config.vk_graphic_device_uuid = {}; // resetting device selection
|
||||
}
|
||||
else if (m_physicalDevice == VK_NULL_HANDLE)
|
||||
{
|
||||
|
|
|
@ -212,7 +212,8 @@ void CemuConfig::Load(XMLConfigParser& parser)
|
|||
// graphics
|
||||
auto graphic = parser.get("Graphic");
|
||||
graphic_api = graphic.get("api", kOpenGL);
|
||||
graphic.get("device", graphic_device_uuid);
|
||||
graphic.get("vkDevice", vk_graphic_device_uuid);
|
||||
graphic.get("mtlDevice", mtl_graphic_device_uuid);
|
||||
vsync = graphic.get("VSync", 0);
|
||||
gx2drawdone_sync = graphic.get("GX2DrawdoneSync", true);
|
||||
upscale_filter = graphic.get("UpscaleFilter", kBicubicHermiteFilter);
|
||||
|
@ -468,7 +469,8 @@ void CemuConfig::Save(XMLConfigParser& parser)
|
|||
// graphics
|
||||
auto graphic = config.set("Graphic");
|
||||
graphic.set("api", graphic_api);
|
||||
graphic.set("device", graphic_device_uuid);
|
||||
graphic.set("vkDevice", vk_graphic_device_uuid);
|
||||
graphic.set("mtlDevice", mtl_graphic_device_uuid);
|
||||
graphic.set("VSync", vsync);
|
||||
graphic.set("GX2DrawdoneSync", gx2drawdone_sync);
|
||||
//graphic.set("PrecompiledShaders", precompiled_shaders.GetValue());
|
||||
|
|
|
@ -462,8 +462,9 @@ struct CemuConfig
|
|||
|
||||
// graphics
|
||||
ConfigValue<GraphicAPI> graphic_api{ kVulkan };
|
||||
std::array<uint8, 16> graphic_device_uuid;
|
||||
ConfigValue<int> vsync{ 0 }; // 0 = off, 1+ = on depending on render backend
|
||||
std::array<uint8, 16> vk_graphic_device_uuid;
|
||||
uint64 mtl_graphic_device_uuid{0};
|
||||
ConfigValue<int> vsync{ 0 }; // 0 = off, 1+ = depending on render backend
|
||||
ConfigValue<bool> gx2drawdone_sync {true};
|
||||
ConfigValue<bool> render_upside_down{ false };
|
||||
ConfigValue<bool> async_compile{ true };
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
|
||||
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h"
|
||||
#if ENABLE_METAL
|
||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||
#endif
|
||||
#include "Cafe/Account/Account.h"
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
@ -93,6 +96,19 @@ private:
|
|||
VulkanRenderer::DeviceInfo m_device_info;
|
||||
};
|
||||
|
||||
#if ENABLE_METAL
|
||||
class wxMetalUUID : public wxClientData
|
||||
{
|
||||
public:
|
||||
wxMetalUUID(const MetalRenderer::DeviceInfo& info)
|
||||
: m_device_info(info) {}
|
||||
const MetalRenderer::DeviceInfo& GetDeviceInfo() const { return m_device_info; }
|
||||
|
||||
private:
|
||||
MetalRenderer::DeviceInfo m_device_info;
|
||||
};
|
||||
#endif
|
||||
|
||||
class wxAccountData : public wxClientData
|
||||
{
|
||||
public:
|
||||
|
@ -1023,16 +1039,32 @@ void GeneralSettings2::StoreConfig()
|
|||
config.graphic_api = (GraphicAPI)m_graphic_api->GetSelection();
|
||||
|
||||
selection = m_graphic_device->GetSelection();
|
||||
if(selection != wxNOT_FOUND)
|
||||
if (config.graphic_api == GraphicAPI::kVulkan)
|
||||
{
|
||||
const auto* info = (wxVulkanUUID*)m_graphic_device->GetClientObject(selection);
|
||||
if(info)
|
||||
config.graphic_device_uuid = info->GetDeviceInfo().uuid;
|
||||
else
|
||||
config.graphic_device_uuid = {};
|
||||
if (selection != wxNOT_FOUND)
|
||||
{
|
||||
const auto* info = (wxVulkanUUID*)m_graphic_device->GetClientObject(selection);
|
||||
if (info)
|
||||
config.vk_graphic_device_uuid = info->GetDeviceInfo().uuid;
|
||||
else
|
||||
config.vk_graphic_device_uuid = {};
|
||||
}
|
||||
else
|
||||
config.vk_graphic_device_uuid = {};
|
||||
}
|
||||
else 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 = {};
|
||||
}
|
||||
else
|
||||
config.graphic_device_uuid = {};
|
||||
|
||||
|
||||
config.vsync = m_vsync->GetSelection();
|
||||
|
@ -1545,7 +1577,7 @@ void GeneralSettings2::HandleGraphicsApiSelection()
|
|||
const auto& config = GetConfig();
|
||||
for(size_t i = 0; i < devices.size(); ++i)
|
||||
{
|
||||
if(config.graphic_device_uuid == devices[i].uuid)
|
||||
if(config.vk_graphic_device_uuid == devices[i].uuid)
|
||||
{
|
||||
m_graphic_device->SetSelection(i);
|
||||
break;
|
||||
|
@ -1566,9 +1598,29 @@ void GeneralSettings2::HandleGraphicsApiSelection()
|
|||
|
||||
m_vsync->Select(selection);
|
||||
|
||||
// TODO: add an option to select the graphic device
|
||||
m_graphic_device->Clear();
|
||||
m_graphic_device->Disable();
|
||||
m_graphic_device->Enable();
|
||||
auto devices = MetalRenderer::GetDevices();
|
||||
m_graphic_device->Clear();
|
||||
#if ENABLE_METAL
|
||||
if(!devices.empty())
|
||||
{
|
||||
for (const auto& device : devices)
|
||||
{
|
||||
m_graphic_device->Append(device.name, new wxMetalUUID(device));
|
||||
}
|
||||
m_graphic_device->SetSelection(0);
|
||||
|
||||
const auto& config = GetConfig();
|
||||
for (size_t i = 0; i < devices.size(); ++i)
|
||||
{
|
||||
if (config.mtl_graphic_device_uuid == devices[i].uuid)
|
||||
{
|
||||
m_graphic_device->SetSelection(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue