mirror of
https://git.suyu.dev/suyu/suyu
synced 2024-12-27 03:42:51 -06:00
metal: create swap chain to manage metal layer
This commit is contained in:
parent
380af618d3
commit
79ff60356d
8 changed files with 115 additions and 29 deletions
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {}
|
||||
|
|
29
src/video_core/renderer_metal/mtl_swap_chain.h
Normal file
29
src/video_core/renderer_metal/mtl_swap_chain.h
Normal 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
|
30
src/video_core/renderer_metal/mtl_swap_chain.mm
Normal file
30
src/video_core/renderer_metal/mtl_swap_chain.mm
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -13,16 +13,10 @@ 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{},
|
||||
layer([static_cast<const CAMetalLayer*>(render_window.GetWindowInfo().render_surface)
|
||||
retain]),
|
||||
rasterizer(gpu_, device, layer) {
|
||||
// Give the layer our device
|
||||
layer.device = device.GetDevice();
|
||||
}
|
||||
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();
|
||||
|
|
Loading…
Reference in a new issue