1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6
7namespace bs
8{
9 /** @addtogroup RenderAPI-Internal
10 * @{
11 */
12
13 /**
14 * Abstract class defining common features of hardware buffers. Hardware buffers usually represent areas of memory the
15 * GPU or the driver can access directly.
16 *
17 * @note Core thread only.
18 * @note Be aware that reading from non-system memory hardware buffers is usually slow and should be avoided.
19 */
20 class BS_CORE_EXPORT HardwareBuffer
21 {
22 public:
23 virtual ~HardwareBuffer() = default;
24
25 /**
26 * Locks a portion of the buffer and returns pointer to the locked area. You must call unlock() when done.
27 *
28 * @param[in] offset Offset in bytes from which to lock the buffer.
29 * @param[in] length Length of the area you want to lock, in bytes.
30 * @param[in] options Signifies what you want to do with the returned pointer. Caller must ensure not to do
31 * anything he hasn't requested (for example don't try to read from the buffer unless you
32 * requested it here).
33 * @param[in] deviceIdx Index of the device whose memory to map. If the buffer doesn't exist on this device,
34 * the method returns null.
35 * @param[in] queueIdx Device queue to perform any read/write operations on. See @ref queuesDoc.
36 */
37 virtual void* lock(UINT32 offset, UINT32 length, GpuLockOptions options, UINT32 deviceIdx = 0, UINT32 queueIdx = 0)
38 {
39 assert(!isLocked() && "Cannot lock this buffer, it is already locked!");
40 void* ret = map(offset, length, options, deviceIdx, queueIdx);
41 mIsLocked = true;
42
43 return ret;
44 }
45
46 /**
47 * Locks the entire buffer and returns pointer to the locked area. You must call unlock() when done.
48 *
49 * @param[in] options Signifies what you want to do with the returned pointer. Caller must ensure not to do
50 * anything he hasn't requested (for example don't try to read from the buffer unless you
51 * requested it here).
52 * @param[in] deviceIdx Index of the device whose memory to map. If the buffer doesn't exist on this device,
53 * the method returns null.
54 * @param[in] queueIdx Device queue to perform any read/write operations on. See @ref queuesDoc.
55 */
56 void* lock(GpuLockOptions options, UINT32 deviceIdx = 0, UINT32 queueIdx = 0)
57 {
58 return this->lock(0, mSize, options, deviceIdx, queueIdx);
59 }
60
61 /** Releases the lock on this buffer. */
62 virtual void unlock()
63 {
64 assert(isLocked() && "Cannot unlock this buffer, it is not locked!");
65
66 unmap();
67 mIsLocked = false;
68 }
69
70 /**
71 * Reads data from a portion of the buffer and copies it to the destination buffer. Caller must ensure destination
72 * buffer is large enough.
73 *
74 * @param[in] offset Offset in bytes from which to copy the data.
75 * @param[in] length Length of the area you want to copy, in bytes.
76 * @param[in] dest Destination buffer large enough to store the read data. Data is written from the start
77 * of the buffer (@p offset is only applied to the source).
78 * @param[in] deviceIdx Index of the device whose memory to read. If the buffer doesn't exist on this device,
79 * no data will be read.
80 * @param[in] queueIdx Device queue to perform the read operation on. See @ref queuesDoc.
81 */
82 virtual void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) = 0;
83
84 /**
85 * Writes data into a portion of the buffer from the source memory.
86 *
87 * @param[in] offset Offset in bytes from which to copy the data.
88 * @param[in] length Length of the area you want to copy, in bytes.
89 * @param[in] source Source buffer containing the data to write. Data is read from the start of the buffer
90 * (@p offset is only applied to the destination).
91 * @param[in] writeFlags Optional write flags that may affect performance.
92 * @param[in] queueIdx Device queue to perform the write operation on. See @ref queuesDoc.
93 */
94 virtual void writeData(UINT32 offset, UINT32 length, const void* source,
95 BufferWriteType writeFlags = BWT_NORMAL, UINT32 queueIdx = 0) = 0;
96
97 /**
98 * Copies data from a specific portion of the source buffer into a specific portion of this buffer.
99 *
100 * @param[in] srcBuffer Buffer to copy from.
101 * @param[in] srcOffset Offset into the source buffer to start copying from, in bytes.
102 * @param[in] dstOffset Offset into this buffer to start copying to, in bytes.
103 * @param[in] length Size of the data to copy, in bytes.
104 * @param[in] discardWholeBuffer Specify true if the data in the current buffer can be entirely discarded. This
105 * may improve performance.
106 * @param[in] commandBuffer Command buffer to queue the copy operation on. If null, main command buffer is
107 * used.
108 */
109 virtual void copyData(HardwareBuffer& srcBuffer, UINT32 srcOffset, UINT32 dstOffset, UINT32 length,
110 bool discardWholeBuffer = false, const SPtr<ct::CommandBuffer>& commandBuffer = nullptr) = 0;
111
112 /**
113 * Copy data from the provided buffer into this buffer. If buffers are not the same size, smaller size will be used.
114 *
115 * @param[in] srcBuffer Hardware buffer to copy from.
116 * @param[in] commandBuffer Command buffer to queue the copy operation on. If null, main command buffer is
117 * used.
118 */
119 virtual void copyData(HardwareBuffer& srcBuffer, const SPtr<ct::CommandBuffer>& commandBuffer = nullptr)
120 {
121 UINT32 sz = std::min(getSize(), srcBuffer.getSize());
122 copyData(srcBuffer, 0, 0, sz, true, commandBuffer);
123 }
124
125 /** Returns the size of this buffer in bytes. */
126 UINT32 getSize() const { return mSize; }
127
128 /** Returns whether or not this buffer is currently locked. */
129 bool isLocked() const { return mIsLocked; }
130
131 /** Returns a mask signifying on which devices has been this buffer created on. */
132 GpuDeviceFlags getDeviceMask() const { return mDeviceMask; }
133
134 protected:
135 friend class HardwareBufferManager;
136
137 /**
138 * Constructs a new buffer.
139 *
140 * @param[in] size Size of the buffer, in bytes.
141 * @param[in] usage Hint on how the buffer is intended to be used.
142 * @param[in] deviceMask Mask that determines on which GPU devices should the object be created on.
143 */
144 HardwareBuffer(UINT32 size, GpuBufferUsage usage, GpuDeviceFlags deviceMask)
145 : mSize(size), mUsage(usage), mDeviceMask(deviceMask)
146 { }
147
148 /** @copydoc lock */
149 virtual void* map(UINT32 offset, UINT32 length, GpuLockOptions options, UINT32 deviceIdx,
150 UINT32 queueIdx) { return nullptr; }
151
152 /** @copydoc unlock */
153 virtual void unmap() { }
154
155 protected:
156 UINT32 mSize;
157 GpuBufferUsage mUsage;
158 GpuDeviceFlags mDeviceMask;
159
160 bool mIsLocked = false;
161 };
162
163 /** @} */
164}