forked from MeloNX/MeloNX
Put everything on the main thread for testing.
This commit is contained in:
parent
60cfb86774
commit
02901a5a14
Binary file not shown.
@ -41,20 +41,23 @@ struct ContentView: View {
|
|||||||
ZStack {
|
ZStack {
|
||||||
if let gameUrl, emulationStarted {
|
if let gameUrl, emulationStarted {
|
||||||
VulkanSDLViewRepresentable { displayid in
|
VulkanSDLViewRepresentable { displayid in
|
||||||
gameUrl.startAccessingSecurityScopedResource()
|
DispatchQueue.main.async {
|
||||||
|
|
||||||
let config = RyujinxEmulator.Configuration(
|
gameUrl.startAccessingSecurityScopedResource()
|
||||||
inputPath: gameUrl.path,
|
|
||||||
mainThread: mainThread,
|
let config = RyujinxEmulator.Configuration(
|
||||||
graphicsBackend: "Vulkan",
|
inputPath: gameUrl.path,
|
||||||
additionalArgs: [
|
mainThread: mainThread,
|
||||||
"--display-id", String(displayid),
|
graphicsBackend: "Vulkan",
|
||||||
"--fullscreen", "true"
|
additionalArgs: [
|
||||||
]
|
"--display-id", String(displayid),
|
||||||
)
|
"--fullscreen", "true"
|
||||||
|
]
|
||||||
|
)
|
||||||
showVirtualController(url: gameUrl, ryuconfig: config)
|
|
||||||
|
|
||||||
|
showVirtualController(url: gameUrl, ryuconfig: config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,32 +113,38 @@ func startEmulation(game: URL, config: RyujinxEmulator.Configuration) {
|
|||||||
|
|
||||||
let config = config
|
let config = config
|
||||||
|
|
||||||
// patchMakeKeyAndVisible()
|
patchMakeKeyAndVisible()
|
||||||
// SDL_Init(SDL_INIT_VIDEO)
|
// SDL_Init(SDL_INIT_VIDEO)
|
||||||
|
DispatchQueue.main.async {
|
||||||
let emulator = RyujinxEmulator()
|
let emulator = RyujinxEmulator()
|
||||||
do {
|
do {
|
||||||
try emulator.startWithRunLoop(config: config)
|
try emulator.startWithRunLoop(config: config)
|
||||||
} catch {
|
} catch {
|
||||||
print(error)
|
print(error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func patchMakeKeyAndVisible() {
|
func patchMakeKeyAndVisible() {
|
||||||
let uiwindowClass = UIWindow.self
|
DispatchQueue.main.async {
|
||||||
let m1 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.makeKeyAndVisible))!
|
let uiwindowClass = UIWindow.self
|
||||||
let m2 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.wdb_makeKeyAndVisible))!
|
let m1 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.makeKeyAndVisible))!
|
||||||
method_exchangeImplementations(m1, m2)
|
let m2 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.wdb_makeKeyAndVisible))!
|
||||||
|
method_exchangeImplementations(m1, m2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension UIWindow {
|
extension UIWindow {
|
||||||
@objc func wdb_makeKeyAndVisible() {
|
@objc func wdb_makeKeyAndVisible() {
|
||||||
print("Making window key and visible...")
|
DispatchQueue.main.async {
|
||||||
if #available(iOS 13.0, *) {
|
|
||||||
self.windowScene = (UIApplication.shared.connectedScenes.first! as! UIWindowScene)
|
print("Making window key and visible...")
|
||||||
|
if #available(iOS 13.0, *) {
|
||||||
|
self.windowScene = (UIApplication.shared.connectedScenes.first! as! UIWindowScene)
|
||||||
|
}
|
||||||
|
self.wdb_makeKeyAndVisible()
|
||||||
|
theWindow = self
|
||||||
}
|
}
|
||||||
self.wdb_makeKeyAndVisible()
|
|
||||||
theWindow = self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,15 +152,20 @@ extension UIWindow {
|
|||||||
var g_gcVirtualController: GCVirtualController!
|
var g_gcVirtualController: GCVirtualController!
|
||||||
@available(iOS 15.0, *)
|
@available(iOS 15.0, *)
|
||||||
func showVirtualController(url: URL, ryuconfig: RyujinxEmulator.Configuration) {
|
func showVirtualController(url: URL, ryuconfig: RyujinxEmulator.Configuration) {
|
||||||
print("Showing virtual controller...")
|
DispatchQueue.main.async {
|
||||||
let config = GCVirtualController.Configuration()
|
|
||||||
config.elements = [
|
print("Showing virtual controller...")
|
||||||
GCInputDirectionalDpad, GCInputButtonA, GCInputButtonB, GCInputButtonX, GCInputButtonY,
|
let config = GCVirtualController.Configuration()
|
||||||
]
|
config.elements = [
|
||||||
g_gcVirtualController = GCVirtualController(configuration: config)
|
GCInputDirectionalDpad, GCInputButtonA, GCInputButtonB, GCInputButtonX, GCInputButtonY,
|
||||||
g_gcVirtualController.connect { err in
|
]
|
||||||
print("Controller connect: \(String(describing: err))")
|
g_gcVirtualController = GCVirtualController(configuration: config)
|
||||||
startEmulation(game: url, config: ryuconfig)
|
g_gcVirtualController.connect { err in
|
||||||
|
print("Controller connect: \(String(describing: err))")
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
startEmulation(game: url, config: ryuconfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +98,16 @@ class RyujinxEmulator {
|
|||||||
|
|
||||||
isRunning = true
|
isRunning = true
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
do {
|
||||||
|
try Self.start(with: config)
|
||||||
|
} catch {
|
||||||
|
Self.log("Emulation failed to start: \(error)")
|
||||||
|
self.isRunning = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
emulationThread = Thread {
|
emulationThread = Thread {
|
||||||
let runLoop = RunLoop.current
|
let runLoop = RunLoop.current
|
||||||
|
|
||||||
@ -105,6 +115,7 @@ class RyujinxEmulator {
|
|||||||
runLoop.add(port, forMode: .default)
|
runLoop.add(port, forMode: .default)
|
||||||
|
|
||||||
print(config.mainThread ? "Running on the main thread" : "Running on the background thread")
|
print(config.mainThread ? "Running on the main thread" : "Running on the background thread")
|
||||||
|
/*
|
||||||
if config.mainThread {
|
if config.mainThread {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
do {
|
do {
|
||||||
@ -124,6 +135,8 @@ class RyujinxEmulator {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -138,7 +151,7 @@ class RyujinxEmulator {
|
|||||||
emulationThread?.name = "RyujinxEmulationThread"
|
emulationThread?.name = "RyujinxEmulationThread"
|
||||||
emulationThread?.qualityOfService = .userInteractive
|
emulationThread?.qualityOfService = .userInteractive
|
||||||
emulationThread?.threadPriority = 0.9
|
emulationThread?.threadPriority = 0.9
|
||||||
emulationThread?.start()
|
// emulationThread?.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func quickStart(romPath: String) throws {
|
func quickStart(romPath: String) throws {
|
||||||
|
@ -18,8 +18,11 @@ struct VulkanSDLViewRepresentable: UIViewRepresentable {
|
|||||||
let configure: (Uint32) -> Void
|
let configure: (Uint32) -> Void
|
||||||
func makeUIView(context: Context) -> VulkanSDLView {
|
func makeUIView(context: Context) -> VulkanSDLView {
|
||||||
let view = VulkanSDLView(frame: .zero)
|
let view = VulkanSDLView(frame: .zero)
|
||||||
configure(SDL_GetWindowID(view.sdlWindow))
|
DispatchQueue.main.async { [self] in
|
||||||
|
configure(SDL_GetWindowID(view.sdlWindow))
|
||||||
|
}
|
||||||
return view
|
return view
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUIView(_ uiView: VulkanSDLView, context: Context) {
|
func updateUIView(_ uiView: VulkanSDLView, context: Context) {
|
||||||
@ -33,19 +36,24 @@ class VulkanSDLView: UIView {
|
|||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
initializeSDL()
|
DispatchQueue.main.async { [self] in
|
||||||
|
initializeSDL()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
super.init(coder: coder)
|
super.init(coder: coder)
|
||||||
initializeSDL()
|
DispatchQueue.main.async { [self] in
|
||||||
|
initializeSDL()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func initializeSDL() {
|
private func initializeSDL() {
|
||||||
// Initialize SDL with video support
|
// Initialize SDL with video support
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Create an SDL window with Metal support
|
// Create an SDL window with Metal support
|
||||||
DispatchQueue.main.async { [self] in
|
DispatchQueue.main.async { [self] in
|
||||||
sdlWindow = SDL_CreateWindow(
|
sdlWindow = SDL_CreateWindow(
|
||||||
@ -57,25 +65,31 @@ class VulkanSDLView: UIView {
|
|||||||
SDL_WINDOW_SHOWN.rawValue | SDL_WINDOW_ALLOW_HIGHDPI.rawValue | SDL_WINDOW_VULKAN.rawValue
|
SDL_WINDOW_SHOWN.rawValue | SDL_WINDOW_ALLOW_HIGHDPI.rawValue | SDL_WINDOW_VULKAN.rawValue
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
guard sdlWindow != nil else {
|
guard sdlWindow != nil else {
|
||||||
print("Error creating SDL window: \(String(cString: SDL_GetError()))")
|
print("Error creating SDL window: \(String(cString: SDL_GetError()))")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create SDL Metal view and attach to this UIView
|
// Create SDL Metal view and attach to this UIView
|
||||||
metalView = SDL_Metal_CreateView(sdlWindow)
|
DispatchQueue.main.async { [self] in
|
||||||
if metalView == nil {
|
metalView = SDL_Metal_CreateView(sdlWindow)
|
||||||
print("Failed to create SDL Metal view.")
|
if metalView == nil {
|
||||||
return
|
print("Failed to create SDL Metal view.")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let metalLayerPointer = SDL_Metal_GetLayer(metalView) {
|
if let metalLayerPointer = SDL_Metal_GetLayer(metalView) {
|
||||||
let metalLayer = Unmanaged<CAMetalLayer>.fromOpaque(metalLayerPointer).takeUnretainedValue()
|
let metalLayer = Unmanaged<CAMetalLayer>.fromOpaque(metalLayerPointer).takeUnretainedValue()
|
||||||
metalLayer.device = MTLCreateSystemDefaultDevice()
|
metalLayer.device = MTLCreateSystemDefaultDevice()
|
||||||
metalLayer.pixelFormat = .bgra8Unorm
|
metalLayer.pixelFormat = .bgra8Unorm
|
||||||
layer.addSublayer(metalLayer)
|
DispatchQueue.main.async { [self] in
|
||||||
|
layer.addSublayer(metalLayer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user