Implement AbstactGfx for Metal

This commit is contained in:
Scott Mansell 2023-01-29 14:55:53 +13:00
parent 89d9ec0a84
commit eaae5b4a45
6 changed files with 95 additions and 106 deletions

View File

@ -2,6 +2,8 @@ add_library(videometal
MRCHelpers.h MRCHelpers.h
MTLBoundingBox.mm MTLBoundingBox.mm
MTLBoundingBox.h MTLBoundingBox.h
MTLGfx.mm
MTLGfx.h
MTLMain.mm MTLMain.mm
MTLObjectCache.h MTLObjectCache.h
MTLObjectCache.mm MTLObjectCache.mm
@ -9,8 +11,6 @@ add_library(videometal
MTLPerfQuery.h MTLPerfQuery.h
MTLPipeline.mm MTLPipeline.mm
MTLPipeline.h MTLPipeline.h
MTLRenderer.mm
MTLRenderer.h
MTLShader.mm MTLShader.mm
MTLShader.h MTLShader.h
MTLStateTracker.mm MTLStateTracker.mm

View File

@ -6,7 +6,7 @@
#include <Metal/Metal.h> #include <Metal/Metal.h>
#include <QuartzCore/QuartzCore.h> #include <QuartzCore/QuartzCore.h>
#include "VideoCommon/RenderBase.h" #include "VideoCommon/AbstractGfx.h"
#include "VideoBackends/Metal/MRCHelpers.h" #include "VideoBackends/Metal/MRCHelpers.h"
@ -15,16 +15,14 @@ namespace Metal
class Framebuffer; class Framebuffer;
class Texture; class Texture;
class Renderer final : public ::Renderer class Gfx final : public ::AbstractGfx
{ {
public: public:
Renderer(MRCOwned<CAMetalLayer*> layer, int width, int height, float layer_scale); Gfx(MRCOwned<CAMetalLayer*> layer);
~Renderer() override; ~Gfx() override;
bool IsHeadless() const override; bool IsHeadless() const override;
bool Initialize() override;
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config, std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config,
std::string_view name) override; std::string_view name) override;
std::unique_ptr<AbstractStagingTexture> std::unique_ptr<AbstractStagingTexture>
@ -49,8 +47,8 @@ public:
void WaitForGPUIdle() override; void WaitForGPUIdle() override;
void OnConfigChanged(u32 bits) override; void OnConfigChanged(u32 bits) override;
void ClearScreen(const MathUtil::Rectangle<int>& rc, bool color_enable, bool alpha_enable, void ClearRegion(const MathUtil::Rectangle<int>& rc, const MathUtil::Rectangle<int>& target_rc,
bool z_enable, u32 color, u32 z) override; bool color_enable, bool alpha_enable, bool z_enable, u32 color, u32 z) override;
void SetPipeline(const AbstractPipeline* pipeline) override; void SetPipeline(const AbstractPipeline* pipeline) override;
void SetFramebuffer(AbstractFramebuffer* framebuffer) override; void SetFramebuffer(AbstractFramebuffer* framebuffer) override;
@ -71,8 +69,8 @@ public:
void BindBackbuffer(const ClearColor& clear_color = {}) override; void BindBackbuffer(const ClearColor& clear_color = {}) override;
void PresentBackbuffer() override; void PresentBackbuffer() override;
protected: // Returns info about the main surface (aka backbuffer)
std::unique_ptr<::BoundingBox> CreateBoundingBox() const override; SurfaceInfo GetSurfaceInfo() const override;
private: private:
MRCOwned<CAMetalLayer*> m_layer; MRCOwned<CAMetalLayer*> m_layer;

View File

@ -1,7 +1,7 @@
// Copyright 2022 Dolphin Emulator Project // Copyright 2022 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "VideoBackends/Metal/MTLRenderer.h" #include "VideoBackends/Metal/MTLGfx.h"
#include "VideoBackends/Metal/MTLBoundingBox.h" #include "VideoBackends/Metal/MTLBoundingBox.h"
#include "VideoBackends/Metal/MTLObjectCache.h" #include "VideoBackends/Metal/MTLObjectCache.h"
@ -16,33 +16,28 @@
#include "VideoCommon/Present.h" #include "VideoCommon/Present.h"
#include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoBackendBase.h"
Metal::Renderer::Renderer(MRCOwned<CAMetalLayer*> layer, int width, int height, float layer_scale) #include <fstream>
: ::Renderer(width, height, layer_scale, Util::ToAbstract([layer pixelFormat])),
m_layer(std::move(layer)) Metal::Gfx::Gfx(MRCOwned<CAMetalLayer*> layer)
: m_layer(std::move(layer))
{ {
UpdateActiveConfig(); UpdateActiveConfig();
[m_layer setDisplaySyncEnabled:g_ActiveConfig.bVSyncActive]; [m_layer setDisplaySyncEnabled:g_ActiveConfig.bVSyncActive];
SetupSurface();
g_state_tracker->FlushEncoders();
} }
Metal::Renderer::~Renderer() = default; Metal::Gfx::~Gfx() = default;
bool Metal::Renderer::IsHeadless() const bool Metal::Gfx::IsHeadless() const
{ {
return m_layer == nullptr; return m_layer == nullptr;
} }
bool Metal::Renderer::Initialize()
{
if (!::Renderer::Initialize())
return false;
SetupSurface();
g_state_tracker->FlushEncoders();
return true;
}
// MARK: Texture Creation // MARK: Texture Creation
std::unique_ptr<AbstractTexture> Metal::Renderer::CreateTexture(const TextureConfig& config, std::unique_ptr<AbstractTexture> Metal::Gfx::CreateTexture(const TextureConfig& config,
std::string_view name) std::string_view name)
{ {
@autoreleasepool @autoreleasepool
@ -78,7 +73,7 @@ std::unique_ptr<AbstractTexture> Metal::Renderer::CreateTexture(const TextureCon
} }
std::unique_ptr<AbstractStagingTexture> std::unique_ptr<AbstractStagingTexture>
Metal::Renderer::CreateStagingTexture(StagingTextureType type, const TextureConfig& config) Metal::Gfx::CreateStagingTexture(StagingTextureType type, const TextureConfig& config)
{ {
@autoreleasepool @autoreleasepool
{ {
@ -99,7 +94,7 @@ Metal::Renderer::CreateStagingTexture(StagingTextureType type, const TextureConf
} }
std::unique_ptr<AbstractFramebuffer> std::unique_ptr<AbstractFramebuffer>
Metal::Renderer::CreateFramebuffer(AbstractTexture* color_attachment, Metal::Gfx::CreateFramebuffer(AbstractTexture* color_attachment,
AbstractTexture* depth_attachment) AbstractTexture* depth_attachment)
{ {
AbstractTexture* const either_attachment = color_attachment ? color_attachment : depth_attachment; AbstractTexture* const either_attachment = color_attachment ? color_attachment : depth_attachment;
@ -111,7 +106,7 @@ Metal::Renderer::CreateFramebuffer(AbstractTexture* color_attachment,
// MARK: Pipeline Creation // MARK: Pipeline Creation
std::unique_ptr<AbstractShader> Metal::Renderer::CreateShaderFromSource(ShaderStage stage, std::unique_ptr<AbstractShader> Metal::Gfx::CreateShaderFromSource(ShaderStage stage,
std::string_view source, std::string_view source,
std::string_view name) std::string_view name)
{ {
@ -125,7 +120,7 @@ std::unique_ptr<AbstractShader> Metal::Renderer::CreateShaderFromSource(ShaderSt
return CreateShaderFromMSL(stage, std::move(*msl), source, name); return CreateShaderFromMSL(stage, std::move(*msl), source, name);
} }
std::unique_ptr<AbstractShader> Metal::Renderer::CreateShaderFromBinary(ShaderStage stage, std::unique_ptr<AbstractShader> Metal::Gfx::CreateShaderFromBinary(ShaderStage stage,
const void* data, const void* data,
size_t length, size_t length,
std::string_view name) std::string_view name)
@ -159,7 +154,7 @@ static NSString* GenericShaderName(ShaderStage stage)
// clang-format on // clang-format on
std::unique_ptr<AbstractShader> Metal::Renderer::CreateShaderFromMSL(ShaderStage stage, std::unique_ptr<AbstractShader> Metal::Gfx::CreateShaderFromMSL(ShaderStage stage,
std::string msl, std::string msl,
std::string_view glsl, std::string_view glsl,
std::string_view name) std::string_view name)
@ -244,7 +239,7 @@ std::unique_ptr<AbstractShader> Metal::Renderer::CreateShaderFromMSL(ShaderStage
} }
std::unique_ptr<NativeVertexFormat> std::unique_ptr<NativeVertexFormat>
Metal::Renderer::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) Metal::Gfx::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
{ {
@autoreleasepool @autoreleasepool
{ {
@ -253,13 +248,13 @@ Metal::Renderer::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_d
} }
std::unique_ptr<AbstractPipeline> std::unique_ptr<AbstractPipeline>
Metal::Renderer::CreatePipeline(const AbstractPipelineConfig& config, const void* cache_data, Metal::Gfx::CreatePipeline(const AbstractPipelineConfig& config, const void* cache_data,
size_t cache_data_length) size_t cache_data_length)
{ {
return g_object_cache->CreatePipeline(config); return g_object_cache->CreatePipeline(config);
} }
void Metal::Renderer::Flush() void Metal::Gfx::Flush()
{ {
@autoreleasepool @autoreleasepool
{ {
@ -267,7 +262,7 @@ void Metal::Renderer::Flush()
} }
} }
void Metal::Renderer::WaitForGPUIdle() void Metal::Gfx::WaitForGPUIdle()
{ {
@autoreleasepool @autoreleasepool
{ {
@ -276,7 +271,7 @@ void Metal::Renderer::WaitForGPUIdle()
} }
} }
void Metal::Renderer::OnConfigChanged(u32 bits) void Metal::Gfx::OnConfigChanged(u32 bits)
{ {
if (bits & CONFIG_CHANGE_BIT_VSYNC) if (bits & CONFIG_CHANGE_BIT_VSYNC)
[m_layer setDisplaySyncEnabled:g_ActiveConfig.bVSyncActive]; [m_layer setDisplaySyncEnabled:g_ActiveConfig.bVSyncActive];
@ -288,14 +283,14 @@ void Metal::Renderer::OnConfigChanged(u32 bits)
} }
} }
void Metal::Renderer::ClearScreen(const MathUtil::Rectangle<int>& rc, bool color_enable, void Metal::Gfx::ClearRegion(const MathUtil::Rectangle<int>& rc,
bool alpha_enable, bool z_enable, u32 color, u32 z) const MathUtil::Rectangle<int>& target_rc,
bool color_enable, bool alpha_enable, bool z_enable, u32 color, u32 z)
{ {
MathUtil::Rectangle<int> target_rc = Renderer::ConvertEFBRectangle(rc); u32 framebuffer_width = m_current_framebuffer->GetWidth();
target_rc.ClampUL(0, 0, m_target_width, m_target_height); u32 framebuffer_height = m_current_framebuffer->GetHeight();
// All Metal render passes are fullscreen, so we can only run a fast clear if the target is too // All Metal render passes are fullscreen, so we can only run a fast clear if the target is too
if (target_rc == MathUtil::Rectangle<int>(0, 0, m_target_width, m_target_height)) if (target_rc == MathUtil::Rectangle<int>(0, 0, framebuffer_width, framebuffer_height))
{ {
// Determine whether the EFB has an alpha channel. If it doesn't, we can clear the alpha // Determine whether the EFB has an alpha channel. If it doesn't, we can clear the alpha
// channel to 0xFF. This hopefully allows us to use the fast path in most cases. // channel to 0xFF. This hopefully allows us to use the fast path in most cases.
@ -339,12 +334,12 @@ void Metal::Renderer::ClearScreen(const MathUtil::Rectangle<int>& rc, bool color
g_state_tracker->EnableEncoderLabel(true); g_state_tracker->EnableEncoderLabel(true);
} }
void Metal::Renderer::SetPipeline(const AbstractPipeline* pipeline) void Metal::Gfx::SetPipeline(const AbstractPipeline* pipeline)
{ {
g_state_tracker->SetPipeline(static_cast<const Pipeline*>(pipeline)); g_state_tracker->SetPipeline(static_cast<const Pipeline*>(pipeline));
} }
void Metal::Renderer::SetFramebuffer(AbstractFramebuffer* framebuffer) void Metal::Gfx::SetFramebuffer(AbstractFramebuffer* framebuffer)
{ {
// Shouldn't be bound as a texture. // Shouldn't be bound as a texture.
if (AbstractTexture* color = framebuffer->GetColorAttachment()) if (AbstractTexture* color = framebuffer->GetColorAttachment())
@ -356,7 +351,7 @@ void Metal::Renderer::SetFramebuffer(AbstractFramebuffer* framebuffer)
g_state_tracker->SetCurrentFramebuffer(static_cast<Framebuffer*>(framebuffer)); g_state_tracker->SetCurrentFramebuffer(static_cast<Framebuffer*>(framebuffer));
} }
void Metal::Renderer::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer) void Metal::Gfx::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer)
{ {
@autoreleasepool @autoreleasepool
{ {
@ -365,7 +360,7 @@ void Metal::Renderer::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer)
} }
} }
void Metal::Renderer::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, void Metal::Gfx::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer,
const ClearColor& color_value, float depth_value) const ClearColor& color_value, float depth_value)
{ {
@autoreleasepool @autoreleasepool
@ -377,39 +372,39 @@ void Metal::Renderer::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer,
} }
} }
void Metal::Renderer::SetScissorRect(const MathUtil::Rectangle<int>& rc) void Metal::Gfx::SetScissorRect(const MathUtil::Rectangle<int>& rc)
{ {
g_state_tracker->SetScissor(rc); g_state_tracker->SetScissor(rc);
} }
void Metal::Renderer::SetTexture(u32 index, const AbstractTexture* texture) void Metal::Gfx::SetTexture(u32 index, const AbstractTexture* texture)
{ {
g_state_tracker->SetTexture( g_state_tracker->SetTexture(
index, texture ? static_cast<const Texture*>(texture)->GetMTLTexture() : nullptr); index, texture ? static_cast<const Texture*>(texture)->GetMTLTexture() : nullptr);
} }
void Metal::Renderer::SetSamplerState(u32 index, const SamplerState& state) void Metal::Gfx::SetSamplerState(u32 index, const SamplerState& state)
{ {
g_state_tracker->SetSampler(index, state); g_state_tracker->SetSampler(index, state);
} }
void Metal::Renderer::SetComputeImageTexture(AbstractTexture* texture, bool read, bool write) void Metal::Gfx::SetComputeImageTexture(AbstractTexture* texture, bool read, bool write)
{ {
g_state_tracker->SetComputeTexture(static_cast<const Texture*>(texture)); g_state_tracker->SetComputeTexture(static_cast<const Texture*>(texture));
} }
void Metal::Renderer::UnbindTexture(const AbstractTexture* texture) void Metal::Gfx::UnbindTexture(const AbstractTexture* texture)
{ {
g_state_tracker->UnbindTexture(static_cast<const Texture*>(texture)->GetMTLTexture()); g_state_tracker->UnbindTexture(static_cast<const Texture*>(texture)->GetMTLTexture());
} }
void Metal::Renderer::SetViewport(float x, float y, float width, float height, float near_depth, void Metal::Gfx::SetViewport(float x, float y, float width, float height, float near_depth,
float far_depth) float far_depth)
{ {
g_state_tracker->SetViewport(x, y, width, height, near_depth, far_depth); g_state_tracker->SetViewport(x, y, width, height, near_depth, far_depth);
} }
void Metal::Renderer::Draw(u32 base_vertex, u32 num_vertices) void Metal::Gfx::Draw(u32 base_vertex, u32 num_vertices)
{ {
@autoreleasepool @autoreleasepool
{ {
@ -417,7 +412,7 @@ void Metal::Renderer::Draw(u32 base_vertex, u32 num_vertices)
} }
} }
void Metal::Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) void Metal::Gfx::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex)
{ {
@autoreleasepool @autoreleasepool
{ {
@ -425,7 +420,7 @@ void Metal::Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vert
} }
} }
void Metal::Renderer::DispatchComputeShader(const AbstractShader* shader, // void Metal::Gfx::DispatchComputeShader(const AbstractShader* shader, //
u32 groupsize_x, u32 groupsize_y, u32 groupsize_z, u32 groupsize_x, u32 groupsize_y, u32 groupsize_z,
u32 groups_x, u32 groups_y, u32 groups_z) u32 groups_x, u32 groups_y, u32 groups_z)
{ {
@ -437,7 +432,7 @@ void Metal::Renderer::DispatchComputeShader(const AbstractShader* shader, //
} }
} }
void Metal::Renderer::BindBackbuffer(const ClearColor& clear_color) void Metal::Gfx::BindBackbuffer(const ClearColor& clear_color)
{ {
@autoreleasepool @autoreleasepool
{ {
@ -449,7 +444,7 @@ void Metal::Renderer::BindBackbuffer(const ClearColor& clear_color)
} }
} }
void Metal::Renderer::PresentBackbuffer() void Metal::Gfx::PresentBackbuffer()
{ {
@autoreleasepool @autoreleasepool
{ {
@ -474,12 +469,7 @@ void Metal::Renderer::PresentBackbuffer()
} }
} }
std::unique_ptr<::BoundingBox> Metal::Renderer::CreateBoundingBox() const void Metal::Gfx::CheckForSurfaceChange()
{
return std::make_unique<BoundingBox>();
}
void Metal::Renderer::CheckForSurfaceChange()
{ {
if (!g_presenter->SurfaceChangedTestAndClear()) if (!g_presenter->SurfaceChangedTestAndClear())
return; return;
@ -487,26 +477,40 @@ void Metal::Renderer::CheckForSurfaceChange()
SetupSurface(); SetupSurface();
} }
void Metal::Renderer::CheckForSurfaceResize() void Metal::Gfx::CheckForSurfaceResize()
{ {
if (!g_presenter->SurfaceResizedTestAndClear()) if (!g_presenter->SurfaceResizedTestAndClear())
return; return;
SetupSurface(); SetupSurface();
} }
void Metal::Renderer::SetupSurface() void Metal::Gfx::SetupSurface()
{ {
CGSize size = [m_layer bounds].size; auto info = GetSurfaceInfo();
// TODO: Update m_backbuffer_scale (need to make doing that not break everything)
const float backbuffer_scale = [m_layer contentsScale]; [m_layer setDrawableSize:{static_cast<double>(info.width), static_cast<double>(info.height)}];
size.width *= backbuffer_scale;
size.height *= backbuffer_scale; TextureConfig cfg(info.width, info.height, 1, 1, 1, info.format, AbstractTextureFlag_RenderTarget);
[m_layer setDrawableSize:size];
m_backbuffer_width = size.width;
m_backbuffer_height = size.height;
TextureConfig cfg(m_backbuffer_width, m_backbuffer_height, 1, 1, 1, m_backbuffer_format,
AbstractTextureFlag_RenderTarget);
m_bb_texture = std::make_unique<Texture>(nullptr, cfg); m_bb_texture = std::make_unique<Texture>(nullptr, cfg);
m_backbuffer = std::make_unique<Framebuffer>(m_bb_texture.get(), nullptr, // m_backbuffer = std::make_unique<Framebuffer>(m_bb_texture.get(), nullptr, //
m_backbuffer_width, m_backbuffer_height, 1, 1); info.width, info.height, 1, 1);
if (g_presenter)
g_presenter->SetBackbuffer(info);
}
SurfaceInfo Metal::Gfx::GetSurfaceInfo() const
{
if (!m_layer) // Headless
return {};
CGSize size = [m_layer bounds].size;
const float scale = [m_layer contentsScale];
return {
static_cast<u32>(size.width * scale),
static_cast<u32>(size.height * scale),
scale,
Util::ToAbstract([m_layer pixelFormat])
};
} }

