metal_stream_buffer.h (1949B)
1 // SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) 3 4 #pragma once 5 6 #include "common/types.h" 7 8 #include <Metal/Metal.h> 9 #include <QuartzCore/QuartzCore.h> 10 11 #ifndef __OBJC__ 12 #error This file needs to be compiled with Objective C++. 13 #endif 14 15 #if __has_feature(objc_arc) 16 #error ARC should not be enabled. 17 #endif 18 19 #include <deque> 20 #include <memory> 21 22 class MetalStreamBuffer 23 { 24 public: 25 MetalStreamBuffer(); 26 MetalStreamBuffer(MetalStreamBuffer&& move) = delete; 27 MetalStreamBuffer(const MetalStreamBuffer&) = delete; 28 ~MetalStreamBuffer(); 29 30 MetalStreamBuffer& operator=(MetalStreamBuffer&& move) = delete; 31 MetalStreamBuffer& operator=(const MetalStreamBuffer&) = delete; 32 33 ALWAYS_INLINE bool IsValid() const { return (m_buffer != nil); } 34 ALWAYS_INLINE id<MTLBuffer> GetBuffer() const { return m_buffer; } 35 ALWAYS_INLINE u8* GetHostPointer() const { return m_host_pointer; } 36 ALWAYS_INLINE u8* GetCurrentHostPointer() const { return m_host_pointer + m_current_offset; } 37 ALWAYS_INLINE u32 GetCurrentSize() const { return m_size; } 38 ALWAYS_INLINE u32 GetCurrentSpace() const { return m_current_space; } 39 ALWAYS_INLINE u32 GetCurrentOffset() const { return m_current_offset; } 40 41 bool Create(id<MTLDevice> device, u32 size); 42 void Destroy(); 43 44 bool ReserveMemory(u32 num_bytes, u32 alignment); 45 void CommitMemory(u32 final_num_bytes); 46 47 private: 48 bool AllocateBuffer(u32 size); 49 void UpdateCurrentFencePosition(); 50 void UpdateGPUPosition(); 51 52 // Waits for as many fences as needed to allocate num_bytes bytes from the buffer. 53 bool WaitForClearSpace(u32 num_bytes); 54 55 u32 m_size = 0; 56 u32 m_current_offset = 0; 57 u32 m_current_space = 0; 58 u32 m_current_gpu_position = 0; 59 60 id<MTLBuffer> m_buffer = nil; 61 u8* m_host_pointer = nullptr; 62 63 // List of fences and the corresponding positions in the buffer 64 std::deque<std::pair<u64, u32>> m_tracked_fences; 65 };