mirror of https://github.com/AxioDL/boo.git
Initial integration of Metal API
This commit is contained in:
parent
606e3676b1
commit
2be32d6ca4
|
@ -40,6 +40,7 @@ elseif(APPLE)
|
||||||
list(APPEND PLAT_SRCS
|
list(APPEND PLAT_SRCS
|
||||||
lib/mac/ApplicationCocoa.mm
|
lib/mac/ApplicationCocoa.mm
|
||||||
lib/mac/WindowCocoa.mm
|
lib/mac/WindowCocoa.mm
|
||||||
|
lib/mac/CocoaCommon.hpp
|
||||||
lib/inputdev/HIDListenerIOKit.cpp
|
lib/inputdev/HIDListenerIOKit.cpp
|
||||||
lib/inputdev/HIDDeviceIOKit.cpp
|
lib/inputdev/HIDDeviceIOKit.cpp
|
||||||
lib/graphicsdev/Metal.mm)
|
lib/graphicsdev/Metal.mm)
|
||||||
|
@ -50,8 +51,11 @@ elseif(APPLE)
|
||||||
find_library(APPKIT_LIBRARY AppKit)
|
find_library(APPKIT_LIBRARY AppKit)
|
||||||
find_library(IOKIT_LIBRARY IOKit)
|
find_library(IOKIT_LIBRARY IOKit)
|
||||||
find_library(OPENGL_LIBRARY OpenGL)
|
find_library(OPENGL_LIBRARY OpenGL)
|
||||||
|
find_library(METAL_LIBRARY Metal)
|
||||||
|
find_library(QUARTZCORE_LIBRARY QuartzCore)
|
||||||
find_library(COREVIDEO_LIBRARY CoreVideo)
|
find_library(COREVIDEO_LIBRARY CoreVideo)
|
||||||
list(APPEND _BOO_SYS_LIBS ${APPKIT_LIBRARY} ${IOKIT_LIBRARY} ${OPENGL_LIBRARY} ${COREVIDEO_LIBRARY})
|
list(APPEND _BOO_SYS_LIBS ${APPKIT_LIBRARY} ${IOKIT_LIBRARY} ${OPENGL_LIBRARY} ${METAL_LIBRARY}
|
||||||
|
${QUARTZCORE_LIBRARY} ${COREVIDEO_LIBRARY})
|
||||||
else(NOT GEKKO)
|
else(NOT GEKKO)
|
||||||
list(APPEND PLAT_SRCS
|
list(APPEND PLAT_SRCS
|
||||||
lib/x11/ApplicationUnix.cpp
|
lib/x11/ApplicationUnix.cpp
|
||||||
|
|
|
@ -6,17 +6,20 @@
|
||||||
#include "boo/IGraphicsContext.hpp"
|
#include "boo/IGraphicsContext.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
struct MetalContext;
|
||||||
|
|
||||||
class MetalDataFactory : public IGraphicsDataFactory
|
class MetalDataFactory : public IGraphicsDataFactory
|
||||||
{
|
{
|
||||||
IGraphicsContext* m_parent;
|
IGraphicsContext* m_parent;
|
||||||
IGraphicsData* m_deferredData = nullptr;
|
IGraphicsData* m_deferredData = nullptr;
|
||||||
std::unordered_set<IGraphicsData*> m_committedData;
|
std::unordered_set<IGraphicsData*> m_committedData;
|
||||||
|
struct MetalContext* m_ctx;
|
||||||
public:
|
public:
|
||||||
MetalDataFactory(IGraphicsContext* parent);
|
MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx);
|
||||||
~MetalDataFactory() {}
|
~MetalDataFactory() {}
|
||||||
|
|
||||||
Platform platform() const {return PlatformMetal;}
|
Platform platform() const {return PlatformMetal;}
|
||||||
|
@ -36,7 +39,7 @@ public:
|
||||||
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements);
|
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements);
|
||||||
|
|
||||||
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
||||||
size_t texCount, const char** texNames,
|
IVertexFormat* vtxFmt, ITextureR* target,
|
||||||
BlendFactor srcFac, BlendFactor dstFac,
|
BlendFactor srcFac, BlendFactor dstFac,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling);
|
bool depthTest, bool depthWrite, bool backfaceCulling);
|
||||||
|
|
||||||
|
@ -53,14 +56,6 @@ public:
|
||||||
void destroyAllData();
|
void destroyAllData();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MetalContext
|
|
||||||
{
|
|
||||||
struct Window
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GDEV_METAL_HPP
|
#endif // GDEV_METAL_HPP
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "boo/IApplication.hpp"
|
#include "boo/IApplication.hpp"
|
||||||
#include "boo/graphicsdev/Metal.hpp"
|
#include "boo/graphicsdev/Metal.hpp"
|
||||||
|
#include "CocoaCommon.hpp"
|
||||||
|
|
||||||
namespace boo {class ApplicationCocoa;}
|
namespace boo {class ApplicationCocoa;}
|
||||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||||
|
@ -92,6 +93,15 @@ public:
|
||||||
[aboutText setString:@"\nBoo Authors\n\nJackoalan\nAntidote\n"];
|
[aboutText setString:@"\nBoo Authors\n\nJackoalan\nAntidote\n"];
|
||||||
[aboutPanel setContentView:aboutText];
|
[aboutPanel setContentView:aboutText];
|
||||||
appDelegate->aboutPanel = aboutPanel;
|
appDelegate->aboutPanel = aboutPanel;
|
||||||
|
|
||||||
|
/* Determine which graphics API to use */
|
||||||
|
for (const SystemString& arg : args)
|
||||||
|
if (!arg.compare("--metal"))
|
||||||
|
{
|
||||||
|
m_metalCtx.m_dev = MTLCreateSystemDefaultDevice();
|
||||||
|
m_metalCtx.m_q = [m_metalCtx.m_dev.get() newCommandQueue];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EPlatformType getPlatformType() const
|
EPlatformType getPlatformType() const
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef BOO_COCOACOMMON_HPP
|
||||||
|
#define BOO_COCOACOMMON_HPP
|
||||||
|
#if __APPLE__
|
||||||
|
|
||||||
|
#include <Metal/Metal.h>
|
||||||
|
#include <QuartzCore/CAMetalLayer.h>
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class NSPtr
|
||||||
|
{
|
||||||
|
T m_ptr = 0;
|
||||||
|
public:
|
||||||
|
NSPtr() = default;
|
||||||
|
~NSPtr() {[m_ptr release];}
|
||||||
|
NSPtr(T&& recv) : m_ptr(recv) {}
|
||||||
|
NSPtr& operator=(T&& recv) {[m_ptr release]; m_ptr = recv; return *this;}
|
||||||
|
NSPtr(const NSPtr& other) = delete;
|
||||||
|
NSPtr(NSPtr&& other) = default;
|
||||||
|
NSPtr& operator=(const NSPtr& other) = delete;
|
||||||
|
NSPtr& operator=(NSPtr&& other) = default;
|
||||||
|
operator bool() const {return m_ptr != 0;}
|
||||||
|
T get() const {return m_ptr;}
|
||||||
|
void reset() {[m_ptr release]; m_ptr = 0;}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace boo
|
||||||
|
{
|
||||||
|
struct MetalContext
|
||||||
|
{
|
||||||
|
NSPtr<id<MTLDevice>> m_dev;
|
||||||
|
NSPtr<id<MTLCommandQueue>> m_q;
|
||||||
|
struct Window
|
||||||
|
{
|
||||||
|
CAMetalLayer* m_metalLayer = nullptr;
|
||||||
|
};
|
||||||
|
std::unordered_map<IWindow*, Window> m_windows;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __APPLE__
|
||||||
|
#endif // BOO_COCOACOMMON_HPP
|
|
@ -1,6 +1,7 @@
|
||||||
#include "boo/graphicsdev/GL.hpp"
|
#include "boo/graphicsdev/GL.hpp"
|
||||||
#include "boo/graphicsdev/glew.h"
|
#include "boo/graphicsdev/glew.h"
|
||||||
#include "boo/graphicsdev/Metal.hpp"
|
#include "boo/graphicsdev/Metal.hpp"
|
||||||
|
#include "CocoaCommon.hpp"
|
||||||
#import <AppKit/AppKit.h>
|
#import <AppKit/AppKit.h>
|
||||||
#import <CoreVideo/CVDisplayLink.h>
|
#import <CoreVideo/CVDisplayLink.h>
|
||||||
#include "boo/IApplication.hpp"
|
#include "boo/IApplication.hpp"
|
||||||
|
@ -142,6 +143,7 @@ class GraphicsContextCocoaMetal;
|
||||||
@interface GraphicsContextCocoaMetalInternal : NSView
|
@interface GraphicsContextCocoaMetalInternal : NSView
|
||||||
{
|
{
|
||||||
BooCocoaResponder* resp;
|
BooCocoaResponder* resp;
|
||||||
|
boo::MetalContext* m_ctx;
|
||||||
}
|
}
|
||||||
- (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx;
|
- (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx;
|
||||||
@end
|
@end
|
||||||
|
@ -150,7 +152,7 @@ namespace boo
|
||||||
{
|
{
|
||||||
static LogVisor::LogModule Log("boo::WindowCocoa");
|
static LogVisor::LogModule Log("boo::WindowCocoa");
|
||||||
IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent);
|
IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent);
|
||||||
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, MetalContext::Window* windowCtx,
|
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow,
|
||||||
IGraphicsContext* parent);
|
IGraphicsContext* parent);
|
||||||
void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx);
|
void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx);
|
||||||
|
|
||||||
|
@ -297,17 +299,16 @@ class GraphicsContextCocoaMetal : public GraphicsContextCocoa
|
||||||
|
|
||||||
IGraphicsCommandQueue* m_commandQueue = nullptr;
|
IGraphicsCommandQueue* m_commandQueue = nullptr;
|
||||||
IGraphicsDataFactory* m_dataFactory = nullptr;
|
IGraphicsDataFactory* m_dataFactory = nullptr;
|
||||||
MetalContext* m_metalCtx;
|
|
||||||
MetalContext::Window* m_metalWindowCtx;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
MetalContext* m_metalCtx;
|
||||||
|
|
||||||
GraphicsContextCocoaMetal(EGraphicsAPI api, IWindow* parentWindow,
|
GraphicsContextCocoaMetal(EGraphicsAPI api, IWindow* parentWindow,
|
||||||
MetalContext* metalCtx, MetalContext::Window* metalWindowCtx)
|
MetalContext* metalCtx)
|
||||||
: GraphicsContextCocoa(api, PF_RGBA8, parentWindow),
|
: GraphicsContextCocoa(api, PF_RGBA8, parentWindow),
|
||||||
m_metalCtx(metalCtx), m_metalWindowCtx(metalWindowCtx)
|
m_metalCtx(metalCtx)
|
||||||
{
|
{
|
||||||
m_dataFactory = new MetalDataFactory(this);
|
m_dataFactory = new MetalDataFactory(this, metalCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
~GraphicsContextCocoaMetal()
|
~GraphicsContextCocoaMetal()
|
||||||
|
@ -315,6 +316,7 @@ public:
|
||||||
delete m_dataFactory;
|
delete m_dataFactory;
|
||||||
delete m_commandQueue;
|
delete m_commandQueue;
|
||||||
[m_nsContext release];
|
[m_nsContext release];
|
||||||
|
m_metalCtx->m_windows.erase(m_parentWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setCallback(IWindowCallback* cb)
|
void _setCallback(IWindowCallback* cb)
|
||||||
|
@ -341,14 +343,16 @@ public:
|
||||||
|
|
||||||
void initializeContext()
|
void initializeContext()
|
||||||
{
|
{
|
||||||
|
MetalContext::Window& w = m_metalCtx->m_windows[m_parentWindow];
|
||||||
m_nsContext = [[GraphicsContextCocoaMetalInternal alloc] initWithBooContext:this];
|
m_nsContext = [[GraphicsContextCocoaMetalInternal alloc] initWithBooContext:this];
|
||||||
if (!m_nsContext)
|
if (!m_nsContext)
|
||||||
Log.report(LogVisor::FatalError, "unable to make new NSView for Metal");
|
Log.report(LogVisor::FatalError, "unable to make new NSView for Metal");
|
||||||
|
w.m_metalLayer = (CAMetalLayer*)m_nsContext.layer;
|
||||||
[(NSWindow*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext];
|
[(NSWindow*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext];
|
||||||
CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink);
|
CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink);
|
||||||
CVDisplayLinkSetOutputCallback(m_dispLink, (CVDisplayLinkOutputCallback)DLCallback, this);
|
CVDisplayLinkSetOutputCallback(m_dispLink, (CVDisplayLinkOutputCallback)DLCallback, this);
|
||||||
CVDisplayLinkStart(m_dispLink);
|
CVDisplayLinkStart(m_dispLink);
|
||||||
m_commandQueue = _NewMetalCommandQueue(m_metalCtx, m_metalWindowCtx, this);
|
m_commandQueue = _NewMetalCommandQueue(m_metalCtx, m_parentWindow, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void makeCurrent()
|
void makeCurrent()
|
||||||
|
@ -382,12 +386,11 @@ public:
|
||||||
|
|
||||||
IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI api,
|
IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI api,
|
||||||
IWindow* parentWindow,
|
IWindow* parentWindow,
|
||||||
MetalContext* metalCtx,
|
MetalContext* metalCtx)
|
||||||
MetalContext::Window* metalWindowCtx)
|
|
||||||
{
|
{
|
||||||
if (api != IGraphicsContext::API_METAL)
|
if (api != IGraphicsContext::API_METAL)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return new GraphicsContextCocoaMetal(api, parentWindow, metalCtx, metalWindowCtx);
|
return new GraphicsContextCocoaMetal(api, parentWindow, metalCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -881,6 +884,8 @@ static boo::ESpecialKey translateKeycode(short code)
|
||||||
@implementation GraphicsContextCocoaMetalInternal
|
@implementation GraphicsContextCocoaMetalInternal
|
||||||
- (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx
|
- (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx
|
||||||
{
|
{
|
||||||
|
self = [self initWithFrame:NSMakeRect(0, 0, 100, 100)];
|
||||||
|
m_ctx = bctx->m_metalCtx;
|
||||||
resp = [[BooCocoaResponder alloc] initWithBooContext:bctx View:self];
|
resp = [[BooCocoaResponder alloc] initWithBooContext:bctx View:self];
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -891,6 +896,20 @@ static boo::ESpecialKey translateKeycode(short code)
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)wantsLayer
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CALayer*)makeBackingLayer
|
||||||
|
{
|
||||||
|
CAMetalLayer* layer = [CAMetalLayer new];
|
||||||
|
layer.device = m_ctx->m_dev.get();
|
||||||
|
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||||
|
layer.framebufferOnly = NO;
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)acceptsTouchEvents
|
- (BOOL)acceptsTouchEvents
|
||||||
{
|
{
|
||||||
return YES;
|
return YES;
|
||||||
|
@ -924,7 +943,10 @@ public:
|
||||||
dispatch_sync(dispatch_get_main_queue(),
|
dispatch_sync(dispatch_get_main_queue(),
|
||||||
^{
|
^{
|
||||||
m_nsWindow = [[WindowCocoaInternal alloc] initWithBooWindow:this title:title];
|
m_nsWindow = [[WindowCocoaInternal alloc] initWithBooWindow:this title:title];
|
||||||
m_gfxCtx = _GraphicsContextCocoaGLNew(IGraphicsContext::API_OPENGL_3_3, this, lastGLCtx);
|
if (metalCtx->m_dev)
|
||||||
|
m_gfxCtx = _GraphicsContextCocoaMetalNew(IGraphicsContext::API_METAL, this, metalCtx);
|
||||||
|
else
|
||||||
|
m_gfxCtx = _GraphicsContextCocoaGLNew(IGraphicsContext::API_OPENGL_3_3, this, lastGLCtx);
|
||||||
m_gfxCtx->initializeContext();
|
m_gfxCtx->initializeContext();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
#include <boo/graphicsdev/D3D.hpp>
|
#include <boo/graphicsdev/D3D.hpp>
|
||||||
|
#elif __APPLE__
|
||||||
|
#include <boo/graphicsdev/Metal.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
|
@ -336,6 +338,33 @@ struct TestApplicationCallback : IApplicationCallback
|
||||||
pipeline = d3dF->newShaderPipeline(VS, PS, vsCompile, psCompile, vfmt,
|
pipeline = d3dF->newShaderPipeline(VS, PS, vsCompile, psCompile, vfmt,
|
||||||
BlendFactorOne, BlendFactorZero, true, true, false);
|
BlendFactorOne, BlendFactorZero, true, true, false);
|
||||||
}
|
}
|
||||||
|
#elif __APPLE__
|
||||||
|
else if (factory->platform() == IGraphicsDataFactory::PlatformMetal)
|
||||||
|
{
|
||||||
|
MetalDataFactory* metalF = dynamic_cast<MetalDataFactory*>(factory);
|
||||||
|
|
||||||
|
static const char* VS =
|
||||||
|
"struct VertData {float3 in_pos [[ attribute(0) ]]; float2 in_uv [[ attribute(1) ]];};\n"
|
||||||
|
"struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n"
|
||||||
|
"vertex VertToFrag main(VertData v [[ stage_in ]])\n"
|
||||||
|
"{\n"
|
||||||
|
" VertToFrag retval;\n"
|
||||||
|
" retval.out_pos = float4(v.in_pos, 1.0);\n"
|
||||||
|
" retval.out_uv = v.in_uv;\n"
|
||||||
|
" return retval;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static const char* FS =
|
||||||
|
"constexpr sampler samp(address::repeat);\n"
|
||||||
|
"struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n"
|
||||||
|
"fragment float4 main(VertToFrag d [[ stage_in ]], texture2d<float> tex [[ texture(0) ]])\n"
|
||||||
|
"{\n"
|
||||||
|
" return tex.sample(samp, d.out_uv);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
pipeline = metalF->newShaderPipeline(VS, FS, vfmt, self->m_renderTarget,
|
||||||
|
BlendFactorOne, BlendFactorZero, true, true, false);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue