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
|
||||
lib/mac/ApplicationCocoa.mm
|
||||
lib/mac/WindowCocoa.mm
|
||||
lib/mac/CocoaCommon.hpp
|
||||
lib/inputdev/HIDListenerIOKit.cpp
|
||||
lib/inputdev/HIDDeviceIOKit.cpp
|
||||
lib/graphicsdev/Metal.mm)
|
||||
|
@ -50,8 +51,11 @@ elseif(APPLE)
|
|||
find_library(APPKIT_LIBRARY AppKit)
|
||||
find_library(IOKIT_LIBRARY IOKit)
|
||||
find_library(OPENGL_LIBRARY OpenGL)
|
||||
find_library(METAL_LIBRARY Metal)
|
||||
find_library(QUARTZCORE_LIBRARY QuartzCore)
|
||||
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)
|
||||
list(APPEND PLAT_SRCS
|
||||
lib/x11/ApplicationUnix.cpp
|
||||
|
|
|
@ -6,17 +6,20 @@
|
|||
#include "boo/IGraphicsContext.hpp"
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
struct MetalContext;
|
||||
|
||||
class MetalDataFactory : public IGraphicsDataFactory
|
||||
{
|
||||
IGraphicsContext* m_parent;
|
||||
IGraphicsData* m_deferredData = nullptr;
|
||||
std::unordered_set<IGraphicsData*> m_committedData;
|
||||
struct MetalContext* m_ctx;
|
||||
public:
|
||||
MetalDataFactory(IGraphicsContext* parent);
|
||||
MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx);
|
||||
~MetalDataFactory() {}
|
||||
|
||||
Platform platform() const {return PlatformMetal;}
|
||||
|
@ -36,7 +39,7 @@ public:
|
|||
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements);
|
||||
|
||||
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
||||
size_t texCount, const char** texNames,
|
||||
IVertexFormat* vtxFmt, ITextureR* target,
|
||||
BlendFactor srcFac, BlendFactor dstFac,
|
||||
bool depthTest, bool depthWrite, bool backfaceCulling);
|
||||
|
||||
|
@ -53,14 +56,6 @@ public:
|
|||
void destroyAllData();
|
||||
};
|
||||
|
||||
struct MetalContext
|
||||
{
|
||||
struct Window
|
||||
{
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // GDEV_METAL_HPP
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "boo/IApplication.hpp"
|
||||
#include "boo/graphicsdev/Metal.hpp"
|
||||
#include "CocoaCommon.hpp"
|
||||
|
||||
namespace boo {class ApplicationCocoa;}
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
|
@ -92,6 +93,15 @@ public:
|
|||
[aboutText setString:@"\nBoo Authors\n\nJackoalan\nAntidote\n"];
|
||||
[aboutPanel setContentView:aboutText];
|
||||
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
|
||||
|
|
|
@ -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/glew.h"
|
||||
#include "boo/graphicsdev/Metal.hpp"
|
||||
#include "CocoaCommon.hpp"
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <CoreVideo/CVDisplayLink.h>
|
||||
#include "boo/IApplication.hpp"
|
||||
|
@ -142,6 +143,7 @@ class GraphicsContextCocoaMetal;
|
|||
@interface GraphicsContextCocoaMetalInternal : NSView
|
||||
{
|
||||
BooCocoaResponder* resp;
|
||||
boo::MetalContext* m_ctx;
|
||||
}
|
||||
- (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx;
|
||||
@end
|
||||
|
@ -150,7 +152,7 @@ namespace boo
|
|||
{
|
||||
static LogVisor::LogModule Log("boo::WindowCocoa");
|
||||
IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent);
|
||||
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, MetalContext::Window* windowCtx,
|
||||
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow,
|
||||
IGraphicsContext* parent);
|
||||
void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx);
|
||||
|
||||
|
@ -297,17 +299,16 @@ class GraphicsContextCocoaMetal : public GraphicsContextCocoa
|
|||
|
||||
IGraphicsCommandQueue* m_commandQueue = nullptr;
|
||||
IGraphicsDataFactory* m_dataFactory = nullptr;
|
||||
MetalContext* m_metalCtx;
|
||||
MetalContext::Window* m_metalWindowCtx;
|
||||
|
||||
public:
|
||||
|
||||
MetalContext* m_metalCtx;
|
||||
|
||||
GraphicsContextCocoaMetal(EGraphicsAPI api, IWindow* parentWindow,
|
||||
MetalContext* metalCtx, MetalContext::Window* metalWindowCtx)
|
||||
MetalContext* metalCtx)
|
||||
: 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()
|
||||
|
@ -315,6 +316,7 @@ public:
|
|||
delete m_dataFactory;
|
||||
delete m_commandQueue;
|
||||
[m_nsContext release];
|
||||
m_metalCtx->m_windows.erase(m_parentWindow);
|
||||
}
|
||||
|
||||
void _setCallback(IWindowCallback* cb)
|
||||
|
@ -341,14 +343,16 @@ public:
|
|||
|
||||
void initializeContext()
|
||||
{
|
||||
MetalContext::Window& w = m_metalCtx->m_windows[m_parentWindow];
|
||||
m_nsContext = [[GraphicsContextCocoaMetalInternal alloc] initWithBooContext:this];
|
||||
if (!m_nsContext)
|
||||
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];
|
||||
CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink);
|
||||
CVDisplayLinkSetOutputCallback(m_dispLink, (CVDisplayLinkOutputCallback)DLCallback, this);
|
||||
CVDisplayLinkStart(m_dispLink);
|
||||
m_commandQueue = _NewMetalCommandQueue(m_metalCtx, m_metalWindowCtx, this);
|
||||
m_commandQueue = _NewMetalCommandQueue(m_metalCtx, m_parentWindow, this);
|
||||
}
|
||||
|
||||
void makeCurrent()
|
||||
|
@ -382,12 +386,11 @@ public:
|
|||
|
||||
IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI api,
|
||||
IWindow* parentWindow,
|
||||
MetalContext* metalCtx,
|
||||
MetalContext::Window* metalWindowCtx)
|
||||
MetalContext* metalCtx)
|
||||
{
|
||||
if (api != IGraphicsContext::API_METAL)
|
||||
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
|
||||
- (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];
|
||||
return self;
|
||||
}
|
||||
|
@ -891,6 +896,20 @@ static boo::ESpecialKey translateKeycode(short code)
|
|||
[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
|
||||
{
|
||||
return YES;
|
||||
|
@ -924,7 +943,10 @@ public:
|
|||
dispatch_sync(dispatch_get_main_queue(),
|
||||
^{
|
||||
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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#if _WIN32
|
||||
#include <boo/graphicsdev/D3D.hpp>
|
||||
#elif __APPLE__
|
||||
#include <boo/graphicsdev/Metal.hpp>
|
||||
#endif
|
||||
|
||||
namespace boo
|
||||
|
@ -336,6 +338,33 @@ struct TestApplicationCallback : IApplicationCallback
|
|||
pipeline = d3dF->newShaderPipeline(VS, PS, vsCompile, psCompile, vfmt,
|
||||
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
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue