From 79ff60356dc754950916d092e9433feacf098b5a Mon Sep 17 00:00:00 2001 From: Samuliak Date: Fri, 5 Apr 2024 16:21:39 +0200 Subject: [PATCH] metal: create swap chain to manage metal layer --- src/video_core/CMakeLists.txt | 1 + .../renderer_metal/mtl_rasterizer.h | 8 +++- .../renderer_metal/mtl_rasterizer.mm | 30 +++++++++++++-- .../renderer_metal/mtl_swap_chain.h | 29 ++++++++++++++ .../renderer_metal/mtl_swap_chain.mm | 30 +++++++++++++++ src/video_core/renderer_metal/objc_bridge.h | 4 ++ .../renderer_metal/renderer_metal.h | 4 +- .../renderer_metal/renderer_metal.mm | 38 ++++++++----------- 8 files changed, 115 insertions(+), 29 deletions(-) create mode 100644 src/video_core/renderer_metal/mtl_swap_chain.h create mode 100644 src/video_core/renderer_metal/mtl_swap_chain.mm diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 4b1a9e7503..38e2e68ef8 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -376,6 +376,7 @@ if (APPLE) list(APPEND sources renderer_metal/mtl_device.mm renderer_metal/mtl_rasterizer.mm + renderer_metal/mtl_swap_chain.mm renderer_metal/renderer_metal.mm ) endif() diff --git a/src/video_core/renderer_metal/mtl_rasterizer.h b/src/video_core/renderer_metal/mtl_rasterizer.h index 5637e40344..a9479db9c5 100644 --- a/src/video_core/renderer_metal/mtl_rasterizer.h +++ b/src/video_core/renderer_metal/mtl_rasterizer.h @@ -3,6 +3,7 @@ #pragma once #include "common/common_types.h" +#include "objc_bridge.h" #include "video_core/control/channel_state_cache.h" #include "video_core/engines/maxwell_dma.h" #include "video_core/rasterizer_interface.h" @@ -15,6 +16,7 @@ class System; namespace Metal { class Device; +class SwapChain; class RasterizerMetal; @@ -36,7 +38,7 @@ public: class RasterizerMetal final : public VideoCore::RasterizerInterface, protected VideoCommon::ChannelSetupCaches { public: - explicit RasterizerMetal(Tegra::GPU& gpu_, const Device& device_, const CAMetalLayer* layer_); + explicit RasterizerMetal(Tegra::GPU& gpu_, const Device& device_, const SwapChain& swap_chain_); ~RasterizerMetal() override; void Draw(bool is_indexed, u32 instance_count) override; @@ -90,7 +92,9 @@ private: AccelerateDMA accelerate_dma; const Device& device; - const CAMetalLayer* layer; + const SwapChain& swap_chain; + + MTLCommandBuffer_t command_buffer; }; } // namespace Metal diff --git a/src/video_core/renderer_metal/mtl_rasterizer.mm b/src/video_core/renderer_metal/mtl_rasterizer.mm index aa44783bb1..65e4eae2a5 100644 --- a/src/video_core/renderer_metal/mtl_rasterizer.mm +++ b/src/video_core/renderer_metal/mtl_rasterizer.mm @@ -4,6 +4,10 @@ #include "video_core/control/channel_state.h" #include "video_core/host1x/host1x.h" #include "video_core/memory_manager.h" +#include "video_core/buffer_cache/buffer_cache.h" +#include "video_core/engines/draw_manager.h" +#include "video_core/engines/kepler_compute.h" +#include "video_core/engines/maxwell_3d.h" #include "video_core/renderer_metal/mtl_rasterizer.h" #include "video_core/renderer_metal/mtl_device.h" @@ -20,11 +24,31 @@ bool AccelerateDMA::BufferClear(GPUVAddr src_address, u64 amount, u32 value) { return true; } -RasterizerMetal::RasterizerMetal(Tegra::GPU& gpu_, const Device& device_, const CAMetalLayer* layer_) - : gpu{gpu_}, device{device_}, layer{layer_} {} +RasterizerMetal::RasterizerMetal(Tegra::GPU& gpu_, const Device& device_, const SwapChain& swap_chain_) + : gpu{gpu_}, device{device_}, swap_chain{swap_chain_} {} RasterizerMetal::~RasterizerMetal() = default; -void RasterizerMetal::Draw(bool is_indexed, u32 instance_count) {} +void RasterizerMetal::Draw(bool is_indexed, u32 instance_count) { + //const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); + if (is_indexed) { + std::cout << "DrawIndexed" << std::endl; + /*[command_buffer drawIndexedPrimitives:MTLPrimitiveTypeTriangle + indexCount:draw_params.num_indices + indexType:MTLIndexTypeUInt32 + indexBuffer:draw_state.index_buffer + indexBufferOffset:draw_params.first_index * sizeof(u32) + instanceCount:draw_params.num_instances + baseVertex:draw_params.base_vertex + baseInstance:draw_params.base_instance];*/ + //cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances, + // draw_params.first_index, draw_params.base_vertex, + // draw_params.base_instance); + } else { + std::cout << "Draw" << std::endl; + //cmdbuf.Draw(draw_params.num_vertices, draw_params.num_instances, + // draw_params.base_vertex, draw_params.base_instance); + } +} void RasterizerMetal::DrawTexture() {} void RasterizerMetal::Clear(u32 layer_count) {} void RasterizerMetal::DispatchCompute() {} diff --git a/src/video_core/renderer_metal/mtl_swap_chain.h b/src/video_core/renderer_metal/mtl_swap_chain.h new file mode 100644 index 0000000000..d923896676 --- /dev/null +++ b/src/video_core/renderer_metal/mtl_swap_chain.h @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "video_core/renderer_metal/objc_bridge.h" + +namespace Metal { + +class Device; + +class SwapChain { +public: + SwapChain(const Device& device_, const CAMetalLayer* layer_); + ~SwapChain(); + + void AcquireNextDrawable(); + + void Present(MTLCommandBuffer_t command_buffer); + + MTLTexture_t GetDrawableTexture(); + +private: + const Device& device; + const CAMetalLayer* layer; + + CAMetalDrawable_t drawable; +}; + +} // namespace Metal diff --git a/src/video_core/renderer_metal/mtl_swap_chain.mm b/src/video_core/renderer_metal/mtl_swap_chain.mm new file mode 100644 index 0000000000..4158ddcc7c --- /dev/null +++ b/src/video_core/renderer_metal/mtl_swap_chain.mm @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "video_core/renderer_metal/mtl_device.h" +#include "video_core/renderer_metal/mtl_swap_chain.h" + +namespace Metal { + +SwapChain::SwapChain(const Device& device_, const CAMetalLayer* layer_) : device(device_), layer([layer_ retain]) { + // Give the layer our device + layer.device = device.GetDevice(); +} + +SwapChain::~SwapChain() { + [layer release]; +} + +void SwapChain::AcquireNextDrawable() { + // Get the next drawable + drawable = [layer nextDrawable]; +} + +void SwapChain::Present(MTLCommandBuffer_t command_buffer) { + [command_buffer presentDrawable:drawable]; +} + +MTLTexture_t SwapChain::GetDrawableTexture() { + return drawable.texture; +} + +} // namespace Metal diff --git a/src/video_core/renderer_metal/objc_bridge.h b/src/video_core/renderer_metal/objc_bridge.h index 5fd55169c3..0e4493ffa0 100644 --- a/src/video_core/renderer_metal/objc_bridge.h +++ b/src/video_core/renderer_metal/objc_bridge.h @@ -7,10 +7,14 @@ #import typedef id MTLDevice_t; typedef id MTLCommandQueue_t; +typedef id MTLCommandBuffer_t; typedef id MTLTexture_t; +typedef id CAMetalDrawable_t; #else typedef void* MTLDevice_t; typedef void* MTLCommandQueue_t; +typedef void* MTLCommandBuffer_t; typedef void* MTLTexture_t; typedef void CAMetalLayer; +typedef void* CAMetalDrawable_t; #endif diff --git a/src/video_core/renderer_metal/renderer_metal.h b/src/video_core/renderer_metal/renderer_metal.h index 852964d5bf..888faa8149 100644 --- a/src/video_core/renderer_metal/renderer_metal.h +++ b/src/video_core/renderer_metal/renderer_metal.h @@ -10,6 +10,7 @@ #include "video_core/renderer_base.h" #include "video_core/renderer_metal/mtl_device.h" #include "video_core/renderer_metal/mtl_rasterizer.h" +#include "video_core/renderer_metal/mtl_swap_chain.h" namespace Core { class TelemetrySession; @@ -49,8 +50,7 @@ private: Tegra::GPU& gpu; Device device; - // TODO: use the layer to get the drawable when drawing directly to the screen - const CAMetalLayer* layer; + SwapChain swap_chain; RasterizerMetal rasterizer; }; diff --git a/src/video_core/renderer_metal/renderer_metal.mm b/src/video_core/renderer_metal/renderer_metal.mm index 6009eed606..82f3dbefb7 100644 --- a/src/video_core/renderer_metal/renderer_metal.mm +++ b/src/video_core/renderer_metal/renderer_metal.mm @@ -12,17 +12,11 @@ RendererMetal::RendererMetal(Core::Frontend::EmuWindow& emu_window, Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_, std::unique_ptr context_) : RendererBase(emu_window, std::move(context_)), device_memory{device_memory_}, - gpu{gpu_}, device{}, - layer([static_cast(render_window.GetWindowInfo().render_surface) - retain]), - rasterizer(gpu_, device, layer) { - // Give the layer our device - layer.device = device.GetDevice(); -} + gpu{gpu_}, device{}, + swap_chain(device, static_cast(render_window.GetWindowInfo().render_surface)), + rasterizer(gpu_, device, swap_chain) {} -RendererMetal::~RendererMetal() { - [layer release]; -} +RendererMetal::~RendererMetal() = default; void RendererMetal::Composite(std::span framebuffers) { if (framebuffers.empty()) { @@ -31,20 +25,20 @@ void RendererMetal::Composite(std::span framebuf // HACK @autoreleasepool { - id drawable = [layer nextDrawable]; + swap_chain.AcquireNextDrawable(); - MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; - renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(1.0, 0.5, 0.0, 1.0); - renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; - renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; - renderPassDescriptor.colorAttachments[0].texture = drawable.texture; + MTLRenderPassDescriptor* render_pass_descriptor = [MTLRenderPassDescriptor renderPassDescriptor]; + render_pass_descriptor.colorAttachments[0].clearColor = MTLClearColorMake(1.0, 0.5, 0.0, 1.0); + render_pass_descriptor.colorAttachments[0].loadAction = MTLLoadActionClear; + render_pass_descriptor.colorAttachments[0].storeAction = MTLStoreActionStore; + render_pass_descriptor.colorAttachments[0].texture = swap_chain.GetDrawableTexture(); - id commandBuffer = [device.GetCommandQueue() commandBuffer]; - id renderEncoder = [commandBuffer - renderCommandEncoderWithDescriptor:renderPassDescriptor]; - [renderEncoder endEncoding]; - [commandBuffer presentDrawable:drawable]; - [commandBuffer commit]; + id command_buffer = [device.GetCommandQueue() commandBuffer]; + id render_encoder = [command_buffer + renderCommandEncoderWithDescriptor:render_pass_descriptor]; + [render_encoder endEncoding]; + swap_chain.Present(command_buffer); + [command_buffer commit]; } gpu.RendererFrameEndNotify();