mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 08:09:26 +01:00
Merge pull request #7039 from stenzek/moltenvk
Vulkan: macOS support via MoltenVK
This commit is contained in:
commit
6388992f62
@ -30,7 +30,31 @@ private:
|
|||||||
};
|
};
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|
||||||
#else // _WIN32
|
#elif defined(__APPLE__)
|
||||||
|
|
||||||
|
#include <dispatch/dispatch.h>
|
||||||
|
|
||||||
|
namespace Common
|
||||||
|
{
|
||||||
|
class Semaphore
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Semaphore(int initial_count, int maximum_count)
|
||||||
|
{
|
||||||
|
m_handle = dispatch_semaphore_create(0);
|
||||||
|
for (int i = 0; i < initial_count; i++)
|
||||||
|
dispatch_semaphore_signal(m_handle);
|
||||||
|
}
|
||||||
|
~Semaphore() { dispatch_release(m_handle); }
|
||||||
|
void Wait() { dispatch_semaphore_wait(m_handle, DISPATCH_TIME_FOREVER); }
|
||||||
|
void Post() { dispatch_semaphore_signal(m_handle); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
dispatch_semaphore_t m_handle;
|
||||||
|
};
|
||||||
|
} // namespace Common
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
@ -293,6 +293,7 @@ PUBLIC
|
|||||||
videonull
|
videonull
|
||||||
videoogl
|
videoogl
|
||||||
videosoftware
|
videosoftware
|
||||||
|
videovulkan
|
||||||
|
|
||||||
PRIVATE
|
PRIVATE
|
||||||
${LZO}
|
${LZO}
|
||||||
@ -322,10 +323,6 @@ if(LIBUSB_FOUND)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT APPLE)
|
|
||||||
target_link_libraries(core PUBLIC videovulkan)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_sources(core PRIVATE
|
target_sources(core PRIVATE
|
||||||
HW/EXI/BBA-TAP/TAP_Win32.cpp
|
HW/EXI/BBA-TAP/TAP_Win32.cpp
|
||||||
|
@ -214,6 +214,9 @@ bool Init(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi)
|
|||||||
|
|
||||||
Host_UpdateMainFrame(); // Disable any menus or buttons at boot
|
Host_UpdateMainFrame(); // Disable any menus or buttons at boot
|
||||||
|
|
||||||
|
// Issue any API calls which must occur on the main thread for the graphics backend.
|
||||||
|
g_video_backend->PrepareWindow(wsi);
|
||||||
|
|
||||||
// Start the emu thread
|
// Start the emu thread
|
||||||
s_emu_thread = std::thread(EmuThread, std::move(boot), wsi);
|
s_emu_thread = std::thread(EmuThread, std::move(boot), wsi);
|
||||||
return true;
|
return true;
|
||||||
|
@ -92,15 +92,17 @@ void AdvancedWidget::CreateWidgets()
|
|||||||
|
|
||||||
m_enable_cropping = new GraphicsBool(tr("Crop"), Config::GFX_CROP);
|
m_enable_cropping = new GraphicsBool(tr("Crop"), Config::GFX_CROP);
|
||||||
m_enable_prog_scan = new QCheckBox(tr("Enable Progressive Scan"));
|
m_enable_prog_scan = new QCheckBox(tr("Enable Progressive Scan"));
|
||||||
|
m_backend_multithreading =
|
||||||
|
new GraphicsBool(tr("Backend Multi-threading"), Config::GFX_BACKEND_MULTITHREADING);
|
||||||
|
|
||||||
misc_layout->addWidget(m_enable_cropping, 0, 0);
|
misc_layout->addWidget(m_enable_cropping, 0, 0);
|
||||||
misc_layout->addWidget(m_enable_prog_scan, 0, 1);
|
misc_layout->addWidget(m_enable_prog_scan, 0, 1);
|
||||||
|
misc_layout->addWidget(m_backend_multithreading, 1, 0);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
m_borderless_fullscreen =
|
m_borderless_fullscreen =
|
||||||
new GraphicsBool(tr("Borderless Fullscreen"), Config::GFX_BORDERLESS_FULLSCREEN);
|
new GraphicsBool(tr("Borderless Fullscreen"), Config::GFX_BORDERLESS_FULLSCREEN);
|
||||||
|
|
||||||
misc_layout->addWidget(m_borderless_fullscreen, 1, 0);
|
misc_layout->addWidget(m_borderless_fullscreen, 1, 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
main_layout->addWidget(debugging_box);
|
main_layout->addWidget(debugging_box);
|
||||||
@ -191,6 +193,11 @@ void AdvancedWidget::AddDescriptions()
|
|||||||
static const char TR_PROGRESSIVE_SCAN_DESCRIPTION[] = QT_TR_NOOP(
|
static const char TR_PROGRESSIVE_SCAN_DESCRIPTION[] = QT_TR_NOOP(
|
||||||
"Enables progressive scan if supported by the emulated software.\nMost games don't "
|
"Enables progressive scan if supported by the emulated software.\nMost games don't "
|
||||||
"care about this.\n\nIf unsure, leave this unchecked.");
|
"care about this.\n\nIf unsure, leave this unchecked.");
|
||||||
|
static const char TR_BACKEND_MULTITHREADING_DESCRIPTION[] =
|
||||||
|
QT_TR_NOOP("Enables multi-threaded command submission in backends where supported. Enabling "
|
||||||
|
"this option may result in a performance improvement on systems with more than "
|
||||||
|
"two CPU cores. Currently, this is limited to the Vulkan backend.\n\nIf unsure, "
|
||||||
|
"leave this checked.");
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static const char TR_BORDERLESS_FULLSCREEN_DESCRIPTION[] = QT_TR_NOOP(
|
static const char TR_BORDERLESS_FULLSCREEN_DESCRIPTION[] = QT_TR_NOOP(
|
||||||
"Implement fullscreen mode with a borderless window spanning the whole screen instead of "
|
"Implement fullscreen mode with a borderless window spanning the whole screen instead of "
|
||||||
@ -217,6 +224,7 @@ void AdvancedWidget::AddDescriptions()
|
|||||||
AddDescription(m_enable_cropping, TR_CROPPING_DESCRIPTION);
|
AddDescription(m_enable_cropping, TR_CROPPING_DESCRIPTION);
|
||||||
AddDescription(m_enable_prog_scan, TR_PROGRESSIVE_SCAN_DESCRIPTION);
|
AddDescription(m_enable_prog_scan, TR_PROGRESSIVE_SCAN_DESCRIPTION);
|
||||||
AddDescription(m_enable_freelook, TR_FREE_LOOK_DESCRIPTION);
|
AddDescription(m_enable_freelook, TR_FREE_LOOK_DESCRIPTION);
|
||||||
|
AddDescription(m_backend_multithreading, TR_BACKEND_MULTITHREADING_DESCRIPTION);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
AddDescription(m_borderless_fullscreen, TR_BORDERLESS_FULLSCREEN_DESCRIPTION);
|
AddDescription(m_borderless_fullscreen, TR_BORDERLESS_FULLSCREEN_DESCRIPTION);
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,5 +44,6 @@ private:
|
|||||||
// Misc
|
// Misc
|
||||||
QCheckBox* m_enable_cropping;
|
QCheckBox* m_enable_cropping;
|
||||||
QCheckBox* m_enable_prog_scan;
|
QCheckBox* m_enable_prog_scan;
|
||||||
|
QCheckBox* m_backend_multithreading;
|
||||||
QCheckBox* m_borderless_fullscreen;
|
QCheckBox* m_borderless_fullscreen;
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
add_subdirectory(OGL)
|
add_subdirectory(OGL)
|
||||||
add_subdirectory(Null)
|
add_subdirectory(Null)
|
||||||
add_subdirectory(Software)
|
add_subdirectory(Software)
|
||||||
|
add_subdirectory(Vulkan)
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
add_subdirectory(D3D)
|
add_subdirectory(D3D)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT APPLE)
|
|
||||||
add_subdirectory(Vulkan)
|
|
||||||
endif()
|
|
||||||
|
@ -118,6 +118,19 @@ VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, void* display_h
|
|||||||
|
|
||||||
return surface;
|
return surface;
|
||||||
|
|
||||||
|
#elif defined(VK_USE_PLATFORM_MACOS_MVK)
|
||||||
|
VkMacOSSurfaceCreateInfoMVK surface_create_info = {
|
||||||
|
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, nullptr, 0, hwnd};
|
||||||
|
|
||||||
|
VkSurfaceKHR surface;
|
||||||
|
VkResult res = vkCreateMacOSSurfaceMVK(instance, &surface_create_info, nullptr, &surface);
|
||||||
|
if (res != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
LOG_VULKAN_ERROR(res, "vkCreateMacOSSurfaceMVK failed: ");
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return surface;
|
||||||
#else
|
#else
|
||||||
return VK_NULL_HANDLE;
|
return VK_NULL_HANDLE;
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,5 +18,6 @@ public:
|
|||||||
std::string GetName() const override { return "Vulkan"; }
|
std::string GetName() const override { return "Vulkan"; }
|
||||||
std::string GetDisplayName() const override { return _trans("Vulkan"); }
|
std::string GetDisplayName() const override { return _trans("Vulkan"); }
|
||||||
void InitBackendInfo() override;
|
void InitBackendInfo() override;
|
||||||
|
void PrepareWindow(const WindowSystemInfo& wsi) override;
|
||||||
};
|
};
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@ -186,6 +186,9 @@ bool VulkanContext::SelectInstanceExtensions(ExtensionList* extension_list, bool
|
|||||||
#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
|
#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
|
||||||
if (enable_surface && !SupportsExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, true))
|
if (enable_surface && !SupportsExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, true))
|
||||||
return false;
|
return false;
|
||||||
|
#elif defined(VK_USE_PLATFORM_MACOS_MVK)
|
||||||
|
if (enable_surface && !SupportsExtension(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, true))
|
||||||
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// VK_EXT_debug_report
|
// VK_EXT_debug_report
|
||||||
@ -833,6 +836,13 @@ void VulkanContext::InitDriverDetails()
|
|||||||
driver = DriverDetails::DRIVER_UNKNOWN;
|
driver = DriverDetails::DRIVER_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
// Vulkan on macOS goes through Metal, and is not susceptible to the same bugs
|
||||||
|
// as the vendor's native Vulkan drivers. We use a different driver fields to
|
||||||
|
// differentiate MoltenVK.
|
||||||
|
driver = DriverDetails::DRIVER_PORTABILITY;
|
||||||
|
#endif
|
||||||
|
|
||||||
DriverDetails::Init(DriverDetails::API_VULKAN, vendor, driver,
|
DriverDetails::Init(DriverDetails::API_VULKAN, vendor, driver,
|
||||||
static_cast<double>(m_device_properties.driverVersion),
|
static_cast<double>(m_device_properties.driverVersion),
|
||||||
DriverDetails::Family::UNKNOWN);
|
DriverDetails::Family::UNKNOWN);
|
||||||
|
@ -178,6 +178,10 @@ VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceXcbPresentationSupportKHR, false)
|
|||||||
|
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkCreateAndroidSurfaceKHR, false)
|
VULKAN_INSTANCE_ENTRY_POINT(vkCreateAndroidSurfaceKHR, false)
|
||||||
|
|
||||||
|
#elif defined(VK_USE_PLATFORM_MACOS_MVK)
|
||||||
|
|
||||||
|
VULKAN_INSTANCE_ENTRY_POINT(vkCreateMacOSSurfaceMVK, false)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkCreateDebugReportCallbackEXT, false)
|
VULKAN_INSTANCE_ENTRY_POINT(vkCreateDebugReportCallbackEXT, false)
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
#include "Common/CommonFuncs.h"
|
#include "Common/CommonFuncs.h"
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
@ -14,7 +16,8 @@
|
|||||||
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#elif defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR) || \
|
#elif defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR) || \
|
||||||
defined(VK_USE_PLATFORM_ANDROID_KHR) || defined(USE_HEADLESS)
|
defined(VK_USE_PLATFORM_ANDROID_KHR) || defined(VK_USE_PLATFORM_MACOS_MVK) || \
|
||||||
|
defined(USE_HEADLESS)
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -98,7 +101,8 @@ void UnloadVulkanLibrary()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR) || \
|
#elif defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR) || \
|
||||||
defined(VK_USE_PLATFORM_ANDROID_KHR) || defined(USE_HEADLESS)
|
defined(VK_USE_PLATFORM_ANDROID_KHR) || defined(VK_USE_PLATFORM_MACOS_MVK) || \
|
||||||
|
defined(USE_HEADLESS)
|
||||||
|
|
||||||
static void* vulkan_module;
|
static void* vulkan_module;
|
||||||
static std::atomic_int vulkan_module_ref_count = {0};
|
static std::atomic_int vulkan_module_ref_count = {0};
|
||||||
@ -112,15 +116,27 @@ bool LoadVulkanLibrary()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
// Check if a path to a specific Vulkan library has been specified.
|
||||||
|
char* libvulkan_env = getenv("LIBVULKAN_PATH");
|
||||||
|
if (libvulkan_env)
|
||||||
|
vulkan_module = dlopen(libvulkan_env, RTLD_NOW);
|
||||||
|
if (!vulkan_module)
|
||||||
|
{
|
||||||
|
// Use the libvulkan.dylib from the application bundle.
|
||||||
|
std::string path = File::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib";
|
||||||
|
vulkan_module = dlopen(path.c_str(), RTLD_NOW);
|
||||||
|
}
|
||||||
|
#else
|
||||||
// Names of libraries to search. Desktop should use libvulkan.so.1 or libvulkan.so.
|
// Names of libraries to search. Desktop should use libvulkan.so.1 or libvulkan.so.
|
||||||
static const char* search_lib_names[] = {"libvulkan.so.1", "libvulkan.so"};
|
static const char* search_lib_names[] = {"libvulkan.so.1", "libvulkan.so"};
|
||||||
|
|
||||||
for (size_t i = 0; i < ArraySize(search_lib_names); i++)
|
for (size_t i = 0; i < ArraySize(search_lib_names); i++)
|
||||||
{
|
{
|
||||||
vulkan_module = dlopen(search_lib_names[i], RTLD_NOW);
|
vulkan_module = dlopen(search_lib_names[i], RTLD_NOW);
|
||||||
if (vulkan_module)
|
if (vulkan_module)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!vulkan_module)
|
if (!vulkan_module)
|
||||||
{
|
{
|
||||||
@ -164,6 +180,7 @@ void UnloadVulkanLibrary()
|
|||||||
dlclose(vulkan_module);
|
dlclose(vulkan_module);
|
||||||
vulkan_module = nullptr;
|
vulkan_module = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
//#warning Unknown platform, not compiling loader.
|
//#warning Unknown platform, not compiling loader.
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
//#define VK_USE_PLATFORM_XCB_KHR
|
//#define VK_USE_PLATFORM_XCB_KHR
|
||||||
#elif defined(ANDROID)
|
#elif defined(ANDROID)
|
||||||
#define VK_USE_PLATFORM_ANDROID_KHR
|
#define VK_USE_PLATFORM_ANDROID_KHR
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#define VK_USE_PLATFORM_MACOS_MVK
|
||||||
#else
|
#else
|
||||||
//#warning Unknown platform
|
//#warning Unknown platform
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,6 +24,10 @@
|
|||||||
#include "VideoCommon/VideoBackendBase.h"
|
#include "VideoCommon/VideoBackendBase.h"
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
|
#if defined(VK_USE_PLATFORM_MACOS_MVK)
|
||||||
|
#include <objc/message.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Vulkan
|
namespace Vulkan
|
||||||
{
|
{
|
||||||
void VideoBackend::InitBackendInfo()
|
void VideoBackend::InitBackendInfo()
|
||||||
@ -272,4 +276,33 @@ void VideoBackend::Shutdown()
|
|||||||
ShutdownShared();
|
ShutdownShared();
|
||||||
UnloadVulkanLibrary();
|
UnloadVulkanLibrary();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoBackend::PrepareWindow(const WindowSystemInfo& wsi)
|
||||||
|
{
|
||||||
|
#if defined(VK_USE_PLATFORM_MACOS_MVK)
|
||||||
|
// This is kinda messy, but it avoids having to write Objective C++ just to create a metal layer.
|
||||||
|
id view = reinterpret_cast<id>(wsi.render_surface);
|
||||||
|
Class clsCAMetalLayer = objc_getClass("CAMetalLayer");
|
||||||
|
if (!clsCAMetalLayer)
|
||||||
|
{
|
||||||
|
ERROR_LOG(VIDEO, "Failed to get CAMetalLayer class.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [CAMetalLayer layer]
|
||||||
|
id layer = reinterpret_cast<id (*)(Class, SEL)>(objc_msgSend)(objc_getClass("CAMetalLayer"),
|
||||||
|
sel_getUid("layer"));
|
||||||
|
if (!layer)
|
||||||
|
{
|
||||||
|
ERROR_LOG(VIDEO, "Failed to create Metal layer.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [view setWantsLayer:YES]
|
||||||
|
reinterpret_cast<void (*)(id, SEL, BOOL)>(objc_msgSend)(view, sel_getUid("setWantsLayer:"), YES);
|
||||||
|
|
||||||
|
// [view setLayer:layer]
|
||||||
|
reinterpret_cast<void (*)(id, SEL, id)>(objc_msgSend)(view, sel_getUid("setLayer:"), layer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@ -61,6 +61,7 @@ enum Driver
|
|||||||
DRIVER_FREEDRENO, // OSS Adreno driver
|
DRIVER_FREEDRENO, // OSS Adreno driver
|
||||||
DRIVER_IMGTEC, // Official PowerVR driver
|
DRIVER_IMGTEC, // Official PowerVR driver
|
||||||
DRIVER_VIVANTE, // Official Vivante driver
|
DRIVER_VIVANTE, // Official Vivante driver
|
||||||
|
DRIVER_PORTABILITY, // Vulkan via Metal on macOS
|
||||||
DRIVER_UNKNOWN // Unknown driver, default to official hardware driver
|
DRIVER_UNKNOWN // Unknown driver, default to official hardware driver
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -283,4 +284,4 @@ void Init(API api, Vendor vendor, Driver driver, const double version, const Fam
|
|||||||
// Once Vendor and driver version is set, this will return if it has the applicable bug passed to
|
// Once Vendor and driver version is set, this will return if it has the applicable bug passed to
|
||||||
// it.
|
// it.
|
||||||
bool HasBug(Bug bug);
|
bool HasBug(Bug bug);
|
||||||
}
|
} // namespace DriverDetails
|
||||||
|
@ -448,7 +448,7 @@ void WritePixelShaderCommonHeader(ShaderCode& out, APIType ApiType, u32 num_texg
|
|||||||
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
||||||
{
|
{
|
||||||
out.Write("SSBO_BINDING(0) buffer BBox {\n"
|
out.Write("SSBO_BINDING(0) buffer BBox {\n"
|
||||||
"\tint4 bbox_data;\n"
|
"\tint bbox_left, bbox_right, bbox_top, bbox_bottom;\n"
|
||||||
"};\n");
|
"};\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -853,13 +853,21 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const ShaderHostConfig& host
|
|||||||
|
|
||||||
if (uid_data->bounding_box)
|
if (uid_data->bounding_box)
|
||||||
{
|
{
|
||||||
const char* atomic_op =
|
if (ApiType == APIType::D3D)
|
||||||
(ApiType == APIType::OpenGL || ApiType == APIType::Vulkan) ? "atomic" : "Interlocked";
|
{
|
||||||
out.Write("\tif(bbox_data[0] > int(rawpos.x)) %sMin(bbox_data[0], int(rawpos.x));\n"
|
out.Write(
|
||||||
"\tif(bbox_data[1] < int(rawpos.x)) %sMax(bbox_data[1], int(rawpos.x));\n"
|
"\tif(bbox_data[0] > int(rawpos.x)) InterlockedMin(bbox_data[0], int(rawpos.x));\n"
|
||||||
"\tif(bbox_data[2] > int(rawpos.y)) %sMin(bbox_data[2], int(rawpos.y));\n"
|
"\tif(bbox_data[1] < int(rawpos.x)) InterlockedMax(bbox_data[1], int(rawpos.x));\n"
|
||||||
"\tif(bbox_data[3] < int(rawpos.y)) %sMax(bbox_data[3], int(rawpos.y));\n",
|
"\tif(bbox_data[2] > int(rawpos.y)) InterlockedMin(bbox_data[2], int(rawpos.y));\n"
|
||||||
atomic_op, atomic_op, atomic_op, atomic_op);
|
"\tif(bbox_data[3] < int(rawpos.y)) InterlockedMax(bbox_data[3], int(rawpos.y));\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.Write("\tif(bbox_left > int(rawpos.x)) atomicMin(bbox_left, int(rawpos.x));\n"
|
||||||
|
"\tif(bbox_right < int(rawpos.x)) atomicMax(bbox_right, int(rawpos.x));\n"
|
||||||
|
"\tif(bbox_top > int(rawpos.y)) atomicMin(bbox_top, int(rawpos.y));\n"
|
||||||
|
"\tif(bbox_bottom < int(rawpos.y)) atomicMax(bbox_bottom, int(rawpos.y));\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Write("}\n");
|
out.Write("}\n");
|
||||||
|
@ -1239,17 +1239,23 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config,
|
|||||||
|
|
||||||
if (bounding_box)
|
if (bounding_box)
|
||||||
{
|
{
|
||||||
const char* atomic_op =
|
|
||||||
(ApiType == APIType::OpenGL || ApiType == APIType::Vulkan) ? "atomic" : "Interlocked";
|
|
||||||
out.Write(" if (bpmem_bounding_box) {\n");
|
out.Write(" if (bpmem_bounding_box) {\n");
|
||||||
out.Write(" if(bbox_data[0] > int(rawpos.x)) %sMin(bbox_data[0], int(rawpos.x));\n",
|
if (ApiType == APIType::D3D)
|
||||||
atomic_op);
|
{
|
||||||
out.Write(" if(bbox_data[1] < int(rawpos.x)) %sMax(bbox_data[1], int(rawpos.x));\n",
|
out.Write(
|
||||||
atomic_op);
|
" if(bbox_data[0] > int(rawpos.x)) InterlockedMin(bbox_data[0], int(rawpos.x));\n"
|
||||||
out.Write(" if(bbox_data[2] > int(rawpos.y)) %sMin(bbox_data[2], int(rawpos.y));\n",
|
" if(bbox_data[1] < int(rawpos.x)) InterlockedMax(bbox_data[1], int(rawpos.x));\n"
|
||||||
atomic_op);
|
" if(bbox_data[2] > int(rawpos.y)) InterlockedMin(bbox_data[2], int(rawpos.y));\n"
|
||||||
out.Write(" if(bbox_data[3] < int(rawpos.y)) %sMax(bbox_data[3], int(rawpos.y));\n",
|
" if(bbox_data[3] < int(rawpos.y)) InterlockedMax(bbox_data[3], int(rawpos.y));\n");
|
||||||
atomic_op);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.Write("\tif(bbox_left > int(rawpos.x)) atomicMin(bbox_left, int(rawpos.x));\n"
|
||||||
|
"\tif(bbox_right < int(rawpos.x)) atomicMax(bbox_right, int(rawpos.x));\n"
|
||||||
|
"\tif(bbox_top > int(rawpos.y)) atomicMin(bbox_top, int(rawpos.y));\n"
|
||||||
|
"\tif(bbox_bottom < int(rawpos.y)) atomicMax(bbox_bottom, int(rawpos.y));\n");
|
||||||
|
}
|
||||||
|
|
||||||
out.Write(" }\n");
|
out.Write(" }\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1414,4 +1420,4 @@ void EnumeratePixelShaderUids(const std::function<void(const PixelShaderUid&)>&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // namespace UberShader
|
||||||
|
@ -25,9 +25,7 @@
|
|||||||
#include "VideoBackends/Null/VideoBackend.h"
|
#include "VideoBackends/Null/VideoBackend.h"
|
||||||
#include "VideoBackends/OGL/VideoBackend.h"
|
#include "VideoBackends/OGL/VideoBackend.h"
|
||||||
#include "VideoBackends/Software/VideoBackend.h"
|
#include "VideoBackends/Software/VideoBackend.h"
|
||||||
#ifndef __APPLE__
|
|
||||||
#include "VideoBackends/Vulkan/VideoBackend.h"
|
#include "VideoBackends/Vulkan/VideoBackend.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "VideoCommon/AsyncRequests.h"
|
#include "VideoCommon/AsyncRequests.h"
|
||||||
#include "VideoCommon/BPStructs.h"
|
#include "VideoCommon/BPStructs.h"
|
||||||
@ -187,9 +185,7 @@ void VideoBackendBase::PopulateList()
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
g_available_video_backends.push_back(std::make_unique<DX11::VideoBackend>());
|
g_available_video_backends.push_back(std::make_unique<DX11::VideoBackend>());
|
||||||
#endif
|
#endif
|
||||||
#ifndef __APPLE__
|
|
||||||
g_available_video_backends.push_back(std::make_unique<Vulkan::VideoBackend>());
|
g_available_video_backends.push_back(std::make_unique<Vulkan::VideoBackend>());
|
||||||
#endif
|
|
||||||
g_available_video_backends.push_back(std::make_unique<SW::VideoSoftware>());
|
g_available_video_backends.push_back(std::make_unique<SW::VideoSoftware>());
|
||||||
g_available_video_backends.push_back(std::make_unique<Null::VideoBackend>());
|
g_available_video_backends.push_back(std::make_unique<Null::VideoBackend>());
|
||||||
|
|
||||||
|
@ -43,6 +43,10 @@ public:
|
|||||||
virtual std::string GetDisplayName() const { return GetName(); }
|
virtual std::string GetDisplayName() const { return GetName(); }
|
||||||
virtual void InitBackendInfo() = 0;
|
virtual void InitBackendInfo() = 0;
|
||||||
|
|
||||||
|
// Prepares a native window for rendering. This is called on the main thread, or the
|
||||||
|
// thread which owns the window.
|
||||||
|
virtual void PrepareWindow(const WindowSystemInfo& wsi) {}
|
||||||
|
|
||||||
void Video_ExitLoop();
|
void Video_ExitLoop();
|
||||||
|
|
||||||
void Video_BeginField(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u64 ticks);
|
void Video_BeginField(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u64 ticks);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user