Put everything on the main thread for testing.

This commit is contained in:
stossy11 2024-11-02 12:37:08 +11:00
parent 60cfb86774
commit 02901a5a14
4 changed files with 93 additions and 52 deletions

View File

@ -41,20 +41,23 @@ struct ContentView: View {
ZStack {
if let gameUrl, emulationStarted {
VulkanSDLViewRepresentable { displayid in
gameUrl.startAccessingSecurityScopedResource()
let config = RyujinxEmulator.Configuration(
inputPath: gameUrl.path,
mainThread: mainThread,
graphicsBackend: "Vulkan",
additionalArgs: [
"--display-id", String(displayid),
"--fullscreen", "true"
]
)
showVirtualController(url: gameUrl, ryuconfig: config)
DispatchQueue.main.async {
gameUrl.startAccessingSecurityScopedResource()
let config = RyujinxEmulator.Configuration(
inputPath: gameUrl.path,
mainThread: mainThread,
graphicsBackend: "Vulkan",
additionalArgs: [
"--display-id", String(displayid),
"--fullscreen", "true"
]
)
showVirtualController(url: gameUrl, ryuconfig: config)
}
}
}
@ -110,32 +113,38 @@ func startEmulation(game: URL, config: RyujinxEmulator.Configuration) {
let config = config
// patchMakeKeyAndVisible()
patchMakeKeyAndVisible()
// SDL_Init(SDL_INIT_VIDEO)
let emulator = RyujinxEmulator()
do {
try emulator.startWithRunLoop(config: config)
} catch {
print(error)
DispatchQueue.main.async {
let emulator = RyujinxEmulator()
do {
try emulator.startWithRunLoop(config: config)
} catch {
print(error)
}
}
}
func patchMakeKeyAndVisible() {
let uiwindowClass = UIWindow.self
let m1 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.makeKeyAndVisible))!
let m2 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.wdb_makeKeyAndVisible))!
method_exchangeImplementations(m1, m2)
DispatchQueue.main.async {
let uiwindowClass = UIWindow.self
let m1 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.makeKeyAndVisible))!
let m2 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.wdb_makeKeyAndVisible))!
method_exchangeImplementations(m1, m2)
}
}
extension UIWindow {
@objc func wdb_makeKeyAndVisible() {
print("Making window key and visible...")
if #available(iOS 13.0, *) {
self.windowScene = (UIApplication.shared.connectedScenes.first! as! UIWindowScene)
DispatchQueue.main.async {
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!
@available(iOS 15.0, *)
func showVirtualController(url: URL, ryuconfig: RyujinxEmulator.Configuration) {
print("Showing virtual controller...")
let config = GCVirtualController.Configuration()
config.elements = [
GCInputDirectionalDpad, GCInputButtonA, GCInputButtonB, GCInputButtonX, GCInputButtonY,
]
g_gcVirtualController = GCVirtualController(configuration: config)
g_gcVirtualController.connect { err in
print("Controller connect: \(String(describing: err))")
startEmulation(game: url, config: ryuconfig)
DispatchQueue.main.async {
print("Showing virtual controller...")
let config = GCVirtualController.Configuration()
config.elements = [
GCInputDirectionalDpad, GCInputButtonA, GCInputButtonB, GCInputButtonX, GCInputButtonY,
]
g_gcVirtualController = GCVirtualController(configuration: config)
g_gcVirtualController.connect { err in
print("Controller connect: \(String(describing: err))")
DispatchQueue.main.async {
startEmulation(game: url, config: ryuconfig)
}
}
}
}

View File

@ -98,6 +98,16 @@ class RyujinxEmulator {
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 {
let runLoop = RunLoop.current
@ -105,6 +115,7 @@ class RyujinxEmulator {
runLoop.add(port, forMode: .default)
print(config.mainThread ? "Running on the main thread" : "Running on the background thread")
/*
if config.mainThread {
DispatchQueue.main.async {
do {
@ -124,6 +135,8 @@ class RyujinxEmulator {
return
}
}
*/
@ -138,7 +151,7 @@ class RyujinxEmulator {
emulationThread?.name = "RyujinxEmulationThread"
emulationThread?.qualityOfService = .userInteractive
emulationThread?.threadPriority = 0.9
emulationThread?.start()
// emulationThread?.start()
}
func quickStart(romPath: String) throws {

View File

@ -18,8 +18,11 @@ struct VulkanSDLViewRepresentable: UIViewRepresentable {
let configure: (Uint32) -> Void
func makeUIView(context: Context) -> VulkanSDLView {
let view = VulkanSDLView(frame: .zero)
configure(SDL_GetWindowID(view.sdlWindow))
DispatchQueue.main.async { [self] in
configure(SDL_GetWindowID(view.sdlWindow))
}
return view
}
func updateUIView(_ uiView: VulkanSDLView, context: Context) {
@ -33,19 +36,24 @@ class VulkanSDLView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
initializeSDL()
DispatchQueue.main.async { [self] in
initializeSDL()
}
}
required init?(coder: NSCoder) {
super.init(coder: coder)
initializeSDL()
DispatchQueue.main.async { [self] in
initializeSDL()
}
}
private func initializeSDL() {
// Initialize SDL with video support
// Create an SDL window with Metal support
DispatchQueue.main.async { [self] in
sdlWindow = SDL_CreateWindow(
@ -57,25 +65,31 @@ class VulkanSDLView: UIView {
SDL_WINDOW_SHOWN.rawValue | SDL_WINDOW_ALLOW_HIGHDPI.rawValue | SDL_WINDOW_VULKAN.rawValue
)
}
guard sdlWindow != nil else {
print("Error creating SDL window: \(String(cString: SDL_GetError()))")
return
}
// Create SDL Metal view and attach to this UIView
metalView = SDL_Metal_CreateView(sdlWindow)
if metalView == nil {
print("Failed to create SDL Metal view.")
return
DispatchQueue.main.async { [self] in
metalView = SDL_Metal_CreateView(sdlWindow)
if metalView == nil {
print("Failed to create SDL Metal view.")
return
}
}
if let metalLayerPointer = SDL_Metal_GetLayer(metalView) {
let metalLayer = Unmanaged<CAMetalLayer>.fromOpaque(metalLayerPointer).takeUnretainedValue()
metalLayer.device = MTLCreateSystemDefaultDevice()
metalLayer.pixelFormat = .bgra8Unorm
layer.addSublayer(metalLayer)
DispatchQueue.main.async { [self] in
layer.addSublayer(metalLayer)
}
}
}
deinit {