metal: create swap chain to manage metal layer

This commit is contained in:
Samuliak 2024-04-05 16:21:39 +02:00
parent 380af618d3
commit 79ff60356d
8 changed files with 115 additions and 29 deletions

View file

@ -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()

View file

@ -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<VideoCommon::ChannelInfo> {
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

View file

@ -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() {}

View file

@ -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

View file

@ -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

View file

@ -7,10 +7,14 @@
#import <QuartzCore/QuartzCore.h>
typedef id<MTLDevice> MTLDevice_t;
typedef id<MTLCommandQueue> MTLCommandQueue_t;
typedef id<MTLCommandBuffer> MTLCommandBuffer_t;
typedef id<MTLTexture> MTLTexture_t;
typedef id<CAMetalDrawable> 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

View file

@ -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;
};

View file

@ -12,17 +12,11 @@ RendererMetal::RendererMetal(Core::Frontend::EmuWindow& emu_window,
Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_,
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
: RendererBase(emu_window, std::move(context_)), device_memory{device_memory_},
gpu{gpu_}, device{},
layer([static_cast<const CAMetalLayer*>(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<const CAMetalLayer*>(render_window.GetWindowInfo().render_surface)),
rasterizer(gpu_, device, swap_chain) {}
RendererMetal::~RendererMetal() {
[layer release];
}
RendererMetal::~RendererMetal() = default;
void RendererMetal::Composite(std::span<const Tegra::FramebufferConfig> framebuffers) {
if (framebuffers.empty()) {
@ -31,20 +25,20 @@ void RendererMetal::Composite(std::span<const Tegra::FramebufferConfig> framebuf
// HACK
@autoreleasepool {
id<CAMetalDrawable> 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<MTLCommandBuffer> commandBuffer = [device.GetCommandQueue() commandBuffer];
id<MTLRenderCommandEncoder> renderEncoder = [commandBuffer
renderCommandEncoderWithDescriptor:renderPassDescriptor];
[renderEncoder endEncoding];
[commandBuffer presentDrawable:drawable];
[commandBuffer commit];
id<MTLCommandBuffer> command_buffer = [device.GetCommandQueue() commandBuffer];
id<MTLRenderCommandEncoder> render_encoder = [command_buffer
renderCommandEncoderWithDescriptor:render_pass_descriptor];
[render_encoder endEncoding];
swap_chain.Present(command_buffer);
[command_buffer commit];
}
gpu.RendererFrameEndNotify();