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#include "Reflection/BsRTTIType.h"
7#include "Material/BsShader.h"
8#include "Material/BsMaterial.h"
9
10namespace bs
11{
12 /** @cond RTTI */
13 /** @addtogroup RTTI-Impl-Core
14 * @{
15 */
16
17 template<> struct RTTIPlainType<SHADER_DATA_PARAM_DESC>
18 {
19 enum { id = TID_SHADER_DATA_PARAM_DESC }; enum { hasDynamicSize = 1 };
20
21 static void toMemory(const SHADER_DATA_PARAM_DESC& data, char* memory)
22 {
23 static constexpr UINT32 VERSION = 1;
24
25 UINT32 size = getDynamicSize(data);
26
27 UINT32 curSize = sizeof(UINT32);
28 memcpy(memory, &size, curSize);
29 memory += curSize;
30
31 memory = rttiWriteElem(data.arraySize, memory);
32 memory = rttiWriteElem(data.rendererSemantic, memory);
33 memory = rttiWriteElem(data.type, memory);
34 memory = rttiWriteElem(data.name, memory);
35 memory = rttiWriteElem(data.gpuVariableName, memory);
36 memory = rttiWriteElem(data.elementSize, memory);
37 memory = rttiWriteElem(data.defaultValueIdx, memory);
38 memory = rttiWriteElem(VERSION, memory);
39 memory = rttiWriteElem(data.attribIdx, memory);
40 }
41
42 static UINT32 fromMemory(SHADER_DATA_PARAM_DESC& data, char* memory)
43 {
44 UINT32 size;
45 memcpy(&size, memory, sizeof(UINT32));
46 memory += sizeof(UINT32);
47
48 UINT32 sizeRead = sizeof(UINT32);
49 memory = rttiReadElem(data.arraySize, memory, sizeRead);
50 memory = rttiReadElem(data.rendererSemantic, memory, sizeRead);
51 memory = rttiReadElem(data.type, memory, sizeRead);
52 memory = rttiReadElem(data.name, memory, sizeRead);
53 memory = rttiReadElem(data.gpuVariableName, memory, sizeRead);
54 memory = rttiReadElem(data.elementSize, memory, sizeRead);
55 memory = rttiReadElem(data.defaultValueIdx, memory, sizeRead);
56
57 // There's more to read, meaning we're reading a newer version of the format
58 // (In the first version, version field is missing, so we check this way).
59 if(sizeRead < size)
60 {
61 UINT32 version = 0;
62 memory = rttiReadElem(version, memory);
63 switch(version)
64 {
65 case 1:
66 memory = rttiReadElem(data.attribIdx, memory);
67 break;
68 default:
69 LOGERR("Unknown version. Unable to deserialize.");
70 break;
71 }
72 }
73
74 return size;
75 }
76
77 static UINT32 getDynamicSize(const SHADER_DATA_PARAM_DESC& data)
78 {
79 UINT64 dataSize = rttiGetElemSize(data.arraySize) + rttiGetElemSize(data.rendererSemantic) + rttiGetElemSize(data.type) +
80 rttiGetElemSize(data.name) + rttiGetElemSize(data.gpuVariableName) + rttiGetElemSize(data.elementSize) +
81 rttiGetElemSize(data.defaultValueIdx) + rttiGetElemSize(data.attribIdx) + sizeof(UINT32) * 2;
82
83#if BS_DEBUG_MODE
84 if(dataSize > std::numeric_limits<UINT32>::max())
85 {
86 BS_EXCEPT(InternalErrorException, "Data overflow! Size doesn't fit into 32 bits.");
87 }
88#endif
89
90 return (UINT32)dataSize;
91 }
92 };
93
94 template<> struct RTTIPlainType<SHADER_OBJECT_PARAM_DESC>
95 {
96 enum { id = TID_SHADER_OBJECT_PARAM_DESC }; enum { hasDynamicSize = 1 };
97
98 static void toMemory(const SHADER_OBJECT_PARAM_DESC& data, char* memory)
99 {
100 static constexpr UINT32 VERSION = 1;
101
102 UINT32 size = getDynamicSize(data);
103
104 UINT32 curSize = sizeof(UINT32);
105 memcpy(memory, &size, curSize);
106 memory += curSize;
107
108 memory = rttiWriteElem(data.rendererSemantic, memory);
109 memory = rttiWriteElem(data.type, memory);
110 memory = rttiWriteElem(data.name, memory);
111 memory = rttiWriteElem(data.gpuVariableNames, memory);
112 memory = rttiWriteElem(data.defaultValueIdx, memory);
113 memory = rttiWriteElem(VERSION, memory);
114 memory = rttiWriteElem(data.attribIdx, memory);
115 }
116
117 static UINT32 fromMemory(SHADER_OBJECT_PARAM_DESC& data, char* memory)
118 {
119 UINT32 size;
120 memcpy(&size, memory, sizeof(UINT32));
121 memory += sizeof(UINT32);
122
123 UINT32 sizeRead = sizeof(UINT32);
124 memory = rttiReadElem(data.rendererSemantic, memory, sizeRead);
125 memory = rttiReadElem(data.type, memory, sizeRead);
126 memory = rttiReadElem(data.name, memory, sizeRead);
127 memory = rttiReadElem(data.gpuVariableNames, memory, sizeRead);
128 memory = rttiReadElem(data.defaultValueIdx, memory, sizeRead);
129
130 // There's more to read, meaning we're reading a newer version of the format
131 // (In the first version, version field is missing, so we check this way).
132 if(sizeRead < size)
133 {
134 UINT32 version = 0;
135 memory = rttiReadElem(version, memory);
136 switch(version)
137 {
138 case 1:
139 memory = rttiReadElem(data.attribIdx, memory);
140 break;
141 default:
142 LOGERR("Unknown version. Unable to deserialize.");
143 break;
144 }
145 }
146
147 return size;
148 }
149
150 static UINT32 getDynamicSize(const SHADER_OBJECT_PARAM_DESC& data)
151 {
152 UINT64 dataSize = rttiGetElemSize(data.rendererSemantic) + rttiGetElemSize(data.type) +
153 rttiGetElemSize(data.name) + rttiGetElemSize(data.gpuVariableNames) +
154 rttiGetElemSize(data.defaultValueIdx) + rttiGetElemSize(data.attribIdx) + sizeof(UINT32) * 2;
155
156#if BS_DEBUG_MODE
157 if(dataSize > std::numeric_limits<UINT32>::max())
158 {
159 BS_EXCEPT(InternalErrorException, "Data overflow! Size doesn't fit into 32 bits.");
160 }
161#endif
162
163 return (UINT32)dataSize;
164 }
165 };
166
167 template<> struct RTTIPlainType<SHADER_PARAM_BLOCK_DESC>
168 {
169 enum { id = TID_SHADER_PARAM_BLOCK_DESC }; enum { hasDynamicSize = 1 };
170
171 static void toMemory(const SHADER_PARAM_BLOCK_DESC& data, char* memory)
172 {
173 UINT32 size = getDynamicSize(data);
174
175 UINT32 curSize = sizeof(UINT32);
176 memcpy(memory, &size, curSize);
177 memory += curSize;
178
179 memory = rttiWriteElem(data.shared, memory);
180 memory = rttiWriteElem(data.usage, memory);
181 memory = rttiWriteElem(data.name, memory);
182 rttiWriteElem(data.rendererSemantic, memory);
183 }
184
185 static UINT32 fromMemory(SHADER_PARAM_BLOCK_DESC& data, char* memory)
186 {
187 UINT32 size;
188 memcpy(&size, memory, sizeof(UINT32));
189 memory += sizeof(UINT32);
190
191 memory = rttiReadElem(data.shared, memory);
192 memory = rttiReadElem(data.usage, memory);
193 memory = rttiReadElem(data.name, memory);
194 rttiReadElem(data.rendererSemantic, memory);
195
196 return size;
197 }
198
199 static UINT32 getDynamicSize(const SHADER_PARAM_BLOCK_DESC& data)
200 {
201 UINT64 dataSize = rttiGetElemSize(data.shared) + rttiGetElemSize(data.usage) +
202 rttiGetElemSize(data.name) + rttiGetElemSize(data.rendererSemantic) + sizeof(UINT32);
203
204#if BS_DEBUG_MODE
205 if(dataSize > std::numeric_limits<UINT32>::max())
206 {
207 BS_EXCEPT(InternalErrorException, "Data overflow! Size doesn't fit into 32 bits.");
208 }
209#endif
210
211 return (UINT32)dataSize;
212 }
213 };
214
215 template<> struct RTTIPlainType<SHADER_PARAM_ATTRIBUTE>
216 {
217 enum { id = TID_SHADER_PARAM_ATTRIBUTE }; enum { hasDynamicSize = 1 };
218
219 static void toMemory(const SHADER_PARAM_ATTRIBUTE& data, char* memory)
220 {
221 static constexpr UINT32 VERSION = 0;
222
223 UINT32 size = getDynamicSize(data);
224
225 UINT32 curSize = sizeof(UINT32);
226 memcpy(memory, &size, curSize);
227 memory += curSize;
228
229 memory = rttiWriteElem(VERSION, memory);
230 memory = rttiWriteElem(data.type, memory);
231 memory = rttiWriteElem(data.value, memory);
232 memory = rttiWriteElem(data.nextParamIdx, memory);
233 }
234
235 static UINT32 fromMemory(SHADER_PARAM_ATTRIBUTE& data, char* memory)
236 {
237 UINT32 size;
238 memcpy(&size, memory, sizeof(UINT32));
239 memory += sizeof(UINT32);
240
241 UINT32 version = 0;
242 memory = rttiReadElem(version, memory);
243
244 switch(version)
245 {
246 case 0:
247 memory = rttiReadElem(data.type, memory);
248 memory = rttiReadElem(data.value, memory);
249 memory = rttiReadElem(data.nextParamIdx, memory);
250 break;
251 default:
252 LOGERR("Unknown version. Unable to deserialize.");
253 break;
254 }
255
256 return size;
257 }
258
259 static UINT32 getDynamicSize(const SHADER_PARAM_ATTRIBUTE& data)
260 {
261 UINT64 dataSize = rttiGetElemSize(data.type) + rttiGetElemSize(data.value) +
262 rttiGetElemSize(data.nextParamIdx) + sizeof(UINT32) * 2;
263
264#if BS_DEBUG_MODE
265 if(dataSize > std::numeric_limits<UINT32>::max())
266 {
267 BS_EXCEPT(InternalErrorException, "Data overflow! Size doesn't fit into 32 bits.");
268 }
269#endif
270
271 return (UINT32)dataSize;
272 }
273 };
274
275 template<> struct RTTIPlainType<ShaderVariationParamValue>
276 {
277 enum { id = TID_ShaderVariationParamValue }; enum { hasDynamicSize = 1 };
278
279 /** @copydoc RTTIPlainType::toMemory */
280 static void toMemory(const ShaderVariationParamValue& data, char* memory)
281 {
282 static constexpr UINT8 VERSION = 0;
283
284 UINT32 size = sizeof(UINT32);
285 char* memoryStart = memory;
286 memory += sizeof(UINT32);
287
288 memory = rttiWriteElem(VERSION, memory, size);
289 memory = rttiWriteElem(data.name, memory, size);
290 memory = rttiWriteElem(data.value, memory, size);
291
292 memcpy(memoryStart, &size, sizeof(UINT32));
293 }
294
295 /** @copydoc RTTIPlainType::fromMemory */
296 static UINT32 fromMemory(ShaderVariationParamValue& data, char* memory)
297 {
298 UINT32 size = 0;
299 memory = rttiReadElem(size, memory);
300
301 UINT8 version;
302 memory = rttiReadElem(version, memory);
303 assert(version == 0);
304
305 memory = rttiReadElem(data.name, memory);
306 memory = rttiReadElem(data.value, memory);
307
308 return size;
309 }
310
311 /** @copydoc RTTIPlainType::getDynamicSize */
312 static UINT32 getDynamicSize(const ShaderVariationParamValue& data)
313 {
314 UINT64 dataSize = sizeof(UINT8) + sizeof(UINT32);
315 dataSize += rttiGetElemSize(data.name);
316 dataSize += rttiGetElemSize(data.value);
317
318 assert(dataSize <= std::numeric_limits<UINT32>::max());
319
320 return (UINT32)dataSize;
321 }
322 };
323
324 template<> struct RTTIPlainType<ShaderVariationParamInfo>
325 {
326 enum { id = TID_ShaderVariationParamInfo }; enum { hasDynamicSize = 1 };
327
328 /** @copydoc RTTIPlainType::toMemory */
329 static void toMemory(const ShaderVariationParamInfo& data, char* memory)
330 {
331 static constexpr UINT8 VERSION = 0;
332
333 UINT32 size = sizeof(UINT32);
334 char* memoryStart = memory;
335 memory += sizeof(UINT32);
336
337 memory = rttiWriteElem(VERSION, memory, size);
338 memory = rttiWriteElem(data.name, memory, size);
339 memory = rttiWriteElem(data.identifier, memory, size);
340 memory = rttiWriteElem(data.isInternal, memory, size);
341 memory = rttiWriteElem(data.values, memory, size);
342
343 memcpy(memoryStart, &size, sizeof(UINT32));
344 }
345
346 /** @copydoc RTTIPlainType::fromMemory */
347 static UINT32 fromMemory(ShaderVariationParamInfo& data, char* memory)
348 {
349 UINT32 size = 0;
350 memory = rttiReadElem(size, memory);
351
352 UINT8 version;
353 memory = rttiReadElem(version, memory);
354 assert(version == 0);
355
356 memory = rttiReadElem(data.name, memory);
357 memory = rttiReadElem(data.identifier, memory);
358 memory = rttiReadElem(data.isInternal, memory);
359 memory = rttiReadElem(data.values, memory);
360
361 return size;
362 }
363
364 /** @copydoc RTTIPlainType::getDynamicSize */
365 static UINT32 getDynamicSize(const ShaderVariationParamInfo& data)
366 {
367 UINT64 dataSize = sizeof(UINT8) + sizeof(UINT32);
368 dataSize += rttiGetElemSize(data.name);
369 dataSize += rttiGetElemSize(data.identifier);
370 dataSize += rttiGetElemSize(data.isInternal);
371 dataSize += rttiGetElemSize(data.values);
372
373 assert(dataSize <= std::numeric_limits<UINT32>::max());
374
375 return (UINT32)dataSize;
376 }
377 };
378
379 class BS_CORE_EXPORT SubShaderRTTI : public RTTIType<SubShader, IReflectable, SubShaderRTTI>
380 {
381 private:
382 BS_BEGIN_RTTI_MEMBERS
383 BS_RTTI_MEMBER_PLAIN(name, 0)
384 BS_RTTI_MEMBER_REFLPTR(shader, 1)
385 BS_END_RTTI_MEMBERS
386
387 public:
388 const String& getRTTIName() override
389 {
390 static String name = "SubShader";
391 return name;
392 }
393
394 UINT32 getRTTIId() override
395 {
396 return TID_SubShader;
397 }
398
399 SPtr<IReflectable> newRTTIObject() override
400 {
401 return bs_shared_ptr_new<SubShader>();
402 }
403 };
404
405 class BS_CORE_EXPORT ShaderRTTI : public RTTIType<Shader, Resource, ShaderRTTI>
406 {
407 private:
408 BS_BEGIN_RTTI_MEMBERS
409 BS_RTTI_MEMBER_REFLPTR_ARRAY_NAMED(mTechniques, mDesc.techniques, 0)
410 BS_RTTI_MEMBER_PLAIN(mName, 1)
411
412 BS_RTTI_MEMBER_PLAIN_NAMED(mQueueSortType, mDesc.queueSortType, 7)
413 BS_RTTI_MEMBER_PLAIN_NAMED(mQueuePriority, mDesc.queuePriority, 8)
414 BS_RTTI_MEMBER_PLAIN_NAMED(mSeparablePasses, mDesc.separablePasses, 9)
415
416 BS_RTTI_MEMBER_PLAIN_NAMED(mDataDefaultValues, mDesc.dataDefaultValues, 10)
417 BS_RTTI_MEMBER_REFL_ARRAY_NAMED(mTextureDefaultValues, mDesc.textureDefaultValues, 11)
418 BS_RTTI_MEMBER_REFLPTR_ARRAY_NAMED(mSamplerDefaultValues, mDesc.samplerDefaultValues, 12)
419
420 BS_RTTI_MEMBER_PLAIN_NAMED(mFlags, mDesc.flags, 13)
421 BS_RTTI_MEMBER_REFL_ARRAY_NAMED(mSubShaders, mDesc.subShaders, 14)
422
423 BS_RTTI_MEMBER_PLAIN_ARRAY_NAMED(mParamAttributes, mDesc.paramAttributes, 15)
424 BS_RTTI_MEMBER_PLAIN_ARRAY_NAMED(mVariationParams, mDesc.variationParams, 16)
425 BS_END_RTTI_MEMBERS
426
427 SHADER_DATA_PARAM_DESC& getDataParam(Shader* obj, UINT32 idx)
428 {
429 auto iter = obj->mDesc.dataParams.begin();
430 for(UINT32 i = 0; i < idx; i++) ++iter;
431
432 return iter->second;
433 }
434
435 void setDataParam(Shader* obj, UINT32 idx, SHADER_DATA_PARAM_DESC& val) { obj->mDesc.dataParams[val.name] = val; }
436 UINT32 getDataParamsArraySize(Shader* obj) { return (UINT32)obj->mDesc.dataParams.size(); }
437 void setDataParamsArraySize(Shader* obj, UINT32 size) { } // Do nothing
438
439 SHADER_OBJECT_PARAM_DESC& getTextureParam(Shader* obj, UINT32 idx)
440 {
441 auto iter = obj->mDesc.textureParams.begin();
442 for(UINT32 i = 0; i < idx; i++) ++iter;
443
444 return iter->second;
445 }
446
447 void setTextureParam(Shader* obj, UINT32 idx, SHADER_OBJECT_PARAM_DESC& val) { obj->mDesc.textureParams[val.name] = val; }
448 UINT32 getTextureParamsArraySize(Shader* obj) { return (UINT32)obj->mDesc.textureParams.size(); }
449 void setTextureParamsArraySize(Shader* obj, UINT32 size) { } // Do nothing
450
451 SHADER_OBJECT_PARAM_DESC& getSamplerParam(Shader* obj, UINT32 idx)
452 {
453 auto iter = obj->mDesc.samplerParams.begin();
454 for (UINT32 i = 0; i < idx; i++) ++iter;
455
456 return iter->second;
457 }
458
459 void setSamplerParam(Shader* obj, UINT32 idx, SHADER_OBJECT_PARAM_DESC& val) { obj->mDesc.samplerParams[val.name] = val; }
460 UINT32 getSamplerParamsArraySize(Shader* obj) { return (UINT32)obj->mDesc.samplerParams.size(); }
461 void setSamplerParamsArraySize(Shader* obj, UINT32 size) { } // Do nothing
462
463 SHADER_OBJECT_PARAM_DESC& getBufferParam(Shader* obj, UINT32 idx)
464 {
465 auto iter = obj->mDesc.bufferParams.begin();
466 for (UINT32 i = 0; i < idx; i++) ++iter;
467
468 return iter->second;
469 }
470
471 void setBufferParam(Shader* obj, UINT32 idx, SHADER_OBJECT_PARAM_DESC& val) { obj->mDesc.bufferParams[val.name] = val; }
472 UINT32 getBufferParamsArraySize(Shader* obj) { return (UINT32)obj->mDesc.bufferParams.size(); }
473 void setBufferParamsArraySize(Shader* obj, UINT32 size) { } // Do nothing
474
475 SHADER_PARAM_BLOCK_DESC& getParamBlock(Shader* obj, UINT32 idx)
476 {
477 auto iter = obj->mDesc.paramBlocks.begin();
478 for (UINT32 i = 0; i < idx; i++) ++iter;
479
480 return iter->second;
481 }
482
483 void setParamBlock(Shader* obj, UINT32 idx, SHADER_PARAM_BLOCK_DESC& val) { obj->mDesc.paramBlocks[val.name] = val; }
484 UINT32 getParamBlocksArraySize(Shader* obj) { return (UINT32)obj->mDesc.paramBlocks.size(); }
485 void setParamBlocksArraySize(Shader* obj, UINT32 size) { } // Do nothing
486
487 public:
488 ShaderRTTI()
489 {
490 addPlainArrayField("mDataParams", 2, &ShaderRTTI::getDataParam, &ShaderRTTI::getDataParamsArraySize,
491 &ShaderRTTI::setDataParam, &ShaderRTTI::setDataParamsArraySize);
492 addPlainArrayField("mTextureParams", 3, &ShaderRTTI::getTextureParam, &ShaderRTTI::getTextureParamsArraySize,
493 &ShaderRTTI::setTextureParam, &ShaderRTTI::setTextureParamsArraySize);
494 addPlainArrayField("mSamplerParams", 4, &ShaderRTTI::getSamplerParam, &ShaderRTTI::getSamplerParamsArraySize,
495 &ShaderRTTI::setSamplerParam, &ShaderRTTI::setSamplerParamsArraySize);
496 addPlainArrayField("mBufferParams", 5, &ShaderRTTI::getBufferParam, &ShaderRTTI::getBufferParamsArraySize,
497 &ShaderRTTI::setBufferParam, &ShaderRTTI::setBufferParamsArraySize);
498 addPlainArrayField("mParamBlocks", 6, &ShaderRTTI::getParamBlock, &ShaderRTTI::getParamBlocksArraySize,
499 &ShaderRTTI::setParamBlock, &ShaderRTTI::setParamBlocksArraySize);
500 }
501
502 void onDeserializationEnded(IReflectable* obj, SerializationContext* context) override
503 {
504 Shader* shader = static_cast<Shader*>(obj);
505 shader->initialize();
506 }
507
508 const String& getRTTIName() override
509 {
510 static String name = "Shader";
511 return name;
512 }
513
514 UINT32 getRTTIId() override
515 {
516 return TID_Shader;
517 }
518
519 SPtr<IReflectable> newRTTIObject() override
520 {
521 return Shader::createEmpty();
522 }
523 };
524
525 class BS_CORE_EXPORT ShaderMetaDataRTTI : public RTTIType < ShaderMetaData, ResourceMetaData, ShaderMetaDataRTTI >
526 {
527 private:
528 Vector<String>& getIncludes(ShaderMetaData* obj) { return obj->includes; }
529 void setIncludes(ShaderMetaData* obj, Vector<String>& includes) { obj->includes = includes; }
530
531 public:
532 ShaderMetaDataRTTI()
533 {
534 addPlainField("includes", 0, &ShaderMetaDataRTTI::getIncludes, &ShaderMetaDataRTTI::setIncludes);
535 }
536
537 const String& getRTTIName() override
538 {
539 static String name = "ShaderMetaData";
540 return name;
541 }
542
543 UINT32 getRTTIId() override
544 {
545 return TID_ShaderMetaData;
546 }
547
548 SPtr<IReflectable> newRTTIObject() override
549 {
550 return bs_shared_ptr_new<ShaderMetaData>();
551 }
552 };
553
554 /** @} */
555 /** @endcond */
556}
557