Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Merge pull request #10754 from tellowkrinkle/Metal
VideoBackends: Add Metal backend
- Loading branch information
Showing
58 changed files
with
4,316 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| add_library(videometal | ||
| MRCHelpers.h | ||
| MTLBoundingBox.mm | ||
| MTLBoundingBox.h | ||
| MTLMain.mm | ||
| MTLObjectCache.h | ||
| MTLObjectCache.mm | ||
| MTLPerfQuery.mm | ||
| MTLPerfQuery.h | ||
| MTLPipeline.mm | ||
| MTLPipeline.h | ||
| MTLRenderer.mm | ||
| MTLRenderer.h | ||
| MTLShader.mm | ||
| MTLShader.h | ||
| MTLStateTracker.mm | ||
| MTLStateTracker.h | ||
| MTLTexture.mm | ||
| MTLTexture.h | ||
| MTLUtil.mm | ||
| MTLUtil.h | ||
| MTLVertexFormat.mm | ||
| MTLVertexFormat.h | ||
| MTLVertexManager.mm | ||
| MTLVertexManager.h | ||
| VideoBackend.h | ||
| ) | ||
|
|
||
| find_library(METAL_LIBRARY Metal) | ||
| find_library(QUARTZCORE_LIBRARY QuartzCore) | ||
|
|
||
| target_link_libraries(videometal | ||
| PUBLIC | ||
| common | ||
| videocommon | ||
| PRIVATE | ||
| spirv_cross | ||
| ${METAL_LIBRARY} | ||
| ${QUARTZCORE_LIBRARY} | ||
| ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| // Copyright 2022 Dolphin Emulator Project | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
|
|
||
| // clang-format off | ||
| #ifndef __OBJC__ | ||
| #error This header is for use with Objective-C++ only. | ||
| #endif | ||
| #if __has_feature(objc_arc) | ||
| #error This file is for manual reference counting! Compile without -fobjc-arc | ||
| #endif | ||
| // clang-format on | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <cstddef> | ||
| #include <utility> | ||
|
|
||
| /// Managed Obj-C pointer | ||
| template <typename T> | ||
| class MRCOwned | ||
| { | ||
| T ptr; | ||
| MRCOwned(T ptr) : ptr(ptr) {} | ||
|
|
||
| public: | ||
| MRCOwned() : ptr(nullptr) {} | ||
| MRCOwned(std::nullptr_t) : ptr(nullptr) {} | ||
| MRCOwned(MRCOwned&& other) : ptr(other.ptr) { other.ptr = nullptr; } | ||
| MRCOwned(const MRCOwned& other) : ptr(other.ptr) { [ptr retain]; } | ||
| ~MRCOwned() | ||
| { | ||
| if (ptr) | ||
| [ptr release]; | ||
| } | ||
| operator T() const { return ptr; } | ||
| MRCOwned& operator=(const MRCOwned& other) | ||
| { | ||
| [other.ptr retain]; | ||
| if (ptr) | ||
| [ptr release]; | ||
| ptr = other.ptr; | ||
| return *this; | ||
| } | ||
| MRCOwned& operator=(MRCOwned&& other) | ||
| { | ||
| std::swap(ptr, other.ptr); | ||
| return *this; | ||
| } | ||
| void Reset() | ||
| { | ||
| [ptr release]; | ||
| ptr = nullptr; | ||
| } | ||
| T Disown() | ||
| { | ||
| T tmp = ptr; | ||
| ptr = nullptr; | ||
| return tmp; | ||
| } | ||
| T Get() const { return ptr; } | ||
| static MRCOwned Transfer(T ptr) { return MRCOwned(ptr); } | ||
| static MRCOwned Retain(T ptr) | ||
| { | ||
| [ptr retain]; | ||
| return MRCOwned(ptr); | ||
| } | ||
| }; | ||
|
|
||
| /// Take ownership of an Obj-C pointer (equivalent to __bridge_transfer) | ||
| template <typename T> | ||
| static inline MRCOwned<T> MRCTransfer(T ptr) | ||
| { | ||
| return MRCOwned<T>::Transfer(ptr); | ||
| } | ||
|
|
||
| /// Retain an Obj-C pointer (equivalent to __bridge) | ||
| template <typename T> | ||
| static inline MRCOwned<T> MRCRetain(T ptr) | ||
| { | ||
| return MRCOwned<T>::Retain(ptr); | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // Copyright 2022 Dolphin Emulator Project | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
|
|
||
| #include "VideoCommon/BoundingBox.h" | ||
|
|
||
| #include <Metal/Metal.h> | ||
|
|
||
| #include "VideoBackends/Metal/MRCHelpers.h" | ||
|
|
||
| namespace Metal | ||
| { | ||
| class BoundingBox final : public ::BoundingBox | ||
| { | ||
| public: | ||
| ~BoundingBox() override; | ||
|
|
||
| bool Initialize() override; | ||
|
|
||
| protected: | ||
| std::vector<BBoxType> Read(u32 index, u32 length) override; | ||
| void Write(u32 index, const std::vector<BBoxType>& values) override; | ||
|
|
||
| private: | ||
| BBoxType* m_cpu_buffer_ptr; | ||
| MRCOwned<id<MTLFence>> m_download_fence; | ||
| MRCOwned<id<MTLFence>> m_upload_fence; | ||
| MRCOwned<id<MTLBuffer>> m_cpu_buffer; | ||
| MRCOwned<id<MTLBuffer>> m_gpu_buffer; | ||
| }; | ||
| } // namespace Metal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| // Copyright 2022 Dolphin Emulator Project | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
|
|
||
| #include "VideoBackends/Metal/MTLBoundingBox.h" | ||
|
|
||
| #include "VideoBackends/Metal/MTLObjectCache.h" | ||
| #include "VideoBackends/Metal/MTLStateTracker.h" | ||
|
|
||
| static constexpr size_t BUFFER_SIZE = sizeof(BBoxType) * NUM_BBOX_VALUES; | ||
|
|
||
| Metal::BoundingBox::~BoundingBox() | ||
| { | ||
| if (g_state_tracker) | ||
| g_state_tracker->SetBBoxBuffer(nullptr, nullptr, nullptr); | ||
| } | ||
|
|
||
| bool Metal::BoundingBox::Initialize() | ||
| { | ||
| const MTLResourceOptions gpu_options = | ||
| MTLResourceStorageModeShared | MTLResourceHazardTrackingModeUntracked; | ||
| const id<MTLDevice> dev = g_device; | ||
| m_upload_fence = MRCTransfer([dev newFence]); | ||
| [m_upload_fence setLabel:@"BBox Upload Fence"]; | ||
| m_download_fence = MRCTransfer([dev newFence]); | ||
| [m_download_fence setLabel:@"BBox Download Fence"]; | ||
| m_gpu_buffer = MRCTransfer([dev newBufferWithLength:BUFFER_SIZE options:gpu_options]); | ||
| [m_gpu_buffer setLabel:@"BBox Buffer"]; | ||
| m_cpu_buffer_ptr = static_cast<BBoxType*>([m_gpu_buffer contents]); | ||
| g_state_tracker->SetBBoxBuffer(m_gpu_buffer, m_upload_fence, m_download_fence); | ||
| return true; | ||
| } | ||
|
|
||
| std::vector<BBoxType> Metal::BoundingBox::Read(u32 index, u32 length) | ||
| { | ||
| @autoreleasepool | ||
| { | ||
| g_state_tracker->EndRenderPass(); | ||
| g_state_tracker->FlushEncoders(); | ||
| g_state_tracker->WaitForFlushedEncoders(); | ||
| return std::vector<BBoxType>(m_cpu_buffer_ptr + index, m_cpu_buffer_ptr + index + length); | ||
| } | ||
| } | ||
|
|
||
| void Metal::BoundingBox::Write(u32 index, const std::vector<BBoxType>& values) | ||
| { | ||
| const u32 size = values.size() * sizeof(BBoxType); | ||
| if (!g_state_tracker->HasUnflushedData() && !g_state_tracker->GPUBusy()) | ||
| { | ||
| // We can just write directly to the buffer! | ||
| memcpy(m_cpu_buffer_ptr + index, values.data(), size); | ||
| } | ||
| else | ||
| { | ||
| @autoreleasepool | ||
| { | ||
| StateTracker::Map map = g_state_tracker->Allocate(StateTracker::UploadBuffer::Other, size, | ||
| StateTracker::AlignMask::Other); | ||
| memcpy(map.cpu_buffer, values.data(), size); | ||
| g_state_tracker->EndRenderPass(); | ||
| id<MTLBlitCommandEncoder> upload = [g_state_tracker->GetRenderCmdBuf() blitCommandEncoder]; | ||
| [upload setLabel:@"BBox Upload"]; | ||
| [upload waitForFence:m_download_fence]; | ||
| [upload copyFromBuffer:map.gpu_buffer | ||
| sourceOffset:map.gpu_offset | ||
| toBuffer:m_gpu_buffer | ||
| destinationOffset:index * sizeof(BBoxType) | ||
| size:size]; | ||
| [upload updateFence:m_upload_fence]; | ||
| [upload endEncoding]; | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.