View File

@ -16,13 +16,15 @@
#include "Common/Common.h" #include "Common/Common.h"
#include "Common/MsgHandler.h" #include "Common/MsgHandler.h"
#include "VideoBackends/Metal/MTLBoundingBox.h"
#include "VideoBackends/Metal/MTLObjectCache.h" #include "VideoBackends/Metal/MTLObjectCache.h"
#include "VideoBackends/Metal/MTLPerfQuery.h" #include "VideoBackends/Metal/MTLPerfQuery.h"
#include "VideoBackends/Metal/MTLRenderer.h" #include "VideoBackends/Metal/MTLGfx.h"
#include "VideoBackends/Metal/MTLStateTracker.h" #include "VideoBackends/Metal/MTLStateTracker.h"
#include "VideoBackends/Metal/MTLUtil.h" #include "VideoBackends/Metal/MTLUtil.h"
#include "VideoBackends/Metal/MTLVertexManager.h" #include "VideoBackends/Metal/MTLVertexManager.h"
#include "VideoCommon/AbstractGfx.h"
#include "VideoCommon/FramebufferManager.h" #include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h" #include "VideoCommon/VideoConfig.h"
@ -93,47 +95,31 @@ bool Metal::VideoBackend::Initialize(const WindowSystemInfo& wsi)
MRCOwned<id<MTLDevice>> adapter = std::move(devs[selected_adapter_index]); MRCOwned<id<MTLDevice>> adapter = std::move(devs[selected_adapter_index]);
Util::PopulateBackendInfoFeatures(&g_Config, adapter); Util::PopulateBackendInfoFeatures(&g_Config, adapter);
// With the backend information populated, we can now initialize videocommon. UpdateActiveConfig();
InitializeShared();
MRCOwned<CAMetalLayer*> layer = MRCRetain(static_cast<CAMetalLayer*>(wsi.render_surface)); MRCOwned<CAMetalLayer*> layer = MRCRetain(static_cast<CAMetalLayer*>(wsi.render_surface));
[layer setDevice:adapter]; [layer setDevice:adapter];
if (Util::ToAbstract([layer pixelFormat]) == AbstractTextureFormat::Undefined) if (Util::ToAbstract([layer pixelFormat]) == AbstractTextureFormat::Undefined)
[layer setPixelFormat:MTLPixelFormatBGRA8Unorm]; [layer setPixelFormat:MTLPixelFormatBGRA8Unorm];
CGSize size = [layer bounds].size;
float scale = [layer contentsScale];
if (!layer) // headless
scale = 1.0;
ObjectCache::Initialize(std::move(adapter)); ObjectCache::Initialize(std::move(adapter));
g_state_tracker = std::make_unique<StateTracker>(); g_state_tracker = std::make_unique<StateTracker>();
g_renderer = std::make_unique<Renderer>(std::move(layer), size.width * scale,
size.height * scale, scale);
g_vertex_manager = std::make_unique<VertexManager>();
g_perf_query = std::make_unique<PerfQuery>();
g_framebuffer_manager = std::make_unique<FramebufferManager>();
g_texture_cache = std::make_unique<TextureCacheBase>();
g_shader_cache = std::make_unique<VideoCommon::ShaderCache>();
if (!g_vertex_manager->Initialize() || !g_shader_cache->Initialize() || return InitializeShared(
!g_renderer->Initialize() || !g_framebuffer_manager->Initialize() || std::make_unique<Metal::Gfx>(std::move(layer)),
!g_texture_cache->Initialize()) std::make_unique<Metal::VertexManager>(),
{ std::make_unique<Metal::PerfQuery>(),
PanicAlertFmt("Failed to initialize renderer classes"); std::make_unique<Metal::BoundingBox>()
Shutdown(); );
return false;
}
g_shader_cache->InitializeShaderCache();
return true;
} }
} }
void Metal::VideoBackend::Shutdown() void Metal::VideoBackend::Shutdown()
{ {
ObjectCache::Shutdown();
ShutdownShared(); ShutdownShared();
g_state_tracker.reset();
ObjectCache::Shutdown();
} }
void Metal::VideoBackend::InitBackendInfo() void Metal::VideoBackend::InitBackendInfo()

View File

@ -9,6 +9,7 @@
#include "VideoBackends/Metal/MRCHelpers.h" #include "VideoBackends/Metal/MRCHelpers.h"
#include "VideoCommon/RenderState.h" #include "VideoCommon/RenderState.h"
#include "VideoCommon/BPMemory.h"
struct AbstractPipelineConfig; struct AbstractPipelineConfig;
class AbstractPipeline; class AbstractPipeline;

View File

@ -6,7 +6,7 @@
#include "Common/Align.h" #include "Common/Align.h"
#include "Common/Assert.h" #include "Common/Assert.h"
#include "VideoBackends/Metal/MTLRenderer.h" #include "VideoBackends/Metal/MTLGfx.h"
#include "VideoBackends/Metal/MTLStateTracker.h" #include "VideoBackends/Metal/MTLStateTracker.h"
Metal::Texture::Texture(MRCOwned<id<MTLTexture>> tex, const TextureConfig& config) Metal::Texture::Texture(MRCOwned<id<MTLTexture>> tex, const TextureConfig& config)