mirror of
https://git.suyu.dev/suyu/suyu
synced 2024-12-27 03:42:51 -06:00
metal: add command recorder for command management
This commit is contained in:
parent
79ff60356d
commit
35b751de1b
9 changed files with 150 additions and 22 deletions
|
@ -374,6 +374,7 @@ if (APPLE)
|
|||
)
|
||||
|
||||
list(APPEND sources
|
||||
renderer_metal/mtl_command_recorder.mm
|
||||
renderer_metal/mtl_device.mm
|
||||
renderer_metal/mtl_rasterizer.mm
|
||||
renderer_metal/mtl_swap_chain.mm
|
||||
|
|
50
src/video_core/renderer_metal/mtl_command_recorder.h
Normal file
50
src/video_core/renderer_metal/mtl_command_recorder.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "objc_bridge.h"
|
||||
#include "video_core/renderer_metal/objc_bridge.h"
|
||||
|
||||
namespace Metal {
|
||||
|
||||
class Device;
|
||||
|
||||
enum class EncoderType { Render, Compute, Blit };
|
||||
|
||||
class CommandRecorder {
|
||||
public:
|
||||
CommandRecorder(const Device& device_);
|
||||
~CommandRecorder();
|
||||
|
||||
void BeginRenderPass(MTLRenderPassDescriptor* render_pass_descriptor);
|
||||
|
||||
void RequireComputeEncoder();
|
||||
|
||||
void RequireBlitEncoder();
|
||||
|
||||
void EndEncoding();
|
||||
|
||||
void Present(CAMetalDrawable_t drawable);
|
||||
|
||||
void Submit();
|
||||
|
||||
MTLCommandBuffer_t GetCommandBuffer() {
|
||||
return command_buffer;
|
||||
}
|
||||
|
||||
MTLCommandEncoder_t GetCommandEncoder() {
|
||||
return encoder;
|
||||
}
|
||||
|
||||
private:
|
||||
const Device& device;
|
||||
|
||||
MTLCommandBuffer_t command_buffer = nil;
|
||||
MTLCommandEncoder_t encoder = nil;
|
||||
|
||||
EncoderType encoder_type;
|
||||
|
||||
void RequireCommandBuffer();
|
||||
};
|
||||
|
||||
} // namespace Metal
|
64
src/video_core/renderer_metal/mtl_command_recorder.mm
Normal file
64
src/video_core/renderer_metal/mtl_command_recorder.mm
Normal file
|
@ -0,0 +1,64 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "video_core/renderer_metal/mtl_command_recorder.h"
|
||||
#include "video_core/renderer_metal/mtl_device.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace Metal {
|
||||
|
||||
CommandRecorder::CommandRecorder(const Device& device_) : device(device_) {}
|
||||
|
||||
CommandRecorder::~CommandRecorder() = default;
|
||||
|
||||
void CommandRecorder::BeginRenderPass(MTLRenderPassDescriptor* render_pass_descriptor) {
|
||||
RequireCommandBuffer();
|
||||
EndEncoding();
|
||||
encoder = [command_buffer renderCommandEncoderWithDescriptor:render_pass_descriptor];
|
||||
encoder_type = EncoderType::Render;
|
||||
}
|
||||
|
||||
void CommandRecorder::RequireComputeEncoder() {
|
||||
RequireCommandBuffer();
|
||||
if (!encoder || encoder_type != EncoderType::Compute) {
|
||||
EndEncoding();
|
||||
encoder = [command_buffer computeCommandEncoder];
|
||||
encoder_type = EncoderType::Compute;
|
||||
}
|
||||
}
|
||||
|
||||
void CommandRecorder::RequireBlitEncoder() {
|
||||
RequireCommandBuffer();
|
||||
if (!encoder || encoder_type != EncoderType::Blit) {
|
||||
EndEncoding();
|
||||
encoder = [command_buffer blitCommandEncoder];
|
||||
encoder_type = EncoderType::Blit;
|
||||
}
|
||||
}
|
||||
|
||||
void CommandRecorder::EndEncoding() {
|
||||
if (encoder) {
|
||||
[encoder endEncoding];
|
||||
[encoder release];
|
||||
encoder = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void CommandRecorder::Present(CAMetalDrawable_t drawable) {
|
||||
[command_buffer presentDrawable:drawable];
|
||||
}
|
||||
|
||||
void CommandRecorder::Submit() {
|
||||
EndEncoding();
|
||||
[command_buffer commit];
|
||||
[command_buffer release];
|
||||
command_buffer = nil;
|
||||
}
|
||||
|
||||
void CommandRecorder::RequireCommandBuffer() {
|
||||
if (!command_buffer) {
|
||||
command_buffer = [device.GetCommandQueue() commandBuffer];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Metal
|
|
@ -3,7 +3,6 @@
|
|||
#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"
|
||||
|
|
|
@ -7,23 +7,26 @@
|
|||
namespace Metal {
|
||||
|
||||
class Device;
|
||||
class CommandRecorder;
|
||||
|
||||
class SwapChain {
|
||||
public:
|
||||
SwapChain(const Device& device_, const CAMetalLayer* layer_);
|
||||
SwapChain(const Device& device_, CommandRecorder& command_recorder_,
|
||||
const CAMetalLayer* layer_);
|
||||
~SwapChain();
|
||||
|
||||
void AcquireNextDrawable();
|
||||
|
||||
void Present(MTLCommandBuffer_t command_buffer);
|
||||
void Present();
|
||||
|
||||
MTLTexture_t GetDrawableTexture();
|
||||
|
||||
private:
|
||||
const Device& device;
|
||||
CommandRecorder& command_recorder;
|
||||
const CAMetalLayer* layer;
|
||||
|
||||
CAMetalDrawable_t drawable;
|
||||
CAMetalDrawable_t drawable = nil;
|
||||
};
|
||||
|
||||
} // namespace Metal
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "video_core/renderer_metal/mtl_command_recorder.h"
|
||||
#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]) {
|
||||
SwapChain::SwapChain(const Device& device_, CommandRecorder& command_recorder_,
|
||||
const CAMetalLayer* layer_)
|
||||
: device(device_), command_recorder(command_recorder_), layer([layer_ retain]) {
|
||||
// Give the layer our device
|
||||
layer.device = device.GetDevice();
|
||||
}
|
||||
|
||||
SwapChain::~SwapChain() {
|
||||
if (drawable) {
|
||||
// TODO: should drawable be released?
|
||||
[drawable release];
|
||||
}
|
||||
[layer release];
|
||||
}
|
||||
|
||||
|
@ -19,8 +26,9 @@ void SwapChain::AcquireNextDrawable() {
|
|||
drawable = [layer nextDrawable];
|
||||
}
|
||||
|
||||
void SwapChain::Present(MTLCommandBuffer_t command_buffer) {
|
||||
[command_buffer presentDrawable:drawable];
|
||||
void SwapChain::Present() {
|
||||
command_recorder.EndEncoding();
|
||||
command_recorder.Present(drawable);
|
||||
}
|
||||
|
||||
MTLTexture_t SwapChain::GetDrawableTexture() {
|
||||
|
|
|
@ -8,13 +8,17 @@
|
|||
typedef id<MTLDevice> MTLDevice_t;
|
||||
typedef id<MTLCommandQueue> MTLCommandQueue_t;
|
||||
typedef id<MTLCommandBuffer> MTLCommandBuffer_t;
|
||||
typedef id<MTLCommandEncoder> MTLCommandEncoder_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* MTLCommandEncoder_t;
|
||||
typedef void* MTLTexture_t;
|
||||
typedef void MTLRenderPassDescriptor;
|
||||
typedef void CAMetalLayer;
|
||||
typedef void* CAMetalDrawable_t;
|
||||
#define nil NULL
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "objc_bridge.h"
|
||||
#include "video_core/host1x/gpu_device_memory_manager.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "video_core/renderer_metal/mtl_command_recorder.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"
|
||||
|
@ -50,6 +51,7 @@ private:
|
|||
Tegra::GPU& gpu;
|
||||
|
||||
Device device;
|
||||
CommandRecorder command_recorder;
|
||||
SwapChain swap_chain;
|
||||
|
||||
RasterizerMetal rasterizer;
|
||||
|
|
|
@ -13,7 +13,9 @@ RendererMetal::RendererMetal(Core::Frontend::EmuWindow& emu_window,
|
|||
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
|
||||
: RendererBase(emu_window, std::move(context_)), device_memory{device_memory_},
|
||||
gpu{gpu_}, device{},
|
||||
swap_chain(device, static_cast<const CAMetalLayer*>(render_window.GetWindowInfo().render_surface)),
|
||||
command_recorder(device),
|
||||
swap_chain(device, command_recorder,
|
||||
static_cast<const CAMetalLayer*>(render_window.GetWindowInfo().render_surface)),
|
||||
rasterizer(gpu_, device, swap_chain) {}
|
||||
|
||||
RendererMetal::~RendererMetal() = default;
|
||||
|
@ -24,22 +26,17 @@ void RendererMetal::Composite(std::span<const Tegra::FramebufferConfig> framebuf
|
|||
}
|
||||
|
||||
// HACK
|
||||
@autoreleasepool {
|
||||
swap_chain.AcquireNextDrawable();
|
||||
swap_chain.AcquireNextDrawable();
|
||||
|
||||
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();
|
||||
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> 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];
|
||||
}
|
||||
command_recorder.BeginRenderPass(render_pass_descriptor);
|
||||
swap_chain.Present();
|
||||
command_recorder.Submit();
|
||||
|
||||
gpu.RendererFrameEndNotify();
|
||||
rasterizer.TickFrame();
|
||||
|
|
Loading…
Reference in a new issue