diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fb1f8f..dd4b28a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS") set(ENABLE_VULKAN TRUE) set(ENABLE_DARWIN TRUE) set(ENABLE_IOS TRUE) + set(ENABLE_METAL TRUE) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "tvOS") @@ -46,6 +47,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "tvOS") set(ENABLE_VULKAN TRUE) set(ENABLE_DARWIN TRUE) set(ENABLE_TVOS TRUE) + set(ENABLE_METAL TRUE) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") diff --git a/engine/gfx/metal/include/gfx_metal.hpp b/engine/gfx/metal/include/gfx_metal.hpp index 2bd8013..63ee119 100755 --- a/engine/gfx/metal/include/gfx_metal.hpp +++ b/engine/gfx/metal/include/gfx_metal.hpp @@ -44,6 +44,8 @@ public: GFXPipeline* create_graphics_pipeline(const GFXGraphicsPipelineCreateInfo& info) override; GFXPipeline* create_compute_pipeline(const GFXComputePipelineCreateInfo& info) override; + GFXSize get_alignment(GFXSize size) override; + GFXCommandBuffer* acquire_command_buffer(bool for_presentation_use = false) override; void submit(GFXCommandBuffer* command_buffer, platform::window_ptr window = nullptr) override; @@ -51,7 +53,7 @@ public: private: struct NativeMTLView { platform::window_ptr identifier = nullptr; - CA::MetalDrawable* layer = nullptr; + MTL::PixelFormat format; }; std::vector nativeViews; diff --git a/engine/gfx/metal/src/gfx_metal.cpp b/engine/gfx/metal/src/gfx_metal.cpp index dc51ae6..aec07a6 100755 --- a/engine/gfx/metal/src/gfx_metal.cpp +++ b/engine/gfx/metal/src/gfx_metal.cpp @@ -172,10 +172,7 @@ void GFXMetal::initialize_view(void* native_handle, const platform::window_ptr i NativeMTLView* native = new NativeMTLView(); native->identifier = identifier; - //native->layer = (CAMetalLayer*)native_handle; - //native->layer.device = device; - - //native->layer.allowsNextDrawableTimeout = true; + native->format = (MTL::PixelFormat)platform::initialize_metal_layer(identifier, device); nativeViews.push_back(native); } @@ -426,8 +423,9 @@ MTL::FunctionConstantValues* get_constant_values(GFXShaderConstants constants) { GFXPipeline* GFXMetal::create_graphics_pipeline(const GFXGraphicsPipelineCreateInfo& info) { GFXMetalPipeline* pipeline = new GFXMetalPipeline(); + pipeline->label = info.label; - NS::Error* error = nil; + NS::Error* error = nullptr; MTL::RenderPipelineDescriptor* pipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init(); @@ -552,7 +550,7 @@ GFXPipeline* GFXMetal::create_graphics_pipeline(const GFXGraphicsPipelineCreateI unsigned int i = 0; for(const auto& attachment : metalRenderPass->attachments) { if(attachment != MTL::PixelFormatDepth32Float) { - MTL::RenderPipelineColorAttachmentDescriptor* colorAttachmentDescriptor = MTL::RenderPipelineColorAttachmentDescriptor::alloc()->init(); + MTL::RenderPipelineColorAttachmentDescriptor* colorAttachmentDescriptor = pipelineDescriptor->colorAttachments()->object(i++); colorAttachmentDescriptor->setPixelFormat(attachment); colorAttachmentDescriptor->setBlendingEnabled(info.blending.enable_blending); @@ -562,16 +560,14 @@ GFXPipeline* GFXMetal::create_graphics_pipeline(const GFXGraphicsPipelineCreateI colorAttachmentDescriptor->setSourceAlphaBlendFactor(toBlendFactor(info.blending.src_alpha)); colorAttachmentDescriptor->setDestinationAlphaBlendFactor(toBlendFactor(info.blending.dst_alpha)); - - pipelineDescriptor->colorAttachments()->setObject(colorAttachmentDescriptor, i++); } else { pipelineDescriptor->setDepthAttachmentPixelFormat(MTL::PixelFormatDepth32Float); } } } else { - MTL::RenderPipelineColorAttachmentDescriptor* colorAttachmentDescriptor = MTL::RenderPipelineColorAttachmentDescriptor::alloc()->init(); + MTL::RenderPipelineColorAttachmentDescriptor* colorAttachmentDescriptor = pipelineDescriptor->colorAttachments()->object(0); - //colorAttachmentDescriptor->setPixelFormat(attachment); [nativeViews[0]->layer pixelFormat]; + colorAttachmentDescriptor->setPixelFormat(nativeViews[0]->format); colorAttachmentDescriptor->setBlendingEnabled(info.blending.enable_blending); colorAttachmentDescriptor->setSourceRGBBlendFactor(toBlendFactor(info.blending.src_rgb)); @@ -579,8 +575,6 @@ GFXPipeline* GFXMetal::create_graphics_pipeline(const GFXGraphicsPipelineCreateI colorAttachmentDescriptor->setSourceAlphaBlendFactor(toBlendFactor(info.blending.src_alpha)); colorAttachmentDescriptor->setDestinationAlphaBlendFactor(toBlendFactor(info.blending.dst_alpha)); - - pipelineDescriptor->colorAttachments()->setObject(colorAttachmentDescriptor, 0); } if(debug_enabled) { @@ -601,11 +595,6 @@ GFXPipeline* GFXMetal::create_graphics_pipeline(const GFXGraphicsPipelineCreateI break; } - for(auto& binding : info.shader_input.bindings) { - if(binding.type == GFXBindingType::PushConstant) - pipeline->pushConstantIndex = binding.binding; - } - pipeline->winding_mode = info.rasterization.winding_mode; MTL::DepthStencilDescriptor* depthStencil = MTL::DepthStencilDescriptor::alloc()->init(); @@ -651,7 +640,6 @@ GFXPipeline* GFXMetal::create_compute_pipeline(const GFXComputePipelineCreateInf NS::Error* error = nullptr; - // vertex MTL::Library* computeLibrary; { std::string compute_src; @@ -688,17 +676,20 @@ GFXPipeline* GFXMetal::create_compute_pipeline(const GFXComputePipelineCreateInf pipeline->compute_handle = device->newComputePipelineState(pipelineDescriptor, MTL::PipelineOptionNone, nullptr, &error); if(!pipeline->compute_handle) prism::log("Compute pipeline error: {}", error->debugDescription()->cString(NS::ASCIIStringEncoding)); - - for(auto& binding : info.shader_input.bindings) { - if(binding.type == GFXBindingType::PushConstant) - pipeline->pushConstantIndex = binding.binding; - } computeLibrary->release(); return pipeline; } +GFXSize GFXMetal::get_alignment(GFXSize size) { +#ifdef PLATFORM_MACOS + return (size + 32 / 2) & ~int(32 - 1); +#else + return size; +#endif +} + GFXCommandBuffer* GFXMetal::acquire_command_buffer(bool for_presentation_use) { GFXCommandBuffer* cmdbuf = nullptr; while(cmdbuf == nullptr) { @@ -719,10 +710,13 @@ GFXCommandBuffer* GFXMetal::acquire_command_buffer(bool for_presentation_use) { } void GFXMetal::submit(GFXCommandBuffer* command_buffer, const platform::window_ptr window) { + NS::AutoreleasePool* pPool = NS::AutoreleasePool::alloc()->init(); + NativeMTLView* native = getNativeView(window); - //id drawable = nil; - //if(native != nullptr) - // drawable = [native->layer nextDrawable]; + + CA::MetalDrawable* drawable = nullptr; + if(native != nullptr) + drawable = ((CA::MetalDrawable*)platform::get_next_drawable(window)); MTL::CommandBuffer* commandBuffer = command_queue->commandBuffer(); @@ -747,18 +741,18 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const platform::window_p const auto needEncoder = [&](CurrentEncoder encoder, bool needs_reset = false) { if(encoder != current_encoder || needs_reset) { - if(renderEncoder != nil) + if(renderEncoder != nullptr) renderEncoder->endEncoding(); - if(computeEncoder != nil) + if(computeEncoder != nullptr) computeEncoder->endEncoding(); - if(blitEncoder != nil) + if(blitEncoder != nullptr) blitEncoder->endEncoding(); - renderEncoder = nil; - computeEncoder = nil; - blitEncoder = nil; + renderEncoder = nullptr; + computeEncoder = nullptr; + blitEncoder = nullptr; } if(current_encoder == encoder && !needs_reset) @@ -775,35 +769,29 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const platform::window_p unsigned int i = 0; for(const auto& attachment : currentFramebuffer->attachments) { if(attachment->format == MTL::PixelFormatDepth32Float) { - MTL::RenderPassDepthAttachmentDescriptor* depthAttachment = MTL::RenderPassDepthAttachmentDescriptor::alloc()->init(); + MTL::RenderPassDepthAttachmentDescriptor* depthAttachment = descriptor->depthAttachment(); depthAttachment->setTexture(attachment->handle); depthAttachment->setLoadAction(MTL::LoadActionClear); depthAttachment->setStoreAction(MTL::StoreActionStore); - - descriptor->setDepthAttachment(depthAttachment); } else { - MTL::RenderPassColorAttachmentDescriptor* colorAttachment = MTL::RenderPassColorAttachmentDescriptor::alloc()->init(); + MTL::RenderPassColorAttachmentDescriptor* colorAttachment = descriptor->colorAttachments()->object(i); colorAttachment->setTexture(attachment->handle); colorAttachment->setLoadAction(MTL::LoadActionClear); colorAttachment->setStoreAction(MTL::StoreActionStore); colorAttachment->setClearColor(currentClearColor); - - descriptor->colorAttachments()->setObject(colorAttachment, i++); } } - - renderEncoder = commandBuffer->renderCommandEncoder(descriptor); } else { - MTL::RenderPassColorAttachmentDescriptor* colorAttachment = MTL::RenderPassColorAttachmentDescriptor::alloc()->init(); + MTL::RenderPassColorAttachmentDescriptor* colorAttachment = descriptor->colorAttachments()->object(0); - //colorAttachment->setTexture(attachment->handle); drawable.texture + colorAttachment->setTexture(drawable->texture()); colorAttachment->setLoadAction(MTL::LoadActionClear); colorAttachment->setStoreAction(MTL::StoreActionStore); colorAttachment->setClearColor(currentClearColor); - - descriptor->colorAttachments()->setObject(colorAttachment, 0); } + + renderEncoder = commandBuffer->renderCommandEncoder(descriptor); if(currentViewport.width != 0.0f && currentViewport.height != 0.0f) renderEncoder->setViewport(currentViewport); @@ -833,13 +821,12 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const platform::window_p case GFXCommandType::SetRenderPass: { currentClearColor = MTL::ClearColor(command.data.set_render_pass.clear_color.r, - command.data.set_render_pass.clear_color.g, - command.data.set_render_pass.clear_color.b, - command.data.set_render_pass.clear_color.a ); + command.data.set_render_pass.clear_color.g, + command.data.set_render_pass.clear_color.b, + command.data.set_render_pass.clear_color.a ); currentFramebuffer = (GFXMetalFramebuffer*)command.data.set_render_pass.framebuffer; currentRenderPass = (GFXMetalRenderPass*)command.data.set_render_pass.render_pass; - currentViewport = MTL::Viewport(); needEncoder(CurrentEncoder::Render, true); @@ -849,12 +836,10 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const platform::window_p { needEncoder(CurrentEncoder::Render); - renderEncoder->setRenderPipelineState(((GFXMetalPipeline*)command.data.set_graphics_pipeline.pipeline)->handle); - currentPipeline = (GFXMetalPipeline*)command.data.set_graphics_pipeline.pipeline; - + + renderEncoder->setRenderPipelineState(((GFXMetalPipeline*)command.data.set_graphics_pipeline.pipeline)->handle); renderEncoder->setDepthStencilState(currentPipeline->depthStencil); - renderEncoder->setCullMode(((GFXMetalPipeline*)command.data.set_graphics_pipeline.pipeline)->cullMode); renderEncoder->setFrontFacingWinding(toWinding(((GFXMetalPipeline*)command.data.set_graphics_pipeline.pipeline)->winding_mode)); @@ -1032,7 +1017,7 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const platform::window_p viewport.znear = command.data.set_viewport.viewport.min_depth; viewport.zfar = command.data.set_viewport.viewport.max_depth; - if(renderEncoder != nil) + if(renderEncoder != nullptr) renderEncoder->setViewport(viewport); currentViewport = viewport; @@ -1081,6 +1066,9 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const platform::window_p case CurrentEncoder::Blit: blitEncoder->insertDebugSignpost(NS::String::string(command.data.insert_label.name.data(), NS::ASCIIStringEncoding)); break; + case CurrentEncoder::Compute: + computeEncoder->insertDebugSignpost(NS::String::string(command.data.insert_label.name.data(), NS::ASCIIStringEncoding)); + break; default: break; } @@ -1095,31 +1083,30 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const platform::window_p } } - if(renderEncoder != nil) + if(renderEncoder != nullptr) renderEncoder->endEncoding(); - if(blitEncoder != nil) + if(blitEncoder != nullptr) blitEncoder->endEncoding(); + + if(computeEncoder != nullptr) + computeEncoder->endEncoding(); - /*[commandBuffer addCompletedHandler:^(id _Nonnull) { + commandBuffer->addCompletedHandler([command_buffer](MTL::CommandBuffer* _) { for(auto [i, buffer] : utility::enumerate(command_buffers)) { if(buffer == command_buffer) free_command_buffers[i] = true; } - }]; + }); if(window != nullptr) { - [commandBuffer presentDrawable:drawable]; - [commandBuffer commit]; + commandBuffer->presentDrawable(drawable); + commandBuffer->commit(); currentFrameIndex = (currentFrameIndex + 1) % 3; - } else { - [commandBuffer commit]; - }*/ - - if(window != nullptr) { - } else { commandBuffer->commit(); } + + pPool->release(); } diff --git a/engine/platform/include/platform.hpp b/engine/platform/include/platform.hpp index d1f1a50..3b5494f 100755 --- a/engine/platform/include/platform.hpp +++ b/engine/platform/include/platform.hpp @@ -177,4 +177,10 @@ namespace platform { void begin_text_input(); void end_text_input(); + + // metal specific stuff +#ifdef ENABLE_METAL + unsigned int initialize_metal_layer(window_ptr window, void* device); + void* get_next_drawable(window_ptr window); +#endif } diff --git a/engine/renderer/src/imguipass.cpp b/engine/renderer/src/imguipass.cpp index 3de9a50..9f92ba5 100755 --- a/engine/renderer/src/imguipass.cpp +++ b/engine/renderer/src/imguipass.cpp @@ -91,12 +91,8 @@ void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, RenderTarget& targ command_buffer->set_graphics_pipeline(pipeline); - if(draw_data->TotalVtxCount > 0) { + if(draw_data->TotalVtxCount > 0) update_buffers(target, *draw_data); - - command_buffer->set_vertex_buffer(target.vertex_buffer[target.current_frame], 0, 0); - command_buffer->set_index_buffer(target.index_buffer[target.current_frame], IndexType::UINT16); - } const Matrix4x4 projection = prism::orthographic(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, @@ -142,8 +138,11 @@ void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, RenderTarget& targ scissor.extent.height = (uint32_t)(clip_max.y - clip_min.y); command_buffer->set_scissor(scissor); + + command_buffer->set_vertex_buffer(target.vertex_buffer[target.current_frame], 0, 0); + command_buffer->set_index_buffer(target.index_buffer[target.current_frame], sizeof(ImDrawIdx) == 2 ? IndexType::UINT16 : IndexType::UINT32); - command_buffer->draw_indexed(pcmd->ElemCount, + command_buffer->draw_indexed(pcmd->ElemCount, (index_offset + pcmd->IdxOffset), (vertex_offset + pcmd->VtxOffset), 0); diff --git a/engine/renderer/src/smaapass.cpp b/engine/renderer/src/smaapass.cpp index 39ce08b..8b9e0f6 100755 --- a/engine/renderer/src/smaapass.cpp +++ b/engine/renderer/src/smaapass.cpp @@ -45,7 +45,6 @@ void SMAAPass::create_render_target_resources(RenderTarget& target) { void SMAAPass::render(GFXCommandBuffer* command_buffer, RenderTarget& target) { GFXRenderPassBeginInfo beginInfo = {}; - beginInfo.clear_color.a = 0.0f; beginInfo.render_area.extent = target.extent; beginInfo.render_pass = render_pass; diff --git a/extern/metal-cpp/src/metal.cpp b/extern/metal-cpp/src/metal.cpp index 7e1ea36..9f1b68a 100644 --- a/extern/metal-cpp/src/metal.cpp +++ b/extern/metal-cpp/src/metal.cpp @@ -1,4 +1,5 @@ #define NS_PRIVATE_IMPLEMENTATION #define CA_PRIVATE_IMPLEMENTATION #define MTL_PRIVATE_IMPLEMENTATION -#include \ No newline at end of file +#include +#include \ No newline at end of file diff --git a/platforms/ios/CMakeLists.txt b/platforms/ios/CMakeLists.txt index 527a7fe..53e33fd 100644 --- a/platforms/ios/CMakeLists.txt +++ b/platforms/ios/CMakeLists.txt @@ -52,7 +52,7 @@ add_platform( ${QUARTZ} ${METAL} ${CORE_GRAPHICS} - GFXVulkan + GFXMetal COMPILE_OPTIONS ) diff --git a/platforms/ios/ViewController.mm.in b/platforms/ios/ViewController.mm.in index e31169f..5121549 100644 --- a/platforms/ios/ViewController.mm.in +++ b/platforms/ios/ViewController.mm.in @@ -1,7 +1,7 @@ #include -#define VK_USE_PLATFORM_METAL_EXT -#include +#include #include +#import "QuartzCore/QuartzCore.hpp" #import @@ -30,7 +30,8 @@ float leftX = 0.0f, leftY = 0.0f; - (void)draw { engine->update(1.0f / (float)maxFPS); engine->begin_frame(1.0f / (float)maxFPS); - engine->render(0); + engine->render((void*)1); + engine->end_frame(); } - (void) controllerConnected { @@ -113,13 +114,17 @@ bool mouse_down = false; int width, height; int drawable_width, drawable_height; +CAMetalLayer* layer; - (void)viewDidLoad { [super viewDidLoad]; view = (GameView*)self.view; view.userInteractionEnabled = true; - + layer = (CAMetalLayer*)view.layer; + CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:view selector:@selector(draw)]; + displayLink.preferredFramesPerSecond = [UIScreen mainScreen].maximumFramesPerSecond; + maxFPS = [UIScreen mainScreen].maximumFramesPerSecond; [displayLink addToRunLoop:NSRunLoop.mainRunLoop forMode:NSDefaultRunLoopMode]; width = [view frame].size.width; @@ -136,13 +141,13 @@ int drawable_width, drawable_height; GFXCreateInfo createInfo = {}; createInfo.api_validation_enabled = true; - GFXVulkan* gfx = new GFXVulkan(); + GFXMetal* gfx = new GFXMetal(); gfx->initialize(createInfo); engine->set_gfx(gfx); app_main(engine); - engine->add_window((void*)CFBridgingRetain([view layer]), 0, {static_cast(width), static_cast(height)}); + engine->add_window((void*)CFBridgingRetain([view layer]), (void*)1, {static_cast(width), static_cast(height)}); app->initialize_render(); @@ -182,16 +187,27 @@ void platform::end_text_input() { } void* platform::create_native_surface(platform::window_ptr index, void* instance) { - VkMetalSurfaceCreateInfoEXT surfaceInfo = {}; + /*VkMetalSurfaceCreateInfoEXT surfaceInfo = {}; surfaceInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; surfaceInfo.pNext = 0; surfaceInfo.flags = 0; - surfaceInfo.pLayer = (CAMetalLayer*)layer; + surfaceInfo.pLayer = layer; VkSurfaceKHR surface; vkCreateMetalSurfaceEXT((VkInstance)instance, &surfaceInfo, nullptr, &surface); - return surface; + return surface;*/ + return nullptr; +} +unsigned int platform::initialize_metal_layer(platform::window_ptr index, void* device) { + layer.device = (__bridge id)device; + layer.allowsNextDrawableTimeout = true; + + return (unsigned int)layer.pixelFormat; +} + +void* platform::get_next_drawable(window_ptr window) { + return (__bridge CA::MetalDrawable*)[layer nextDrawable]; } bool platform::is_main_window(platform::window_ptr index) { @@ -199,7 +215,8 @@ bool platform::is_main_window(platform::window_ptr index) { } std::vector platform::get_native_surface_extension() { - return {VK_EXT_METAL_SURFACE_EXTENSION_NAME}; + //return {VK_EXT_METAL_SURFACE_EXTENSION_NAME}; + return {}; } void platform::show_window(const platform::window_ptr index) { @@ -251,7 +268,7 @@ bool platform::get_key_down(InputButton key) { } platform::window_ptr platform::open_window(const std::string_view title, const prism::Rectangle rect, const WindowFlags flags) { - return 0; + return (void*)1; } void platform::set_window_title(const platform::window_ptr index, const std::string_view title) { diff --git a/platforms/sdl/CMakeLists.txt b/platforms/sdl/CMakeLists.txt index bcf29c2..08531aa 100644 --- a/platforms/sdl/CMakeLists.txt +++ b/platforms/sdl/CMakeLists.txt @@ -4,10 +4,13 @@ if(ENABLE_MACOS) find_library(METAL Metal) set(EXTRA_LIBRARIES GFXMetal ${METAL}) + set(EXTRA_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sdl_metal.mm) endif() add_platform( - SRC ${CMAKE_CURRENT_SOURCE_DIR}/file.cpp + SRC + ${CMAKE_CURRENT_SOURCE_DIR}/file.cpp + ${EXTRA_SRC} MAIN_FILE main.cpp.in EXECUTABLE_PROPERTIES diff --git a/platforms/sdl/main.cpp.in b/platforms/sdl/main.cpp.in index 0525733..d7c6080 100644 --- a/platforms/sdl/main.cpp.in +++ b/platforms/sdl/main.cpp.in @@ -25,6 +25,7 @@ GFX* gfx_interface = nullptr; std::vector windows; +std::map renderers; SDL_Window* main_window = nullptr; SDL_Window* get_window(const platform::window_ptr index) { @@ -126,6 +127,11 @@ platform::window_ptr platform::open_window(const std::string_view title, const p if(windows.size() == 1) main_window = win; + #ifdef ENABLE_METAL + SDL_Renderer* renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + renderers[win] = renderer; + #endif + engine->add_window((void*)win, win, {static_cast(real_width), static_cast(real_height)}); app->initialize_render(); @@ -304,7 +310,7 @@ int main(int argc, char* argv[]) { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER); #ifdef ENABLE_METAL - SDL_setenv("METAL_DEVICE_WRAPPER_TYPE", "1", 0); + SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal"); #endif engine = new prism::engine(argc, argv); diff --git a/platforms/sdl/sdl_metal.mm b/platforms/sdl/sdl_metal.mm new file mode 100644 index 0000000..1bf5123 --- /dev/null +++ b/platforms/sdl/sdl_metal.mm @@ -0,0 +1,40 @@ +#include "platform.hpp" +#import "QuartzCore/QuartzCore.hpp" + +#include +#include + +#import +#import + +extern std::vector windows; +extern std::map renderers; + +SDL_Window* get_window(platform::window_ptr index); +CAMetalLayer* get_layer(platform::window_ptr index) { + return (__bridge CAMetalLayer*)SDL_RenderGetMetalLayer(renderers[get_window(index)]); +} + +// instance == MTL::Device +unsigned int platform::initialize_metal_layer(platform::window_ptr index, void* device) { + auto layer = get_layer(index); + + layer.device = (__bridge id)device; + layer.allowsNextDrawableTimeout = true; + + return (unsigned int)layer.pixelFormat; +} + +void* platform::get_next_drawable(window_ptr window) { + auto renderer = renderers[get_window(window)]; + auto layer = get_layer(window); + + int width, height; + SDL_GetRendererOutputSize(renderer, &width, &height); + layer.drawableSize = CGSizeMake(width, height); + + auto drawable = (__bridge CA::MetalDrawable*)[layer nextDrawable]; + drawable->retain(); + + return drawable; +}