2021-12-06 17:13:43 +01:00
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
# pragma once
2022-08-31 15:15:56 +02:00
# include <common/linear_allocator.h>
2022-08-06 12:32:05 +02:00
# include <common/segment_table.h>
2021-12-06 17:13:43 +01:00
# include "buffer.h"
namespace skyline : : gpu {
2022-04-23 19:10:39 +02:00
/**
2022-06-05 09:32:33 +02:00
* @ brief The Buffer Manager is responsible for maintaining a global view of buffers being mapped from the guest to the host , any lookups and creation of host buffer from equivalent guest buffer alongside reconciliation of any overlaps with existing textures
2022-04-23 19:10:39 +02:00
*/
2022-06-05 09:32:33 +02:00
class BufferManager {
2022-04-23 19:10:39 +02:00
private :
2022-06-05 09:32:33 +02:00
GPU & gpu ;
std : : mutex mutex ; //!< Synchronizes access to the buffer mappings
2022-08-01 18:20:09 +02:00
std : : vector < std : : shared_ptr < Buffer > > bufferMappings ; //!< A sorted vector of all buffer mappings
2022-08-31 15:15:56 +02:00
LinearAllocatorState < > delegateAllocatorState ; //!< Linear allocator used to allocate buffer delegates
size_t nextBufferId { } ; //!< The next unique buffer id to be assigned
2022-08-01 18:20:09 +02:00
static constexpr size_t L2EntryGranularity { 19 } ; //!< The amount of AS (in bytes) a single L2 PTE covers (512 KiB == 1 << 19)
2022-08-31 14:08:28 +02:00
SegmentTable < Buffer * , constant : : AddressSpaceSize , constant : : PageSizeBits , L2EntryGranularity > bufferTable ; //!< A page table of all buffer mappings for O(1) lookups on full matches
2022-04-23 19:10:39 +02:00
2022-07-19 19:12:43 +02:00
/**
* @ brief A wrapper around a Buffer which locks it with the specified ContextTag
*/
struct LockedBuffer {
std : : shared_ptr < Buffer > buffer ;
ContextLock < Buffer > lock ;
2022-08-04 12:17:17 +02:00
std : : unique_lock < std : : recursive_mutex > stateLock ;
2022-07-19 19:12:43 +02:00
LockedBuffer ( std : : shared_ptr < Buffer > pBuffer , ContextTag tag ) ;
Buffer * operator - > ( ) const ;
std : : shared_ptr < Buffer > & operator * ( ) ;
} ;
using LockedBuffers = boost : : container : : small_vector < LockedBuffer , 4 > ;
/**
* @ return A vector of buffers locked with the supplied tag which are contained within the supplied range
*/
LockedBuffers Lookup ( span < u8 > range , ContextTag tag ) ;
/**
* @ brief Inserts the supplied buffer into the map based on its guest address
2022-08-01 18:20:09 +02:00
* @ note The supplied buffer * * must * * have a valid guest mapping
2022-07-19 19:12:43 +02:00
*/
void InsertBuffer ( std : : shared_ptr < Buffer > buffer ) ;
/**
* @ brief Deletes the supplied buffer from the map , the lifetime of the buffer will no longer be extended by the map
2022-08-01 18:20:09 +02:00
* @ note The supplied buffer * * must * * have a valid guest mapping
2022-07-19 19:12:43 +02:00
*/
void DeleteBuffer ( const std : : shared_ptr < Buffer > & buffer ) ;
/**
* @ brief Coalesce the supplied buffers into a single buffer encompassing the specified range and locks it with the supplied tag
* @ param range The range of memory that the newly created buffer will cover , this will be extended to cover the entirety of the supplied buffers automatically and can be null
* @ note The supplied buffers * * must * * be in the map and locked with the supplied tag
*/
LockedBuffer CoalesceBuffers ( span < u8 > range , const LockedBuffers & srcBuffers , ContextTag tag ) ;
2022-04-23 19:10:39 +02:00
/**
2022-06-05 09:32:33 +02:00
* @ return If the end of the supplied buffer is less than the supplied pointer
2022-04-23 19:10:39 +02:00
*/
2022-06-05 09:32:33 +02:00
static bool BufferLessThan ( const std : : shared_ptr < Buffer > & it , u8 * pointer ) ;
public :
BufferManager ( GPU & gpu ) ;
2022-04-23 19:10:39 +02:00
2022-06-26 11:28:58 +02:00
/**
* @ brief Acquires an exclusive lock on the texture for the calling thread
* @ note Naming is in accordance to the BasicLockable named requirement
*/
void lock ( ) ;
/**
* @ brief Relinquishes an existing lock on the texture by the calling thread
* @ note Naming is in accordance to the BasicLockable named requirement
*/
void unlock ( ) ;
/**
* @ brief Attempts to acquire an exclusive lock but returns immediately if it ' s captured by another thread
* @ note Naming is in accordance to the Lockable named requirement
*/
bool try_lock ( ) ;
2022-04-23 19:10:39 +02:00
/**
2022-07-16 16:42:09 +02:00
* @ param attachBuffer A function that attaches the buffer to the current context , this ' ll be called when coalesced buffers are merged into the current buffer
2022-06-26 11:02:34 +02:00
* @ return A pre - existing or newly created Buffer object which covers the supplied mappings
2022-06-26 11:28:58 +02:00
* @ note The buffer manager * * must * * be locked prior to calling this
2022-04-23 19:10:39 +02:00
*/
2022-07-16 19:00:57 +02:00
BufferView FindOrCreate ( GuestBuffer guestMapping , ContextTag tag = { } , const std : : function < void ( std : : shared_ptr < Buffer > , ContextLock < Buffer > & & ) > & attachBuffer = { } ) ;
2021-12-06 17:13:43 +01:00
} ;
}