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#include "RenderAPI/BsGpuParamBlockBuffer.h"
4#include "RenderAPI/BsHardwareBuffer.h"
5#include "Managers/BsHardwareBufferManager.h"
6#include "Profiling/BsRenderStats.h"
7
8namespace bs
9{
10 GpuParamBlockBuffer::GpuParamBlockBuffer(UINT32 size, GpuBufferUsage usage)
11 :mUsage(usage), mSize(size), mCachedData(nullptr)
12 {
13 if (mSize > 0)
14 {
15 mCachedData = (UINT8*)bs_alloc(mSize);
16 memset(mCachedData, 0, mSize);
17 }
18 }
19
20 GpuParamBlockBuffer::~GpuParamBlockBuffer()
21 {
22 if (mCachedData != nullptr)
23 bs_free(mCachedData);
24 }
25
26 void GpuParamBlockBuffer::write(UINT32 offset, const void* data, UINT32 size)
27 {
28#if BS_DEBUG_MODE
29 if ((offset + size) > mSize)
30 {
31 BS_EXCEPT(InvalidParametersException, "Wanted range is out of buffer bounds. " \
32 "Available range: 0 .. " + toString(mSize) + ". " \
33 "Wanted range: " + toString(offset) + " .. " + toString(offset + size) + ".");
34 }
35#endif
36
37 memcpy(mCachedData + offset, data, size);
38 markCoreDirty();
39 }
40
41 void GpuParamBlockBuffer::read(UINT32 offset, void* data, UINT32 size)
42 {
43#if BS_DEBUG_MODE
44 if ((offset + size) > mSize)
45 {
46 BS_EXCEPT(InvalidParametersException, "Wanted range is out of buffer bounds. " \
47 "Available range: 0 .. " + toString(mSize) + ". " \
48 "Wanted range: " + toString(offset) + " .. " + toString(offset + size) + ".");
49 }
50#endif
51
52 memcpy(data, mCachedData + offset, size);
53 }
54
55 void GpuParamBlockBuffer::zeroOut(UINT32 offset, UINT32 size)
56 {
57#if BS_DEBUG_MODE
58 if ((offset + size) > mSize)
59 {
60 BS_EXCEPT(InvalidParametersException, "Wanted range is out of buffer bounds. " \
61 "Available range: 0 .. " + toString(mSize) + ". " \
62 "Wanted range: " + toString(offset) + " .. " + toString(offset + size) + ".");
63 }
64#endif
65
66 memset(mCachedData + offset, 0, size);
67 markCoreDirty();
68 }
69
70 SPtr<ct::GpuParamBlockBuffer> GpuParamBlockBuffer::getCore() const
71 {
72 return std::static_pointer_cast<ct::GpuParamBlockBuffer>(mCoreSpecific);
73 }
74
75 SPtr<ct::CoreObject> GpuParamBlockBuffer::createCore() const
76 {
77 return ct::HardwareBufferManager::instance().createGpuParamBlockBufferInternal(mSize, mUsage);
78 }
79
80 CoreSyncData GpuParamBlockBuffer::syncToCore(FrameAlloc* allocator)
81 {
82 UINT8* buffer = allocator->alloc(mSize);
83 read(0, buffer, mSize);
84
85 return CoreSyncData(buffer, mSize);
86 }
87
88 SPtr<GpuParamBlockBuffer> GpuParamBlockBuffer::create(UINT32 size, GpuBufferUsage usage)
89 {
90 return HardwareBufferManager::instance().createGpuParamBlockBuffer(size, usage);
91 }
92
93 namespace ct
94 {
95 GpuParamBlockBuffer::GpuParamBlockBuffer(UINT32 size, GpuBufferUsage usage, GpuDeviceFlags deviceMask)
96 :mUsage(usage), mSize(size), mCachedData(nullptr), mGPUBufferDirty(false)
97 {
98 if (mSize > 0)
99 {
100 mCachedData = (UINT8*)bs_alloc(mSize);
101 memset(mCachedData, 0, mSize);
102 }
103 }
104
105 GpuParamBlockBuffer::~GpuParamBlockBuffer()
106 {
107 if (mCachedData != nullptr)
108 bs_free(mCachedData);
109
110 BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_GpuParamBuffer);
111 }
112
113 void GpuParamBlockBuffer::initialize()
114 {
115 BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_GpuParamBuffer);
116
117 CoreObject::initialize();
118 }
119
120 void GpuParamBlockBuffer::write(UINT32 offset, const void* data, UINT32 size)
121 {
122#if BS_DEBUG_MODE
123 if ((offset + size) > mSize)
124 {
125 BS_EXCEPT(InvalidParametersException, "Wanted range is out of buffer bounds. " \
126 "Available range: 0 .. " + toString(mSize) + ". " \
127 "Wanted range: " + toString(offset) + " .. " + toString(offset + size) + ".");
128 }
129#endif
130
131 memcpy(mCachedData + offset, data, size);
132 mGPUBufferDirty = true;
133 }
134
135 void GpuParamBlockBuffer::read(UINT32 offset, void* data, UINT32 size)
136 {
137#if BS_DEBUG_MODE
138 if ((offset + size) > mSize)
139 {
140 BS_EXCEPT(InvalidParametersException, "Wanted range is out of buffer bounds. " \
141 "Available range: 0 .. " + toString(mSize) + ". " \
142 "Wanted range: " + toString(offset) + " .. " + toString(offset + size) + ".");
143 }
144#endif
145
146 memcpy(data, mCachedData + offset, size);
147 }
148
149 void GpuParamBlockBuffer::zeroOut(UINT32 offset, UINT32 size)
150 {
151#if BS_DEBUG_MODE
152 if ((offset + size) > mSize)
153 {
154 BS_EXCEPT(InvalidParametersException, "Wanted range is out of buffer bounds. " \
155 "Available range: 0 .. " + toString(mSize) + ". " \
156 "Wanted range: " + toString(offset) + " .. " + toString(offset + size) + ".");
157 }
158#endif
159
160 memset(mCachedData + offset, 0, size);
161 mGPUBufferDirty = true;
162 }
163
164 void GpuParamBlockBuffer::flushToGPU(UINT32 queueIdx)
165 {
166 if (mGPUBufferDirty)
167 {
168 writeToGPU(mCachedData, queueIdx);
169 mGPUBufferDirty = false;
170 }
171 }
172
173 void GpuParamBlockBuffer::writeToGPU(const UINT8* data, UINT32 queueIdx)
174 {
175 mBuffer->writeData(0, mSize, data, BWT_DISCARD, queueIdx);
176
177 BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_GpuParamBuffer);
178 }
179
180 void GpuParamBlockBuffer::syncToCore(const CoreSyncData& data)
181 {
182 assert(mSize == data.getBufferSize());
183
184 write(0, data.getBuffer(), data.getBufferSize());
185 }
186
187 SPtr<GpuParamBlockBuffer> GpuParamBlockBuffer::create(UINT32 size, GpuBufferUsage usage, GpuDeviceFlags deviceMask)
188 {
189 return HardwareBufferManager::instance().createGpuParamBlockBuffer(size, usage, deviceMask);
190 }
191 }
192}
193