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/BsGpuParam.h"
4#include "RenderAPI/BsGpuParams.h"
5#include "RenderAPI/BsGpuParamBlockBuffer.h"
6#include "RenderAPI/BsGpuParamDesc.h"
7#include "RenderAPI/BsRenderAPI.h"
8#include "Debug/BsDebug.h"
9#include "Error/BsException.h"
10#include "Math/BsVector2I.h"
11
12namespace bs
13{
14 template<class T, bool Core>
15 TGpuDataParam<T, Core>::TGpuDataParam()
16 :mParamDesc(nullptr)
17 { }
18
19 template<class T, bool Core>
20 TGpuDataParam<T, Core>::TGpuDataParam(GpuParamDataDesc* paramDesc, const GpuParamsType& parent)
21 :mParent(parent), mParamDesc(paramDesc)
22 { }
23
24 template<class T, bool Core>
25 void TGpuDataParam<T, Core>::set(const T& value, UINT32 arrayIdx) const
26 {
27 if (mParent == nullptr)
28 return;
29
30 GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSet, mParamDesc->paramBlockSlot);
31 if (paramBlock == nullptr)
32 return;
33
34#if BS_DEBUG_MODE
35 if (arrayIdx >= mParamDesc->arraySize)
36 {
37 BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
38 toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
39 }
40#endif
41
42 UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
43 UINT32 sizeBytes = std::min(elementSizeBytes, (UINT32)sizeof(T)); // Truncate if it doesn't fit within parameter size
44
45 const bool transposeMatrices = ct::gCaps().conventions.matrixOrder == Conventions::MatrixOrder::ColumnMajor;
46 if (TransposePolicy<T>::transposeEnabled(transposeMatrices))
47 {
48 auto transposed = TransposePolicy<T>::transpose(value);
49 paramBlock->write((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), &transposed, sizeBytes);
50 }
51 else
52 paramBlock->write((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), &value, sizeBytes);
53
54 // Set unused bytes to 0
55 if (sizeBytes < elementSizeBytes)
56 {
57 UINT32 diffSize = elementSizeBytes - sizeBytes;
58 paramBlock->zeroOut((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32) + sizeBytes, diffSize);
59 }
60
61 mParent->_markCoreDirty();
62 }
63
64 template<class T, bool Core>
65 T TGpuDataParam<T, Core>::get(UINT32 arrayIdx) const
66 {
67 if (mParent == nullptr)
68 return T();
69
70 GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSet, mParamDesc->paramBlockSlot);
71 if (paramBlock == nullptr)
72 return T();
73
74#if BS_DEBUG_MODE
75 if (arrayIdx >= mParamDesc->arraySize)
76 {
77 BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
78 toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
79 }
80#endif
81
82 UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
83 UINT32 sizeBytes = std::min(elementSizeBytes, (UINT32)sizeof(T));
84
85 T value;
86 paramBlock->read((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), &value, sizeBytes);
87
88 return value;
89 }
90
91 template<bool Core>
92 TGpuParamStruct<Core>::TGpuParamStruct()
93 :mParamDesc(nullptr)
94 { }
95
96 template<bool Core>
97 TGpuParamStruct<Core>::TGpuParamStruct(GpuParamDataDesc* paramDesc, const GpuParamsType& parent)
98 :mParent(parent), mParamDesc(paramDesc)
99 { }
100
101 template<bool Core>
102 void TGpuParamStruct<Core>::set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx) const
103 {
104 if (mParent == nullptr)
105 return;
106
107 GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSet, mParamDesc->paramBlockSlot);
108 if (paramBlock == nullptr)
109 return;
110
111 UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
112
113#if BS_DEBUG_MODE
114 if (sizeBytes > elementSizeBytes)
115 {
116 LOGWRN("Provided element size larger than maximum element size. Maximum size: " +
117 toString(elementSizeBytes) + ". Supplied size: " + toString(sizeBytes));
118 }
119
120 if (arrayIdx >= mParamDesc->arraySize)
121 {
122 BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
123 toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
124 }
125#endif
126
127 sizeBytes = std::min(elementSizeBytes, sizeBytes);
128
129 paramBlock->write((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), value, sizeBytes);
130
131 // Set unused bytes to 0
132 if (sizeBytes < elementSizeBytes)
133 {
134 UINT32 diffSize = elementSizeBytes - sizeBytes;
135 paramBlock->zeroOut((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32) + sizeBytes, diffSize);
136 }
137
138 mParent->_markCoreDirty();
139 }
140
141 template<bool Core>
142 void TGpuParamStruct<Core>::get(void* value, UINT32 sizeBytes, UINT32 arrayIdx) const
143 {
144 if (mParent == nullptr)
145 return;
146
147 GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSet, mParamDesc->paramBlockSlot);
148 if (paramBlock == nullptr)
149 return;
150
151 UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
152
153#if BS_DEBUG_MODE
154 if (sizeBytes > elementSizeBytes)
155 {
156 LOGWRN("Provided element size larger than maximum element size. Maximum size: " +
157 toString(elementSizeBytes) + ". Supplied size: " + toString(sizeBytes));
158 }
159
160 if (arrayIdx >= mParamDesc->arraySize)
161 {
162 BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
163 toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
164 }
165#endif
166 sizeBytes = std::min(elementSizeBytes, sizeBytes);
167
168 paramBlock->read((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), value, sizeBytes);
169 }
170
171 template<bool Core>
172 UINT32 TGpuParamStruct<Core>::getElementSize() const
173 {
174 if (mParent == nullptr)
175 return 0;
176
177 return mParamDesc->elementSize * sizeof(UINT32);
178 }
179
180 template<bool Core>
181 TGpuParamTexture<Core>::TGpuParamTexture()
182 :mParamDesc(nullptr)
183 { }
184
185 template<bool Core>
186 TGpuParamTexture<Core>::TGpuParamTexture(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent)
187 :mParent(parent), mParamDesc(paramDesc)
188 { }
189
190 template<bool Core>
191 void TGpuParamTexture<Core>::set(const TextureType& texture, const TextureSurface& surface) const
192 {
193 if (mParent == nullptr)
194 return;
195
196 mParent->setTexture(mParamDesc->set, mParamDesc->slot, texture, surface);
197
198 mParent->_markResourcesDirty();
199 mParent->_markCoreDirty();
200 }
201
202 template<bool Core>
203 typename TGpuParamTexture<Core>::TextureType TGpuParamTexture<Core>::get() const
204 {
205 if (mParent == nullptr)
206 return TextureType();
207
208 return mParent->getTexture(mParamDesc->set, mParamDesc->slot);
209 }
210
211 template<bool Core>
212 TGpuParamBuffer<Core>::TGpuParamBuffer()
213 :mParamDesc(nullptr)
214 { }
215
216 template<bool Core>
217 TGpuParamBuffer<Core>::TGpuParamBuffer(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent)
218 : mParent(parent), mParamDesc(paramDesc)
219 { }
220
221 template<bool Core>
222 void TGpuParamBuffer<Core>::set(const BufferType& buffer) const
223 {
224 if (mParent == nullptr)
225 return;
226
227 mParent->setBuffer(mParamDesc->set, mParamDesc->slot, buffer);
228
229 mParent->_markResourcesDirty();
230 mParent->_markCoreDirty();
231 }
232
233 template<bool Core>
234 typename TGpuParamBuffer<Core>::BufferType TGpuParamBuffer<Core>::get() const
235 {
236 if (mParent == nullptr)
237 return BufferType();
238
239 return mParent->getBuffer(mParamDesc->set, mParamDesc->slot);
240 }
241
242 template<bool Core>
243 TGpuParamLoadStoreTexture<Core>::TGpuParamLoadStoreTexture()
244 :mParamDesc(nullptr)
245 { }
246
247 template<bool Core>
248 TGpuParamLoadStoreTexture<Core>::TGpuParamLoadStoreTexture(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent)
249 :mParent(parent), mParamDesc(paramDesc)
250 { }
251
252 template<bool Core>
253 void TGpuParamLoadStoreTexture<Core>::set(const TextureType& texture, const TextureSurface& surface) const
254 {
255 if (mParent == nullptr)
256 return;
257
258 mParent->setLoadStoreTexture(mParamDesc->set, mParamDesc->slot, texture, surface);
259
260 mParent->_markResourcesDirty();
261 mParent->_markCoreDirty();
262 }
263
264 template<bool Core>
265 typename TGpuParamLoadStoreTexture<Core>::TextureType TGpuParamLoadStoreTexture<Core>::get() const
266 {
267 if (mParent == nullptr)
268 return TextureType();
269
270 return mParent->getTexture(mParamDesc->set, mParamDesc->slot);
271 }
272
273 template<bool Core>
274 TGpuParamSampState<Core>::TGpuParamSampState()
275 :mParamDesc(nullptr)
276 { }
277
278 template<bool Core>
279 TGpuParamSampState<Core>::TGpuParamSampState(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent)
280 :mParent(parent), mParamDesc(paramDesc)
281 { }
282
283 template<bool Core>
284 void TGpuParamSampState<Core>::set(const SamplerStateType& samplerState) const
285 {
286 if (mParent == nullptr)
287 return;
288
289 mParent->setSamplerState(mParamDesc->set, mParamDesc->slot, samplerState);
290
291 mParent->_markResourcesDirty();
292 mParent->_markCoreDirty();
293 }
294
295 template<bool Core>
296 typename TGpuParamSampState<Core>::SamplerStateType TGpuParamSampState<Core>::get() const
297 {
298 if (mParent == nullptr)
299 return SamplerStateType();
300
301 return mParent->getSamplerState(mParamDesc->set, mParamDesc->slot);
302 }
303
304 template class TGpuDataParam < float, false > ;
305 template class TGpuDataParam < int, false >;
306 template class TGpuDataParam < Color, false > ;
307 template class TGpuDataParam < Vector2, false > ;
308 template class TGpuDataParam < Vector3, false > ;
309 template class TGpuDataParam < Vector4, false > ;
310 template class TGpuDataParam < Vector2I, false > ;
311 template class TGpuDataParam < Vector3I, false > ;
312 template class TGpuDataParam < Vector4I, false > ;
313 template class TGpuDataParam < Matrix2, false >;
314 template class TGpuDataParam < Matrix2x3, false >;
315 template class TGpuDataParam < Matrix2x4, false >;
316 template class TGpuDataParam < Matrix3, false > ;
317 template class TGpuDataParam < Matrix3x2, false > ;
318 template class TGpuDataParam < Matrix3x4, false > ;
319 template class TGpuDataParam < Matrix4, false > ;
320 template class TGpuDataParam < Matrix4x2, false >;
321 template class TGpuDataParam < Matrix4x3, false >;
322
323 template class TGpuDataParam < float, true > ;
324 template class TGpuDataParam < int, true >;
325 template class TGpuDataParam < Color, true > ;
326 template class TGpuDataParam < Vector2, true > ;
327 template class TGpuDataParam < Vector3, true > ;
328 template class TGpuDataParam < Vector4, true > ;
329 template class TGpuDataParam < Vector2I, true > ;
330 template class TGpuDataParam < Vector3I, true > ;
331 template class TGpuDataParam < Vector4I, true > ;
332 template class TGpuDataParam < Matrix2, true >;
333 template class TGpuDataParam < Matrix2x3, true >;
334 template class TGpuDataParam < Matrix2x4, true >;
335 template class TGpuDataParam < Matrix3, true > ;
336 template class TGpuDataParam < Matrix3x2, true >;
337 template class TGpuDataParam < Matrix3x4, true >;
338 template class TGpuDataParam < Matrix4, true > ;
339 template class TGpuDataParam < Matrix4x2, true >;
340 template class TGpuDataParam < Matrix4x3, true >;
341
342 template class TGpuParamStruct < false > ;
343 template class TGpuParamStruct < true > ;
344
345 template class TGpuParamTexture < false > ;
346 template class TGpuParamTexture < true > ;
347
348 template class TGpuParamBuffer < false >;
349 template class TGpuParamBuffer < true >;
350
351 template class TGpuParamSampState < false > ;
352 template class TGpuParamSampState < true > ;
353
354 template class TGpuParamLoadStoreTexture < false > ;
355 template class TGpuParamLoadStoreTexture < true > ;
356}