mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-07-02 05:16:19 +12:00
Metal renderer & iOS frontend fixes
This commit is contained in:
parent
630952f36b
commit
adcd03d31e
8 changed files with 71 additions and 36 deletions
|
@ -1,7 +1,9 @@
|
|||
#pragma once
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <QuartzCore/QuartzCore.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void iosCreateEmulator();
|
||||
void iosLoadROM(NSString* pathNS);
|
||||
void iosRunFrame(CAMetalLayer* layer);
|
||||
void iosSetOutputSize(uint32_t width, uint32_t height);
|
|
@ -40,7 +40,13 @@ namespace PICA {
|
|||
};
|
||||
|
||||
void checkForMTLPixelFormatSupport(MTL::Device* device) {
|
||||
if (!device->supportsFamily(MTL::GPUFamilyApple1)) {
|
||||
#ifndef PANDA3DS_IOS_SIMULATOR
|
||||
const bool supportsApple1 = device->supportsFamily(MTL::GPUFamilyApple1);
|
||||
#else
|
||||
// iOS simulator claims to support Apple1, yet doesn't support a bunch of texture formats from it...
|
||||
const bool supportsApple1 = false;
|
||||
#endif
|
||||
if (!supportsApple1) {
|
||||
mtlPixelFormatInfos[2] = {MTL::PixelFormatRGBA8Unorm, 4, decodeTexelA1BGR5ToRGBA8};
|
||||
mtlPixelFormatInfos[3] = {MTL::PixelFormatRGBA8Unorm, 4, decodeTexelB5G6R5ToRGBA8};
|
||||
mtlPixelFormatInfos[4] = {MTL::PixelFormatRGBA8Unorm, 4, decodeTexelABGR4ToRGBA8};
|
||||
|
|
|
@ -130,7 +130,7 @@ void RendererMTL::display() {
|
|||
// Top screen
|
||||
if (topScreen) {
|
||||
renderCommandEncoder->setViewport(
|
||||
MTL::Viewport{blitInfo.topScreenX, blitInfo.topScreenY + 240 * blitInfo.scale, 400 * blitInfo.scale, 240 * blitInfo.scale, 0.0f, 1.0f}
|
||||
MTL::Viewport{blitInfo.topScreenX, blitInfo.topScreenY, 400 * blitInfo.scale, 240 * blitInfo.scale, 0.0f, 1.0f}
|
||||
);
|
||||
renderCommandEncoder->setFragmentTexture(topScreen->get().texture, 0);
|
||||
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangleStrip, NS::UInteger(0), NS::UInteger(4));
|
||||
|
|
|
@ -10,8 +10,8 @@ struct BasicVertexOut {
|
|||
};
|
||||
|
||||
struct NDCViewport {
|
||||
float2 offset;
|
||||
float2 scale;
|
||||
float2 offset;
|
||||
float2 scale;
|
||||
};
|
||||
|
||||
vertex BasicVertexOut vertexBlit(uint vid [[vertex_id]], constant NDCViewport& viewport [[buffer(0)]]) {
|
||||
|
|
|
@ -33,6 +33,10 @@ IOS_EXPORT void iosRunFrame(CAMetalLayer* layer) {
|
|||
}
|
||||
|
||||
IOS_EXPORT void iosLoadROM(NSString* pathNS) {
|
||||
auto path = std::filesystem::path([pathNS UTF8String]);
|
||||
emulator->loadROM(path);
|
||||
auto path = std::filesystem::path([pathNS UTF8String]);
|
||||
emulator->loadROM(path);
|
||||
}
|
||||
|
||||
IOS_EXPORT void iosSetOutputSize(uint32_t width, uint32_t height) {
|
||||
emulator->setOutputSize(width, height);
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
#pragma once
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <QuartzCore/QuartzCore.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void iosCreateEmulator();
|
||||
void iosLoadROM(NSString* pathNS);
|
||||
void iosRunFrame(CAMetalLayer* layer);
|
||||
void iosSetOutputSize(uint32_t width, uint32_t height);
|
Binary file not shown.
|
@ -3,27 +3,42 @@ import SwiftUI
|
|||
import MetalKit
|
||||
import Darwin
|
||||
|
||||
final class DrawableSize {
|
||||
var width: UInt32 = 0
|
||||
var height: UInt32 = 0
|
||||
var sizeChanged = false
|
||||
}
|
||||
|
||||
var emulatorLock = NSLock()
|
||||
var drawableSize = DrawableSize()
|
||||
|
||||
class ResizeAwareMTKView: MTKView {
|
||||
var onResize: ((CGSize) -> Void)?
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
onResize?(self.drawableSize)
|
||||
}
|
||||
}
|
||||
|
||||
class DocumentViewController: UIViewController, DocumentDelegate {
|
||||
var documentPicker: DocumentPicker!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
/// set up the document picker
|
||||
documentPicker = DocumentPicker(presentationController: self, delegate: self)
|
||||
/// When the view loads (ie user opens the app) show the file picker
|
||||
show()
|
||||
}
|
||||
|
||||
/// callback from the document picker
|
||||
/// Callback from the document picker
|
||||
func didPickDocument(document: Document?) {
|
||||
if let pickedDoc = document {
|
||||
let fileURL = pickedDoc.fileURL
|
||||
|
||||
print("Loading ROM", fileURL)
|
||||
emulatorLock.lock()
|
||||
print(fileURL.path(percentEncoded: false))
|
||||
iosLoadROM(fileURL.path(percentEncoded: false))
|
||||
emulatorLock.unlock()
|
||||
}
|
||||
|
@ -36,25 +51,15 @@ class DocumentViewController: UIViewController, DocumentDelegate {
|
|||
|
||||
struct DocumentView: UIViewControllerRepresentable {
|
||||
func makeUIViewController(context: Context) -> DocumentViewController {
|
||||
return DocumentViewController()
|
||||
DocumentViewController()
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: DocumentViewController, context: Context) {
|
||||
// No update needed
|
||||
}
|
||||
func updateUIViewController(_ uiViewController: DocumentViewController, context: Context) {}
|
||||
}
|
||||
|
||||
struct ContentView: UIViewRepresentable {
|
||||
@State var showFileImporter = true
|
||||
|
||||
/*
|
||||
func makeCoordinator() -> Renderer {
|
||||
Renderer(self)
|
||||
}
|
||||
*/
|
||||
|
||||
func makeUIView(context: UIViewRepresentableContext<ContentView>) -> MTKView {
|
||||
let mtkView = MTKView()
|
||||
func makeUIView(context: Context) -> ResizeAwareMTKView {
|
||||
let mtkView = ResizeAwareMTKView()
|
||||
mtkView.preferredFramesPerSecond = 60
|
||||
mtkView.enableSetNeedsDisplay = true
|
||||
mtkView.isPaused = true
|
||||
|
@ -64,17 +69,34 @@ struct ContentView: UIViewRepresentable {
|
|||
}
|
||||
|
||||
mtkView.framebufferOnly = false
|
||||
mtkView.drawableSize = mtkView.frame.size
|
||||
|
||||
mtkView.onResize = { newDrawableSize in
|
||||
let newWidth = UInt32(newDrawableSize.width)
|
||||
let newHeight = UInt32(newDrawableSize.height)
|
||||
|
||||
emulatorLock.lock()
|
||||
if drawableSize.width != newWidth || drawableSize.height != newHeight {
|
||||
drawableSize.width = newWidth
|
||||
drawableSize.height = newHeight
|
||||
drawableSize.sizeChanged = true
|
||||
}
|
||||
emulatorLock.unlock()
|
||||
}
|
||||
|
||||
let dispatchQueue = DispatchQueue(label: "QueueIdentification", qos: .background)
|
||||
let metalLayer = mtkView.layer as! CAMetalLayer;
|
||||
let metalLayer = mtkView.layer as! CAMetalLayer
|
||||
|
||||
dispatchQueue.async{
|
||||
dispatchQueue.async {
|
||||
iosCreateEmulator()
|
||||
|
||||
while (true) {
|
||||
emulatorLock.lock()
|
||||
iosRunFrame(metalLayer);
|
||||
if drawableSize.sizeChanged {
|
||||
drawableSize.sizeChanged = false
|
||||
iosSetOutputSize(drawableSize.width, drawableSize.height)
|
||||
}
|
||||
|
||||
iosRunFrame(metalLayer)
|
||||
emulatorLock.unlock()
|
||||
}
|
||||
}
|
||||
|
@ -82,14 +104,13 @@ struct ContentView: UIViewRepresentable {
|
|||
return mtkView
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: MTKView, context: UIViewRepresentableContext<ContentView>) {
|
||||
print("Updating MTKView");
|
||||
}
|
||||
func updateUIView(_ uiView: ResizeAwareMTKView, context: Context) {}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
DocumentView();
|
||||
ContentView();
|
||||
DocumentView()
|
||||
ContentView()
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue