mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-05 06:21:19 +12:00
parent
fa004a33c6
commit
770d6cfda7
7 changed files with 41 additions and 105 deletions
|
@ -20,8 +20,6 @@
|
||||||
#include "Cemu/Logging/CemuLogging.h"
|
#include "Cemu/Logging/CemuLogging.h"
|
||||||
#include "Cafe/HW/Latte/Core/FetchShader.h"
|
#include "Cafe/HW/Latte/Core/FetchShader.h"
|
||||||
#include "Cafe/HW/Latte/Core/LatteConst.h"
|
#include "Cafe/HW/Latte/Core/LatteConst.h"
|
||||||
#include "Foundation/NSString.hpp"
|
|
||||||
#include "Metal/MTLDevice.hpp"
|
|
||||||
#include "config/CemuConfig.h"
|
#include "config/CemuConfig.h"
|
||||||
#include "gui/guiWrapper.h"
|
#include "gui/guiWrapper.h"
|
||||||
|
|
||||||
|
@ -38,53 +36,10 @@ float supportBufferData[512 * 4];
|
||||||
// Defined in the OpenGL renderer
|
// Defined in the OpenGL renderer
|
||||||
void LatteDraw_handleSpecialState8_clearAsDepth();
|
void LatteDraw_handleSpecialState8_clearAsDepth();
|
||||||
|
|
||||||
std::vector<std::string> MetalRenderer::GetDevices()
|
|
||||||
{
|
|
||||||
auto devices = MTL::CopyAllDevices();
|
|
||||||
std::vector<std::string> result;
|
|
||||||
result.reserve(devices->count());
|
|
||||||
for (uint32 i = 0; i < devices->count(); i++)
|
|
||||||
{
|
|
||||||
MTL::Device* device = static_cast<MTL::Device*>(devices->object(i));
|
|
||||||
result.push_back(std::string(device->name()->utf8String()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
MetalRenderer::MetalRenderer()
|
MetalRenderer::MetalRenderer()
|
||||||
{
|
{
|
||||||
// Pick a device
|
m_device = MTL::CreateSystemDefaultDevice();
|
||||||
auto& config = GetConfig();
|
m_commandQueue = m_device->newCommandQueue();
|
||||||
const bool hasDeviceSet = !config.graphic_device_name.empty();
|
|
||||||
|
|
||||||
// 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));
|
|
||||||
std::string name = std::string(device->name()->utf8String());
|
|
||||||
if (name == config.graphic_device_name)
|
|
||||||
{
|
|
||||||
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.graphic_device_name);
|
|
||||||
config.graphic_device_name = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the system default device
|
|
||||||
m_device = MTL::CreateSystemDefaultDevice();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Feature support
|
// Feature support
|
||||||
m_isAppleGPU = m_device->supportsFamily(MTL::GPUFamilyApple1);
|
m_isAppleGPU = m_device->supportsFamily(MTL::GPUFamilyApple1);
|
||||||
|
@ -95,9 +50,6 @@ MetalRenderer::MetalRenderer()
|
||||||
|
|
||||||
CheckForPixelFormatSupport(m_pixelFormatSupport);
|
CheckForPixelFormatSupport(m_pixelFormatSupport);
|
||||||
|
|
||||||
// Create command queue
|
|
||||||
m_commandQueue = m_device->newCommandQueue();
|
|
||||||
|
|
||||||
// Synchronization resources
|
// Synchronization resources
|
||||||
m_event = m_device->newEvent();
|
m_event = m_device->newEvent();
|
||||||
|
|
||||||
|
@ -571,7 +523,6 @@ void MetalRenderer::DeleteFontTextures()
|
||||||
void MetalRenderer::AppendOverlayDebugInfo()
|
void MetalRenderer::AppendOverlayDebugInfo()
|
||||||
{
|
{
|
||||||
ImGui::Text("--- GPU info ---");
|
ImGui::Text("--- GPU info ---");
|
||||||
ImGui::Text("GPU name %s", m_device->name()->utf8String());
|
|
||||||
ImGui::Text("Is Apple GPU %s", (m_isAppleGPU ? "yes" : "no"));
|
ImGui::Text("Is Apple GPU %s", (m_isAppleGPU ? "yes" : "no"));
|
||||||
ImGui::Text("Has unified memory %s", (m_hasUnifiedMemory ? "yes" : "no"));
|
ImGui::Text("Has unified memory %s", (m_hasUnifiedMemory ? "yes" : "no"));
|
||||||
ImGui::Text("Supports Metal3 %s", (m_supportsMetal3 ? "yes" : "no"));
|
ImGui::Text("Supports Metal3 %s", (m_supportsMetal3 ? "yes" : "no"));
|
||||||
|
@ -685,7 +636,6 @@ void MetalRenderer::texture_clearColorSlice(LatteTexture* hostTexture, sint32 sl
|
||||||
{
|
{
|
||||||
if (!FormatIsRenderable(hostTexture->format))
|
if (!FormatIsRenderable(hostTexture->format))
|
||||||
{
|
{
|
||||||
// TODO: handle this somehow?
|
|
||||||
cemuLog_logOnce(LogType::Force, "cannot clear color texture with format {}, because it's not renderable", hostTexture->format);
|
cemuLog_logOnce(LogType::Force, "cannot clear color texture with format {}, because it's not renderable", hostTexture->format);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,8 +155,6 @@ public:
|
||||||
static constexpr uint32 OCCLUSION_QUERY_POOL_SIZE = 1024;
|
static constexpr uint32 OCCLUSION_QUERY_POOL_SIZE = 1024;
|
||||||
static constexpr uint32 TEXTURE_READBACK_SIZE = 32 * 1024 * 1024; // 32 MB
|
static constexpr uint32 TEXTURE_READBACK_SIZE = 32 * 1024 * 1024; // 32 MB
|
||||||
|
|
||||||
static std::vector<std::string> GetDevices();
|
|
||||||
|
|
||||||
MetalRenderer();
|
MetalRenderer();
|
||||||
~MetalRenderer() override;
|
~MetalRenderer() override;
|
||||||
|
|
||||||
|
@ -461,7 +459,7 @@ private:
|
||||||
MetalPerformanceMonitor m_performanceMonitor;
|
MetalPerformanceMonitor m_performanceMonitor;
|
||||||
|
|
||||||
// Metal objects
|
// Metal objects
|
||||||
MTL::Device* m_device = nullptr;
|
MTL::Device* m_device;
|
||||||
MTL::CommandQueue* m_commandQueue;
|
MTL::CommandQueue* m_commandQueue;
|
||||||
|
|
||||||
// Feature support
|
// Feature support
|
||||||
|
|
|
@ -91,7 +91,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback(VkDebugUtilsMessageSeverityFla
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> VulkanRenderer::GetDevices()
|
std::vector<VulkanRenderer::DeviceInfo> VulkanRenderer::GetDevices()
|
||||||
{
|
{
|
||||||
if(!vkEnumerateInstanceVersion)
|
if(!vkEnumerateInstanceVersion)
|
||||||
{
|
{
|
||||||
|
@ -105,7 +105,7 @@ std::vector<std::string> VulkanRenderer::GetDevices()
|
||||||
apiVersion = VK_API_VERSION_1_1;
|
apiVersion = VK_API_VERSION_1_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> result;
|
std::vector<DeviceInfo> result;
|
||||||
|
|
||||||
std::vector<const char*> requiredExtensions;
|
std::vector<const char*> requiredExtensions;
|
||||||
requiredExtensions.clear();
|
requiredExtensions.clear();
|
||||||
|
@ -168,7 +168,7 @@ std::vector<std::string> VulkanRenderer::GetDevices()
|
||||||
physDeviceProps.pNext = &physDeviceIDProps;
|
physDeviceProps.pNext = &physDeviceIDProps;
|
||||||
vkGetPhysicalDeviceProperties2(device, &physDeviceProps);
|
vkGetPhysicalDeviceProperties2(device, &physDeviceProps);
|
||||||
|
|
||||||
result.emplace_back(physDeviceProps.properties.deviceName);
|
result.emplace_back(physDeviceProps.properties.deviceName, physDeviceIDProps.deviceUUID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vkDestroySurfaceKHR(instance, surface, nullptr);
|
vkDestroySurfaceKHR(instance, surface, nullptr);
|
||||||
|
@ -181,6 +181,7 @@ std::vector<std::string> VulkanRenderer::GetDevices()
|
||||||
vkDestroyInstance(instance, nullptr);
|
vkDestroyInstance(instance, nullptr);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::DetermineVendor()
|
void VulkanRenderer::DetermineVendor()
|
||||||
|
@ -388,7 +389,8 @@ VulkanRenderer::VulkanRenderer()
|
||||||
auto surface = CreateFramebufferSurface(m_instance, gui_getWindowInfo().window_main);
|
auto surface = CreateFramebufferSurface(m_instance, gui_getWindowInfo().window_main);
|
||||||
|
|
||||||
auto& config = GetConfig();
|
auto& config = GetConfig();
|
||||||
const bool has_device_set = !config.graphic_device_name.empty();
|
decltype(config.graphic_device_uuid) zero{};
|
||||||
|
const bool has_device_set = config.graphic_device_uuid != zero;
|
||||||
|
|
||||||
VkPhysicalDevice fallbackDevice = VK_NULL_HANDLE;
|
VkPhysicalDevice fallbackDevice = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
@ -408,7 +410,7 @@ VulkanRenderer::VulkanRenderer()
|
||||||
physDeviceProps.pNext = &physDeviceIDProps;
|
physDeviceProps.pNext = &physDeviceIDProps;
|
||||||
vkGetPhysicalDeviceProperties2(device, &physDeviceProps);
|
vkGetPhysicalDeviceProperties2(device, &physDeviceProps);
|
||||||
|
|
||||||
if (config.graphic_device_name != physDeviceProps.properties.deviceName)
|
if (memcmp(config.graphic_device_uuid.data(), physDeviceIDProps.deviceUUID, VK_UUID_SIZE) != 0)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,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");
|
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;
|
m_physicalDevice = fallbackDevice;
|
||||||
config.graphic_device_name = ""; // resetting device selection
|
config.graphic_device_uuid = {}; // resetting device selection
|
||||||
}
|
}
|
||||||
else if (m_physicalDevice == VK_NULL_HANDLE)
|
else if (m_physicalDevice == VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -156,7 +156,19 @@ public:
|
||||||
sint32 texelCountY;
|
sint32 texelCountY;
|
||||||
}FormatInfoVK;
|
}FormatInfoVK;
|
||||||
|
|
||||||
static std::vector<std::string> GetDevices();
|
struct DeviceInfo
|
||||||
|
{
|
||||||
|
DeviceInfo(const std::string name, uint8* uuid)
|
||||||
|
: name(name)
|
||||||
|
{
|
||||||
|
std::copy(uuid, uuid + VK_UUID_SIZE, this->uuid.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::array<uint8, VK_UUID_SIZE> uuid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::vector<DeviceInfo> GetDevices();
|
||||||
VulkanRenderer();
|
VulkanRenderer();
|
||||||
virtual ~VulkanRenderer();
|
virtual ~VulkanRenderer();
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,7 @@ void CemuConfig::Load(XMLConfigParser& parser)
|
||||||
// graphics
|
// graphics
|
||||||
auto graphic = parser.get("Graphic");
|
auto graphic = parser.get("Graphic");
|
||||||
graphic_api = graphic.get("api", kOpenGL);
|
graphic_api = graphic.get("api", kOpenGL);
|
||||||
graphic.get("device", graphic_device_name);
|
graphic.get("device", graphic_device_uuid);
|
||||||
vsync = graphic.get("VSync", 0);
|
vsync = graphic.get("VSync", 0);
|
||||||
gx2drawdone_sync = graphic.get("GX2DrawdoneSync", true);
|
gx2drawdone_sync = graphic.get("GX2DrawdoneSync", true);
|
||||||
upscale_filter = graphic.get("UpscaleFilter", kBicubicHermiteFilter);
|
upscale_filter = graphic.get("UpscaleFilter", kBicubicHermiteFilter);
|
||||||
|
@ -468,7 +468,7 @@ void CemuConfig::Save(XMLConfigParser& parser)
|
||||||
// graphics
|
// graphics
|
||||||
auto graphic = config.set("Graphic");
|
auto graphic = config.set("Graphic");
|
||||||
graphic.set("api", graphic_api);
|
graphic.set("api", graphic_api);
|
||||||
graphic.set("device", graphic_device_name);
|
graphic.set("device", graphic_device_uuid);
|
||||||
graphic.set("VSync", vsync);
|
graphic.set("VSync", vsync);
|
||||||
graphic.set("GX2DrawdoneSync", gx2drawdone_sync);
|
graphic.set("GX2DrawdoneSync", gx2drawdone_sync);
|
||||||
//graphic.set("PrecompiledShaders", precompiled_shaders.GetValue());
|
//graphic.set("PrecompiledShaders", precompiled_shaders.GetValue());
|
||||||
|
|
|
@ -462,7 +462,7 @@ struct CemuConfig
|
||||||
|
|
||||||
// graphics
|
// graphics
|
||||||
ConfigValue<GraphicAPI> graphic_api{ kVulkan };
|
ConfigValue<GraphicAPI> graphic_api{ kVulkan };
|
||||||
std::string graphic_device_name;
|
std::array<uint8, 16> graphic_device_uuid;
|
||||||
ConfigValue<int> vsync{ 0 }; // 0 = off, 1+ = on depending on render backend
|
ConfigValue<int> vsync{ 0 }; // 0 = off, 1+ = on depending on render backend
|
||||||
ConfigValue<bool> gx2drawdone_sync {true};
|
ConfigValue<bool> gx2drawdone_sync {true};
|
||||||
ConfigValue<bool> render_upside_down{ false };
|
ConfigValue<bool> render_upside_down{ false };
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#include "Foundation/NSString.hpp"
|
|
||||||
#include "Metal/MTLDevice.hpp"
|
|
||||||
#include "gui/wxgui.h"
|
#include "gui/wxgui.h"
|
||||||
#include "gui/GeneralSettings2.h"
|
#include "gui/GeneralSettings2.h"
|
||||||
#include "gui/CemuApp.h"
|
#include "gui/CemuApp.h"
|
||||||
|
@ -29,9 +27,6 @@
|
||||||
|
|
||||||
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
|
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.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 "Cafe/Account/Account.h"
|
||||||
|
|
||||||
#include <boost/tokenizer.hpp>
|
#include <boost/tokenizer.hpp>
|
||||||
|
@ -87,15 +82,15 @@ private:
|
||||||
IAudioInputAPI::DeviceDescriptionPtr m_description;
|
IAudioInputAPI::DeviceDescriptionPtr m_description;
|
||||||
};
|
};
|
||||||
|
|
||||||
class wxGraphicsDevice : public wxClientData
|
class wxVulkanUUID : public wxClientData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxGraphicsDevice(const std::string& name)
|
wxVulkanUUID(const VulkanRenderer::DeviceInfo& info)
|
||||||
: m_name(name) {}
|
: m_device_info(info) {}
|
||||||
const std::string& GetName() const { return m_name; }
|
const VulkanRenderer::DeviceInfo& GetDeviceInfo() const { return m_device_info; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_name;
|
VulkanRenderer::DeviceInfo m_device_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
class wxAccountData : public wxClientData
|
class wxAccountData : public wxClientData
|
||||||
|
@ -1030,14 +1025,14 @@ void GeneralSettings2::StoreConfig()
|
||||||
selection = m_graphic_device->GetSelection();
|
selection = m_graphic_device->GetSelection();
|
||||||
if(selection != wxNOT_FOUND)
|
if(selection != wxNOT_FOUND)
|
||||||
{
|
{
|
||||||
const auto* info = (wxGraphicsDevice*)m_graphic_device->GetClientObject(selection);
|
const auto* info = (wxVulkanUUID*)m_graphic_device->GetClientObject(selection);
|
||||||
if(info)
|
if(info)
|
||||||
config.graphic_device_name = info->GetName();
|
config.graphic_device_uuid = info->GetDeviceInfo().uuid;
|
||||||
else
|
else
|
||||||
config.graphic_device_name = "";
|
config.graphic_device_uuid = {};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
config.graphic_device_name = "";
|
config.graphic_device_uuid = {};
|
||||||
|
|
||||||
|
|
||||||
config.vsync = m_vsync->GetSelection();
|
config.vsync = m_vsync->GetSelection();
|
||||||
|
@ -1543,14 +1538,14 @@ void GeneralSettings2::HandleGraphicsApiSelection()
|
||||||
{
|
{
|
||||||
for(const auto& device : devices)
|
for(const auto& device : devices)
|
||||||
{
|
{
|
||||||
m_graphic_device->Append(device, new wxGraphicsDevice(device));
|
m_graphic_device->Append(device.name, new wxVulkanUUID(device));
|
||||||
}
|
}
|
||||||
m_graphic_device->SetSelection(0);
|
m_graphic_device->SetSelection(0);
|
||||||
|
|
||||||
const auto& config = GetConfig();
|
const auto& config = GetConfig();
|
||||||
for(size_t i = 0; i < devices.size(); ++i)
|
for(size_t i = 0; i < devices.size(); ++i)
|
||||||
{
|
{
|
||||||
if(config.graphic_device_name == devices[i])
|
if(config.graphic_device_uuid == devices[i].uuid)
|
||||||
{
|
{
|
||||||
m_graphic_device->SetSelection(i);
|
m_graphic_device->SetSelection(i);
|
||||||
break;
|
break;
|
||||||
|
@ -1571,30 +1566,9 @@ void GeneralSettings2::HandleGraphicsApiSelection()
|
||||||
|
|
||||||
m_vsync->Select(selection);
|
m_vsync->Select(selection);
|
||||||
|
|
||||||
m_graphic_device->Enable();
|
// TODO: add an option to select the graphic device
|
||||||
m_graphic_device->Clear();
|
m_graphic_device->Clear();
|
||||||
|
m_graphic_device->Disable();
|
||||||
#if ENABLE_METAL
|
|
||||||
auto devices = MetalRenderer::GetDevices();
|
|
||||||
if (!devices.empty())
|
|
||||||
{
|
|
||||||
for (const auto& device : devices)
|
|
||||||
{
|
|
||||||
m_graphic_device->Append(device, new wxGraphicsDevice(device));
|
|
||||||
}
|
|
||||||
m_graphic_device->SetSelection(0);
|
|
||||||
|
|
||||||
const auto& config = GetConfig();
|
|
||||||
for (size_t i = 0; i < devices.size(); ++i)
|
|
||||||
{
|
|
||||||
if (config.graphic_device_name == devices[i])
|
|
||||||
{
|
|
||||||
m_graphic_device->SetSelection(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue