forked from suyu/suyu
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
|
list(APPEND sources
|
||||||
|
renderer_metal/mtl_command_recorder.mm
|
||||||
renderer_metal/mtl_device.mm
|
renderer_metal/mtl_device.mm
|
||||||
renderer_metal/mtl_rasterizer.mm
|
renderer_metal/mtl_rasterizer.mm
|
||||||
renderer_metal/mtl_swap_chain.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
|
#pragma once
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "objc_bridge.h"
|
|
||||||
#include "video_core/control/channel_state_cache.h"
|
#include "video_core/control/channel_state_cache.h"
|
||||||
#include "video_core/engines/maxwell_dma.h"
|
#include "video_core/engines/maxwell_dma.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
|
|
|
@ -7,23 +7,26 @@
|
||||||
namespace Metal {
|
namespace Metal {
|
||||||
|
|
||||||
class Device;
|
class Device;
|
||||||
|
class CommandRecorder;
|
||||||
|
|
||||||
class SwapChain {
|
class SwapChain {
|
||||||
public:
|
public:
|
||||||
SwapChain(const Device& device_, const CAMetalLayer* layer_);
|
SwapChain(const Device& device_, CommandRecorder& command_recorder_,
|
||||||
|
const CAMetalLayer* layer_);
|
||||||
~SwapChain();
|
~SwapChain();
|
||||||
|
|
||||||
void AcquireNextDrawable();
|
void AcquireNextDrawable();
|
||||||
|
|
||||||
void Present(MTLCommandBuffer_t command_buffer);
|
void Present();
|
||||||
|
|
||||||
MTLTexture_t GetDrawableTexture();
|
MTLTexture_t GetDrawableTexture();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Device& device;
|
const Device& device;
|
||||||
|
CommandRecorder& command_recorder;
|
||||||
const CAMetalLayer* layer;
|
const CAMetalLayer* layer;
|
||||||
|
|
||||||
CAMetalDrawable_t drawable;
|
CAMetalDrawable_t drawable = nil;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Metal
|
} // namespace Metal
|
||||||
|
|
|
@ -1,16 +1,23 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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_device.h"
|
||||||
#include "video_core/renderer_metal/mtl_swap_chain.h"
|
#include "video_core/renderer_metal/mtl_swap_chain.h"
|
||||||
|
|
||||||
namespace Metal {
|
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
|
// Give the layer our device
|
||||||
layer.device = device.GetDevice();
|
layer.device = device.GetDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
SwapChain::~SwapChain() {
|
SwapChain::~SwapChain() {
|
||||||
|
if (drawable) {
|
||||||
|
// TODO: should drawable be released?
|
||||||
|
[drawable release];
|
||||||
|
}
|
||||||
[layer release];
|
[layer release];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +26,9 @@ void SwapChain::AcquireNextDrawable() {
|
||||||
drawable = [layer nextDrawable];
|
drawable = [layer nextDrawable];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapChain::Present(MTLCommandBuffer_t command_buffer) {
|
void SwapChain::Present() {
|
||||||
[command_buffer presentDrawable:drawable];
|
command_recorder.EndEncoding();
|
||||||
|
command_recorder.Present(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
MTLTexture_t SwapChain::GetDrawableTexture() {
|
MTLTexture_t SwapChain::GetDrawableTexture() {
|
||||||
|
|
|
@ -8,13 +8,17 @@
|
||||||
typedef id<MTLDevice> MTLDevice_t;
|
typedef id<MTLDevice> MTLDevice_t;
|
||||||
typedef id<MTLCommandQueue> MTLCommandQueue_t;
|
typedef id<MTLCommandQueue> MTLCommandQueue_t;
|
||||||
typedef id<MTLCommandBuffer> MTLCommandBuffer_t;
|
typedef id<MTLCommandBuffer> MTLCommandBuffer_t;
|
||||||
|
typedef id<MTLCommandEncoder> MTLCommandEncoder_t;
|
||||||
typedef id<MTLTexture> MTLTexture_t;
|
typedef id<MTLTexture> MTLTexture_t;
|
||||||
typedef id<CAMetalDrawable> CAMetalDrawable_t;
|
typedef id<CAMetalDrawable> CAMetalDrawable_t;
|
||||||
#else
|
#else
|
||||||
typedef void* MTLDevice_t;
|
typedef void* MTLDevice_t;
|
||||||
typedef void* MTLCommandQueue_t;
|
typedef void* MTLCommandQueue_t;
|
||||||
typedef void* MTLCommandBuffer_t;
|
typedef void* MTLCommandBuffer_t;
|
||||||
|
typedef void* MTLCommandEncoder_t;
|
||||||
typedef void* MTLTexture_t;
|
typedef void* MTLTexture_t;
|
||||||
|
typedef void MTLRenderPassDescriptor;
|
||||||
typedef void CAMetalLayer;
|
typedef void CAMetalLayer;
|
||||||
typedef void* CAMetalDrawable_t;
|
typedef void* CAMetalDrawable_t;
|
||||||
|
#define nil NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "objc_bridge.h"
|
#include "objc_bridge.h"
|
||||||
#include "video_core/host1x/gpu_device_memory_manager.h"
|
#include "video_core/host1x/gpu_device_memory_manager.h"
|
||||||
#include "video_core/renderer_base.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_device.h"
|
||||||
#include "video_core/renderer_metal/mtl_rasterizer.h"
|
#include "video_core/renderer_metal/mtl_rasterizer.h"
|
||||||
#include "video_core/renderer_metal/mtl_swap_chain.h"
|
#include "video_core/renderer_metal/mtl_swap_chain.h"
|
||||||
|
@ -50,6 +51,7 @@ private:
|
||||||
Tegra::GPU& gpu;
|
Tegra::GPU& gpu;
|
||||||
|
|
||||||
Device device;
|
Device device;
|
||||||
|
CommandRecorder command_recorder;
|
||||||
SwapChain swap_chain;
|
SwapChain swap_chain;
|
||||||
|
|
||||||
RasterizerMetal rasterizer;
|
RasterizerMetal rasterizer;
|
||||||
|
|
|
@ -13,7 +13,9 @@ RendererMetal::RendererMetal(Core::Frontend::EmuWindow& emu_window,
|
||||||
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
|
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
|
||||||
: RendererBase(emu_window, std::move(context_)), device_memory{device_memory_},
|
: RendererBase(emu_window, std::move(context_)), device_memory{device_memory_},
|
||||||
gpu{gpu_}, device{},
|
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) {}
|
rasterizer(gpu_, device, swap_chain) {}
|
||||||
|
|
||||||
RendererMetal::~RendererMetal() = default;
|
RendererMetal::~RendererMetal() = default;
|
||||||
|
@ -24,22 +26,17 @@ void RendererMetal::Composite(std::span<const Tegra::FramebufferConfig> framebuf
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK
|
// HACK
|
||||||
@autoreleasepool {
|
swap_chain.AcquireNextDrawable();
|
||||||
swap_chain.AcquireNextDrawable();
|
|
||||||
|
|
||||||
MTLRenderPassDescriptor* render_pass_descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
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].clearColor = MTLClearColorMake(1.0, 0.5, 0.0, 1.0);
|
||||||
render_pass_descriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
|
render_pass_descriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||||
render_pass_descriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
|
render_pass_descriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
|
||||||
render_pass_descriptor.colorAttachments[0].texture = swap_chain.GetDrawableTexture();
|
render_pass_descriptor.colorAttachments[0].texture = swap_chain.GetDrawableTexture();
|
||||||
|
|
||||||
id<MTLCommandBuffer> command_buffer = [device.GetCommandQueue() commandBuffer];
|
command_recorder.BeginRenderPass(render_pass_descriptor);
|
||||||
id<MTLRenderCommandEncoder> render_encoder = [command_buffer
|
swap_chain.Present();
|
||||||
renderCommandEncoderWithDescriptor:render_pass_descriptor];
|
command_recorder.Submit();
|
||||||
[render_encoder endEncoding];
|
|
||||||
swap_chain.Present(command_buffer);
|
|
||||||
[command_buffer commit];
|
|
||||||
}
|
|
||||||
|
|
||||||
gpu.RendererFrameEndNotify();
|
gpu.RendererFrameEndNotify();
|
||||||
rasterizer.TickFrame();
|
rasterizer.TickFrame();
|
||||||
|
|
Loading…
Reference in a new issue