1 /* 2 * Copyright 2021 Google LLC 3 * SPDX-License-Identifier: MIT 4 */ 5 #ifndef __COMMAND_BUFFER_STAGING_STREAM_H 6 #define __COMMAND_BUFFER_STAGING_STREAM_H 7 8 #include <vulkan/vulkan_core.h> 9 10 #include <functional> 11 12 #include "gfxstream/guest/IOStream.h" 13 14 namespace gfxstream { 15 namespace vk { 16 17 class CommandBufferStagingStream : public gfxstream::guest::IOStream { 18 public: 19 // host will write kSyncDataReadComplete to the sync bytes to indicate memory is no longer being 20 // used by host. This is only used with custom allocators. The sync bytes are used to ensure 21 // that, during reallocations the guest does not free memory being read by the host. The guest 22 // ensures that the sync bytes are marked as read complete before releasing the memory. 23 static constexpr size_t kSyncDataSize = 8; 24 // indicates read is complete 25 static constexpr uint32_t kSyncDataReadComplete = 0X0; 26 // indicates read is pending 27 static constexpr uint32_t kSyncDataReadPending = 0X1; 28 29 // \struct backing memory structure 30 struct Memory { 31 VkDeviceMemory deviceMemory = 32 VK_NULL_HANDLE; // device memory associated with allocated memory 33 void* ptr = nullptr; // pointer to allocated memory 34 bool operator==(const Memory& rhs) const { 35 return (deviceMemory == rhs.deviceMemory) && (ptr == rhs.ptr); 36 } 37 }; 38 39 // allocator 40 // param size to allocate 41 // return allocated memory 42 using Alloc = std::function<Memory(size_t)>; 43 // free function 44 // param memory to free 45 using Free = std::function<void(const Memory&)>; 46 // constructor 47 // \param allocFn is the allocation function provided. 48 // \param freeFn is the free function provided 49 explicit CommandBufferStagingStream(const Alloc& allocFn, const Free& freeFn); 50 // constructor 51 explicit CommandBufferStagingStream(); 52 ~CommandBufferStagingStream(); 53 54 virtual size_t idealAllocSize(size_t len); 55 virtual void* allocBuffer(size_t minSize); 56 virtual int commitBuffer(size_t size); 57 virtual const unsigned char* readFully(void* buf, size_t len); 58 virtual const unsigned char* read(void* buf, size_t* inout_len); 59 virtual int writeFully(const void* buf, size_t len); 60 virtual const unsigned char* commitBufferAndReadFully(size_t size, void* buf, size_t len); 61 62 void getWritten(unsigned char** bufOut, size_t* sizeOut); 63 void reset(); 64 65 // marks the command buffer stream as flushing. The owner of CommandBufferStagingStream 66 // should call markFlushing after finishing writing to the stream. 67 // This will mark the sync data to kSyncDataReadPending. This is only applicable when 68 // using custom allocators. markFlushing will be a no-op if called 69 // when not using custom allocators 70 void markFlushing(); 71 72 // gets the device memory associated with the stream. This is VK_NULL_HANDLE for default 73 // allocation \return device memory 74 VkDeviceMemory getDeviceMemory(); 75 76 private: 77 // underlying memory for data 78 Memory m_mem; 79 // size of portion of memory available for data. 80 // for custom allocation, this size excludes size of sync data. 81 size_t m_size; 82 // current write position in data buffer 83 uint32_t m_writePos; 84 85 // alloc function 86 Alloc m_alloc; 87 // free function 88 Free m_free; 89 90 // realloc function 91 // \param size of memory to be allocated 92 // \ param reference size to update with actual size allocated. This size can be < requested 93 // size for custom allocation to account for sync data 94 using Realloc = std::function<Memory(const Memory&, size_t)>; 95 Realloc m_realloc; 96 97 // flag tracking use of custom allocation/free 98 bool m_usingCustomAlloc = false; 99 100 // adjusted memory location to point to start of data after accounting for metadata 101 // \return pointer to data start 102 unsigned char* getDataPtr(); 103 }; 104 105 } // namespace vk 106 } // namespace gfxstream 107 108 #endif 109