2021-12-06 07:30:39 +01:00
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
# pragma once
2022-06-10 00:18:33 +02:00
# include <boost/functional/hash.hpp>
2022-07-31 14:41:28 +02:00
# include <common/linear_allocator.h>
2022-08-31 17:38:04 +02:00
# include <common/spin_lock.h>
2022-03-06 16:37:37 +01:00
# include <nce.h>
2022-06-26 11:02:34 +02:00
# include <gpu/tag_allocator.h>
2022-08-06 23:29:33 +02:00
# include "megabuffer.h"
2021-12-06 07:30:39 +01:00
# include "memory_manager.h"
namespace skyline : : gpu {
2022-03-28 08:57:05 +02:00
using GuestBuffer = span < u8 > ; //!< The CPU mapping for the guest buffer, multiple mappings for buffers aren't supported since overlaps cannot be reconciled
2021-12-06 07:30:39 +01:00
2022-08-31 15:15:56 +02:00
class BufferView ;
2021-12-06 17:13:43 +01:00
class BufferManager ;
2022-08-31 15:15:56 +02:00
class BufferDelegate ;
2021-12-06 07:30:39 +01:00
2022-09-17 13:46:31 +02:00
/**
* @ brief Represents a bound Vulkan buffer that can be used for state updates
*/
struct BufferBinding {
vk : : Buffer buffer { } ;
vk : : DeviceSize offset { } ;
vk : : DeviceSize size { } ;
BufferBinding ( ) = default ;
BufferBinding ( vk : : Buffer buffer , vk : : DeviceSize offset = 0 , vk : : DeviceSize size = 0 ) : buffer { buffer } , offset { offset } , size { size } { }
operator bool ( ) const {
return buffer ;
}
} ;
2021-12-06 07:30:39 +01:00
/**
* @ brief A buffer which is backed by host constructs while being synchronized with the underlying guest buffer
* @ note This class conforms to the Lockable and BasicLockable C + + named requirements
*/
2022-06-26 08:56:18 +02:00
class Buffer : public std : : enable_shared_from_this < Buffer > {
2021-12-06 07:30:39 +01:00
private :
2022-03-06 15:57:13 +01:00
GPU & gpu ;
2022-08-31 17:38:04 +02:00
SpinLock mutex ; //!< Synchronizes any mutations to the buffer or its backing
2022-06-26 11:02:34 +02:00
std : : atomic < ContextTag > tag { } ; //!< The tag associated with the last lock call
2021-12-06 07:30:39 +01:00
memory : : Buffer backing ;
2022-04-12 17:20:20 +02:00
std : : optional < GuestBuffer > guest ;
2022-08-04 12:17:17 +02:00
std : : shared_ptr < FenceCycle > cycle { } ; //!< A fence cycle for when any host operation mutating the buffer has completed, it must be waited on prior to any mutations to the backing
2022-08-31 15:15:56 +02:00
size_t id ;
2021-12-06 07:30:39 +01:00
2022-03-06 15:57:13 +01:00
span < u8 > mirror { } ; //!< A contiguous mirror of all the guest mappings to allow linear access on the CPU
span < u8 > alignedMirror { } ; //!< The mirror mapping aligned to page size to reflect the full mapping
2022-03-06 16:37:37 +01:00
std : : optional < nce : : NCE : : TrapHandle > trapHandle { } ; //!< The handle of the traps for the guest mappings
2022-08-04 12:17:17 +02:00
2022-03-06 16:37:37 +01:00
enum class DirtyState {
Clean , //!< The CPU mappings are in sync with the GPU buffer
CpuDirty , //!< The CPU mappings have been modified but the GPU buffer is not up to date
GpuDirty , //!< The GPU buffer has been modified but the CPU mappings have not been updated
2022-08-04 12:17:17 +02:00
} dirtyState { DirtyState : : CpuDirty } ; //!< The state of the CPU mappings with respect to the GPU buffer
2022-03-06 16:37:37 +01:00
2022-08-04 12:17:17 +02:00
enum class BackingImmutability {
None , //!< Backing can be freely written to and read from
SequencedWrites , //!< Sequenced writes must not modify the backing on the CPU due to it being read directly on the GPU, but non-sequenced writes can freely occur (SynchroniseHost etc)
AllWrites //!< No CPU writes to the backing can be performed, all must be sequenced on the GPU or delayed till this is no longer the case
} backingImmutability { } ; //!< Describes how the buffer backing should be accessed by the current context
2022-08-31 17:38:04 +02:00
RecursiveSpinLock stateMutex ; //!< Synchronizes access to the dirty state and backing immutability
2022-04-23 19:10:39 +02:00
2022-08-04 12:17:17 +02:00
bool everHadInlineUpdate { } ; //!< Whether the buffer has ever had an inline update since it was created, if this is set then megabuffering will be attempted by views to avoid the cost of inline GPU updates
2022-04-23 19:10:39 +02:00
2022-06-10 22:26:19 +02:00
static constexpr u64 InitialSequenceNumber { 1 } ; //!< Sequence number that all buffers start off with
2022-09-17 13:53:50 +02:00
static constexpr u64 FrequentlySyncedThreshold { 15 } ; //!< Threshold for the sequence number after which the buffer is considered elegible for megabuffering
2022-06-10 22:26:19 +02:00
u64 sequenceNumber { InitialSequenceNumber } ; //!< Sequence number that is incremented after all modifications to the host side `backing` buffer, used to prevent redundant copies of the buffer being stored in the megabuffer by views
2022-09-17 13:46:31 +02:00
constexpr static vk : : DeviceSize MegaBufferingDisableThreshold { 1024 * 128 } ; //!< The threshold at which a view is considered to be too large to be megabuffered (128KiB)
/**
* @ brief Holds a single megabuffer copy with sequencing information for an offset within the buffer
*/
struct MegaBufferTableEntry {
MegaBufferAllocator : : Allocation allocation { } ; //!< The allocation in the megabuffer for the entry, can be any size
size_t executionNumber ; //!< Execution number of when the allocation was made
size_t sequenceNumber ; //!< Sequence number of when the allocation was made
} ;
2022-09-18 16:28:23 +02:00
static constexpr int MegaBufferTableShiftMin { std : : countr_zero ( 0x80U ) } ; //!< The minimum shift for megabuffer table entries, giving an alignment of at least 128 bytes
2022-09-17 13:46:31 +02:00
static constexpr size_t MegaBufferTableMaxEntries { 0x500U } ; //!< Maximum number of entries in the megabuffer table, `megaBufferTableShift` is set based on this and the total buffer size
int megaBufferTableShift ; //!< Shift to apply to buffer offsets to get their megabuffer table index
std : : vector < MegaBufferTableEntry > megaBufferTable ; //!< Table of megabuffer allocations for regions of the buffer
2022-03-28 08:57:05 +02:00
private :
2022-08-31 15:15:56 +02:00
BufferDelegate * delegate ;
2022-03-28 08:57:05 +02:00
2021-12-06 07:30:39 +01:00
friend BufferView ;
2021-12-06 17:13:43 +01:00
friend BufferManager ;
2021-12-06 07:30:39 +01:00
2022-03-06 15:57:13 +01:00
/**
2022-07-25 19:22:45 +02:00
* @ brief Sets up mirror mappings for the guest mappings , this must be called after construction for the mirror to be valid
2022-03-06 15:57:13 +01:00
*/
void SetupGuestMappings ( ) ;
2021-12-06 07:30:39 +01:00
public :
2022-08-04 12:17:17 +02:00
void UpdateCycle ( const std : : shared_ptr < FenceCycle > & newCycle ) {
std : : scoped_lock lock { stateMutex } ;
newCycle - > ChainCycle ( cycle ) ;
cycle = newCycle ;
}
2021-12-06 07:30:39 +01:00
constexpr vk : : Buffer GetBacking ( ) {
return backing . vkBuffer ;
}
2022-04-20 11:26:06 +02:00
/**
* @ return A span over the backing of this buffer
* @ note This operation * * must * * be performed only on host - only buffers since synchronization is handled internally for guest - backed buffers
*/
span < u8 > GetBackingSpan ( ) {
if ( guest )
throw exception ( " Attempted to get a span of a guest-backed buffer " ) ;
return span < u8 > ( backing ) ;
}
2022-07-25 19:22:45 +02:00
/**
* @ brief Creates a buffer object wrapping the guest buffer with a backing that can represent the guest buffer data
* @ note The guest mappings will not be setup until SetupGuestMappings ( ) is called
*/
2022-08-31 15:15:56 +02:00
Buffer ( LinearAllocatorState < > & delegateAllocator , GPU & gpu , GuestBuffer guest , size_t id ) ;
2021-12-06 07:30:39 +01:00
2022-04-12 17:20:20 +02:00
/**
* @ brief Creates a host - only Buffer which isn ' t backed by any guest buffer
* @ note The created buffer won ' t have a mirror so any operations cannot depend on a mirror existing
*/
2022-08-31 15:15:56 +02:00
Buffer ( LinearAllocatorState < > & delegateAllocator , GPU & gpu , vk : : DeviceSize size , size_t id ) ;
2022-04-12 17:20:20 +02:00
2022-03-06 15:57:13 +01:00
~ Buffer ( ) ;
2021-12-06 07:30:39 +01:00
/**
2022-03-06 15:57:13 +01:00
* @ brief Acquires an exclusive lock on the buffer for the calling thread
2021-12-06 07:30:39 +01:00
* @ note Naming is in accordance to the BasicLockable named requirement
*/
2022-06-26 11:02:34 +02:00
void lock ( ) ;
/**
2022-08-04 12:17:17 +02:00
* @ brief Acquires an exclusive lock on the buffer for the calling thread
* @ param tag A tag to associate with the lock , future invocations with the same tag prior to the unlock will acquire the lock without waiting ( A default initialised tag will disable this behaviour )
* @ return If the lock was acquired by this call as opposed to the buffer already being locked with the same tag
2022-06-26 11:02:34 +02:00
* @ note All locks using the same tag * * must * * be from the same thread as it ' ll only have one corresponding unlock ( ) call
*/
bool LockWithTag ( ContextTag tag ) ;
2021-12-06 07:30:39 +01:00
/**
2022-03-06 15:57:13 +01:00
* @ brief Relinquishes an existing lock on the buffer by the calling thread
2021-12-06 07:30:39 +01:00
* @ note Naming is in accordance to the BasicLockable named requirement
*/
2022-06-26 11:02:34 +02:00
void unlock ( ) ;
2021-12-06 07:30:39 +01:00
/**
* @ 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
*/
2022-06-26 11:02:34 +02:00
bool try_lock ( ) ;
2021-12-06 07:30:39 +01:00
2022-03-06 16:37:37 +01:00
/**
* @ brief Marks the buffer as dirty on the GPU , it will be synced on the next call to SynchronizeGuest
* @ note This * * must * * be called after syncing the buffer to the GPU not before
* @ note The buffer * * must * * be locked prior to calling this
*/
void MarkGpuDirty ( ) ;
2022-06-29 18:32:09 +02:00
/**
2022-08-04 12:17:17 +02:00
* @ brief Prevents sequenced writes to this buffer ' s backing from occuring on the CPU , forcing sequencing on the GPU instead for the duration of the context . Unsequenced writes such as those from the guest can still occur however .
* @ note The buffer * * must * * be locked prior to calling this
*/
void BlockSequencedCpuBackingWrites ( ) {
std : : scoped_lock lock { stateMutex } ;
if ( backingImmutability = = BackingImmutability : : None )
backingImmutability = BackingImmutability : : SequencedWrites ;
}
/**
* @ brief Prevents * any * writes to this buffer ' s backing from occuring on the CPU , forcing sequencing on the GPU instead for the duration of the context .
* @ note The buffer * * must * * be locked prior to calling this
*/
void BlockAllCpuBackingWrites ( ) {
std : : scoped_lock lock { stateMutex } ;
backingImmutability = BackingImmutability : : AllWrites ;
}
/**
* @ return If sequenced writes to the backing must not occur on the CPU
* @ note The buffer * * must * * be locked prior to calling this
*/
bool SequencedCpuBackingWritesBlocked ( ) {
std : : scoped_lock lock { stateMutex } ;
return backingImmutability = = BackingImmutability : : SequencedWrites | | backingImmutability = = BackingImmutability : : AllWrites ;
}
/**
* @ return If no writes to the backing are allowed to occur on the CPU
2022-06-29 18:32:09 +02:00
* @ note The buffer * * must * * be locked prior to calling this
*/
2022-08-04 12:17:17 +02:00
bool AllCpuBackingWritesBlocked ( ) {
std : : scoped_lock lock { stateMutex } ;
return backingImmutability = = BackingImmutability : : AllWrites ;
2022-06-29 18:32:09 +02:00
}
/**
2022-08-04 12:17:17 +02:00
* @ return If the cycle needs to be attached to the buffer before ending the current context
* @ note This is an alias for ` SequencedCpuBackingWritesBlocked ( ) ` since this is only ever set when the backing is accessed on the GPU in some form
* @ note The buffer * * must * * be locked prior to calling this
2022-06-29 18:32:09 +02:00
*/
2022-08-04 12:17:17 +02:00
bool RequiresCycleAttach ( ) {
return SequencedCpuBackingWritesBlocked ( ) ;
2022-06-29 18:32:09 +02:00
}
2021-12-06 07:30:39 +01:00
/**
* @ brief Waits on a fence cycle if it exists till it ' s signalled and resets it after
* @ note The buffer * * must * * be locked prior to calling this
*/
void WaitOnFence ( ) ;
2022-04-23 19:10:39 +02:00
/**
* @ brief Polls a fence cycle if it exists and resets it if signalled
* @ return Whether the fence cycle was signalled
* @ note The buffer * * must * * be locked prior to calling this
*/
bool PollFence ( ) ;
2022-07-17 14:48:33 +02:00
/**
* @ brief Invalidates the Buffer on the guest and deletes the trap that backs this buffer as it is no longer necessary
* @ note This will not clear any views or delegates on the buffer , it will only remove guest mappings and delete the trap
* @ note The buffer * * must * * be locked prior to calling this
*/
void Invalidate ( ) ;
2021-12-06 07:30:39 +01:00
/**
* @ brief Synchronizes the host buffer with the guest
2022-08-04 12:17:17 +02:00
* @ param skipTrap If true , setting up a CPU trap will be skipped
2021-12-06 07:30:39 +01:00
* @ note The buffer * * must * * be locked prior to calling this
*/
2022-08-04 12:17:17 +02:00
void SynchronizeHost ( bool skipTrap = false ) ;
2021-12-06 07:30:39 +01:00
/**
* @ brief Synchronizes the guest buffer with the host buffer
2022-08-04 12:17:17 +02:00
* @ param skipTrap If true , setting up a CPU trap will be skipped
2022-04-23 19:10:39 +02:00
* @ param nonBlocking If true , the call will return immediately if the fence is not signalled , skipping the sync
2022-07-13 18:49:37 +02:00
* @ return If the buffer ' s contents were successfully synchronized , this ' ll only be false on non - blocking operations or lack of a guest buffer
2021-12-06 07:30:39 +01:00
* @ note The buffer * * must * * be locked prior to calling this
*/
2022-08-04 12:17:17 +02:00
bool SynchronizeGuest ( bool skipTrap = false , bool nonBlocking = false ) ;
2021-12-06 07:30:39 +01:00
2022-04-30 16:21:55 +02:00
/**
* @ brief Synchronizes the guest buffer with the host buffer immediately , flushing GPU work if necessary
2022-06-26 11:10:46 +02:00
* @ param isFirstUsage If this is the first usage of this resource in the context as returned from LockWithTag ( . . . )
2022-04-30 16:21:55 +02:00
* @ param flushHostCallback Callback to flush and execute all pending GPU work to allow for synchronisation of GPU dirty buffers
2022-06-26 11:10:46 +02:00
* @ note The buffer * * must * * be locked prior to calling this
2022-04-30 16:21:55 +02:00
*/
2022-06-26 11:10:46 +02:00
void SynchronizeGuestImmediate ( bool isFirstUsage , const std : : function < void ( ) > & flushHostCallback ) ;
2022-04-30 16:21:55 +02:00
2022-03-28 08:57:05 +02:00
/**
* @ brief Reads data at the specified offset in the buffer
2022-06-26 11:10:46 +02:00
* @ param isFirstUsage If this is the first usage of this resource in the context as returned from LockWithTag ( . . . )
2022-04-23 19:10:39 +02:00
* @ param flushHostCallback Callback to flush and execute all pending GPU work to allow for synchronisation of GPU dirty buffers
2022-03-28 08:57:05 +02:00
*/
2022-06-26 11:10:46 +02:00
void Read ( bool isFirstUsage , const std : : function < void ( ) > & flushHostCallback , span < u8 > data , vk : : DeviceSize offset ) ;
2022-03-28 08:57:05 +02:00
2022-03-06 15:57:13 +01:00
/**
2022-06-10 22:26:19 +02:00
* @ brief Writes data at the specified offset in the buffer , falling back to GPU side copies if the buffer is host immutable
2022-06-26 11:10:46 +02:00
* @ param isFirstUsage If this is the first usage of this resource in the context as returned from LockWithTag ( . . . )
2022-04-23 19:10:39 +02:00
* @ param flushHostCallback Callback to flush and execute all pending GPU work to allow for synchronisation of GPU dirty buffers
2022-08-31 15:45:55 +02:00
* @ param gpuCopyCallback Optional callback to perform a GPU - side copy for this Write if necessary , if such a copy is needed and this is not supplied ` true ` will be returned to indicate that the write needs to be repeated with the callback present
* @ return Whether the write needs to be repeated with ` gpuCopyCallback ` provided , always false if ` gpuCopyCallback ` is provided
2022-03-06 15:57:13 +01:00
*/
2022-08-31 15:45:55 +02:00
bool Write ( bool isFirstUsage , const std : : function < void ( ) > & flushHostCallback , span < u8 > data , vk : : DeviceSize offset , const std : : function < void ( ) > & gpuCopyCallback = { } ) ;
2022-03-06 15:57:13 +01:00
2021-12-06 07:30:39 +01:00
/**
2022-08-31 15:15:56 +02:00
* @ return A view into this buffer with the supplied attributes
* @ note The buffer * * must * * be locked prior to calling this
*/
BufferView GetView ( vk : : DeviceSize offset , vk : : DeviceSize size ) ;
/**
* @ return A view into this buffer containing the given mapping , if the buffer doesn ' t contain the mapping an empty view will be returned
2022-03-17 14:32:06 +01:00
* @ note The buffer * * must * * be locked prior to calling this
2021-12-06 07:30:39 +01:00
*/
2022-08-31 15:15:56 +02:00
BufferView TryGetView ( span < u8 > mapping ) ;
2022-04-23 19:10:39 +02:00
2022-09-17 13:46:31 +02:00
/*
* @ brief If megabuffering is determined to be beneficial for this buffer , allocates and copies the given view of buffer into the megabuffer ( in case of cache miss ) , returning a binding of the allocated megabuffer region
* @ return A binding to the megabuffer allocation for the view , may be invalid if megabuffering is not beneficial
2022-04-23 19:10:39 +02:00
* @ note The buffer * * must * * be locked prior to calling this
*/
2022-09-17 13:46:31 +02:00
BufferBinding TryMegaBufferView ( const std : : shared_ptr < FenceCycle > & pCycle , MegaBufferAllocator & allocator , size_t executionNumber ,
vk : : DeviceSize offset , vk : : DeviceSize size ) ;
2022-04-23 19:10:39 +02:00
/**
2022-06-10 22:26:19 +02:00
* @ brief Increments the sequence number of the buffer , any futher calls to AcquireCurrentSequence will return this new sequence number . See the comment for ` sequenceNumber `
2022-04-23 19:10:39 +02:00
* @ note The buffer * * must * * be locked prior to calling this
2022-06-10 22:26:19 +02:00
* @ note This * * must * * be called after any modifications of the backing buffer data ( but not mirror )
2022-04-23 19:10:39 +02:00
*/
2022-06-10 22:26:19 +02:00
void AdvanceSequence ( ) ;
2022-04-30 16:21:55 +02:00
/**
2022-06-26 11:10:46 +02:00
* @ param isFirstUsage If this is the first usage of this resource in the context as returned from LockWithTag ( . . . )
2022-04-30 16:21:55 +02:00
* @ param flushHostCallback Callback to flush and execute all pending GPU work to allow for synchronisation of GPU dirty buffers
* @ return A span of the backing buffer contents
* @ note The returned span * * must * * not be written to
* @ note The buffer * * must * * be kept locked until the span is no longer in use
*/
2022-06-26 11:10:46 +02:00
span < u8 > GetReadOnlyBackingSpan ( bool isFirstUsage , const std : : function < void ( ) > & flushHostCallback ) ;
2021-12-06 07:30:39 +01:00
} ;
2022-08-31 15:15:56 +02:00
/**
* @ brief A delegate for a strong reference to a Buffer by a BufferView which can be changed to another Buffer transparently
*/
class BufferDelegate {
private :
union {
BufferDelegate * link { } ;
Buffer * buffer ;
} ;
vk : : DeviceSize offset { } ;
bool linked { } ;
public :
BufferDelegate ( Buffer * buffer ) ;
/**
* @ brief Follows links to get the underlying target buffer of the delegate
*/
Buffer * GetBuffer ( ) ;
/**
* @ brief Links the delegate to target a new buffer object
* @ note Both the current target buffer object and new target buffer object * * must * * be locked prior to calling this
*/
void Link ( BufferDelegate * newTarget , vk : : DeviceSize newOffset ) ;
/**
* @ return The offset of the delegate in the buffer
* @ note The target buffer * * must * * be locked prior to calling this
*/
vk : : DeviceSize GetOffset ( ) ;
} ;
2021-12-06 07:30:39 +01:00
/**
* @ brief A contiguous view into a Vulkan Buffer that represents a single guest buffer ( as opposed to Buffer objects which contain multiple )
* @ note The object * * must * * be locked prior to accessing any members as values will be mutated
* @ note This class conforms to the Lockable and BasicLockable C + + named requirements
*/
2022-08-31 15:15:56 +02:00
class BufferView {
private :
BufferDelegate * delegate { } ;
vk : : DeviceSize offset { } ;
/**
* @ brief Resolves the delegate ' s pointer chain so it directly points to the target buffer , updating offset accordingly
* @ note The view * * must * * be locked prior to calling this
*/
void ResolveDelegate ( ) ;
public :
vk : : DeviceSize size { } ;
2021-12-06 07:30:39 +01:00
2022-08-31 15:15:56 +02:00
BufferView ( ) ;
2022-03-17 14:32:06 +01:00
2022-08-31 15:15:56 +02:00
BufferView ( BufferDelegate * delegate , vk : : DeviceSize offset , vk : : DeviceSize size ) ;
2021-12-06 07:30:39 +01:00
/**
2022-08-31 15:15:56 +02:00
* @ return A pointer to the current underlying buffer of the view
* @ note The view * * must * * be locked prior to calling this
2021-12-06 07:30:39 +01:00
*/
2022-08-31 15:15:56 +02:00
Buffer * GetBuffer ( ) const ;
2021-12-06 07:30:39 +01:00
2022-06-26 11:02:34 +02:00
/**
2022-08-31 15:15:56 +02:00
* @ return The offset of the view in the underlying buffer
* @ note The view * * must * * be locked prior to calling this
2022-06-26 11:02:34 +02:00
*/
2022-08-31 15:15:56 +02:00
vk : : DeviceSize GetOffset ( ) const ;
2022-06-26 11:02:34 +02:00
2021-12-06 07:30:39 +01:00
/**
2022-09-18 16:30:24 +02:00
* @ note The buffer manager * * MUST * * be locked prior to calling this
*/
2022-08-31 15:15:56 +02:00
void lock ( ) {
2022-09-18 16:30:24 +02:00
delegate - > GetBuffer ( ) - > lock ( ) ;
2022-03-28 08:57:05 +02:00
}
2022-09-18 16:30:24 +02:00
/**
* @ note The buffer manager * * MUST * * be locked prior to calling this
*/
2022-08-31 15:15:56 +02:00
bool try_lock ( ) {
2022-09-18 16:30:24 +02:00
return delegate - > GetBuffer ( ) - > try_lock ( ) ;
2022-03-28 08:57:05 +02:00
}
2022-09-18 16:30:24 +02:00
/**
* @ note The buffer manager * * MUST * * be locked prior to calling this
*/
2022-08-31 15:15:56 +02:00
bool LockWithTag ( ContextTag tag ) {
2022-09-18 16:30:24 +02:00
return delegate - > GetBuffer ( ) - > LockWithTag ( tag ) ;
2022-03-28 08:57:05 +02:00
}
2022-08-31 15:15:56 +02:00
void unlock ( ) {
delegate - > GetBuffer ( ) - > unlock ( ) ;
}
2022-03-28 08:57:05 +02:00
/**
* @ brief Reads data at the specified offset in the view
* @ note The view * * must * * be locked prior to calling this
2022-04-23 19:10:39 +02:00
* @ note See Buffer : : Read
2022-03-28 08:57:05 +02:00
*/
2022-08-31 15:15:56 +02:00
void Read ( bool isFirstUsage , const std : : function < void ( ) > & flushHostCallback , span < u8 > data , vk : : DeviceSize readOffset ) const ;
2022-03-28 08:57:05 +02:00
/**
* @ brief Writes data at the specified offset in the view
* @ note The view * * must * * be locked prior to calling this
2022-04-23 19:10:39 +02:00
* @ note See Buffer : : Write
*/
2022-09-17 13:46:31 +02:00
bool Write ( bool isFirstUsage , const std : : shared_ptr < FenceCycle > & cycle , const std : : function < void ( ) > & flushHostCallback ,
span < u8 > data , vk : : DeviceSize writeOffset , const std : : function < void ( ) > & gpuCopyCallback = { } ) const ;
2022-04-23 19:10:39 +02:00
2022-09-17 13:46:31 +02:00
/*
* @ brief If megabuffering is determined to be beneficial for the underlying buffer , allocates and copies this view into the megabuffer ( in case of cache miss ) , returning a binding of the allocated megabuffer region
* @ param sizeOverride If non - zero , specifies the size of the megabuffer region to allocate and copy to , * MUST * be smaller than the size of the view
2022-04-23 19:10:39 +02:00
* @ note The view * * must * * be locked prior to calling this
2022-09-17 13:46:31 +02:00
* @ note See Buffer : : TryMegaBufferView
2022-03-28 08:57:05 +02:00
*/
2022-09-17 13:46:31 +02:00
BufferBinding TryMegaBuffer ( const std : : shared_ptr < FenceCycle > & pCycle , MegaBufferAllocator & allocator , size_t executionNumber , size_t sizeOverride = 0 ) const ;
2022-04-30 16:21:55 +02:00
/**
* @ return A span of the backing buffer contents
* @ note The returned span * * must * * not be written to
* @ note The view * * must * * be kept locked until the span is no longer in use
* @ note See Buffer : : GetReadOnlyBackingSpan
*/
2022-06-26 11:10:46 +02:00
span < u8 > GetReadOnlyBackingSpan ( bool isFirstUsage , const std : : function < void ( ) > & flushHostCallback ) ;
2022-08-31 15:15:56 +02:00
constexpr operator bool ( ) {
return delegate ! = nullptr ;
}
2021-12-06 07:30:39 +01:00
} ;
}