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/BsIReflectable.h"
7#include "Allocators/BsStaticAlloc.h"
8#include "Math/BsVector2.h"
9#include "RenderAPI/BsGpuParams.h"
10#include "Allocators/BsPoolAlloc.h"
11
12namespace bs
13{
14 template<class T>
15 class TAnimationCurve;
16 class ColorGradient;
17
18 /** @addtogroup Material-Internal
19 * @{
20 */
21
22 struct SHADER_DATA_PARAM_DESC;
23 struct SHADER_OBJECT_PARAM_DESC;
24 struct SHADER_PARAM_ATTRIBUTE;
25
26 /** Types of textures that can be assigned to a material texture parameter. */
27 enum class MateralParamTextureType
28 {
29 /** Normal texture (static image, entire UV range). */
30 Normal,
31 /** Texture that is writeable by the material using unordered writes. */
32 LoadStore,
33 /** Sprite texture (either a subset of a larger texture, or an animated texture). */
34 Sprite
35 };
36
37 /** Common functionality for MaterialParams and ct::MaterialParams. */
38 class BS_CORE_EXPORT MaterialParamsBase
39 {
40 public:
41 /** Type of material parameter. */
42 enum class ParamType
43 {
44 Data, Texture, Sampler, Buffer
45 };
46
47 /** Result codes for getParam method. */
48 enum class GetParamResult
49 {
50 Success,
51 NotFound,
52 InvalidType,
53 IndexOutOfBounds
54 };
55
56 /** Meta-data about a parameter. */
57 struct ParamData
58 {
59 ParamType type;
60 GpuParamDataType dataType;
61 UINT32 index;
62 UINT32 arraySize;
63 mutable UINT64 version;
64 };
65
66 /** Information about a single data parameter in a material. */
67 struct DataParamInfo
68 {
69 UINT32 offset;
70
71 TAnimationCurve<float>* floatCurve;
72 ColorGradient* colorGradient;
73 UINT32 spriteTextureIdx;
74 };
75
76 /**
77 * Creates a new material params object and initializes enough room for parameters from the provided parameter data.
78 */
79 MaterialParamsBase(
80 const Map<String, SHADER_DATA_PARAM_DESC>& dataParams,
81 const Map<String, SHADER_OBJECT_PARAM_DESC>& textureParams,
82 const Map<String, SHADER_OBJECT_PARAM_DESC>& bufferParams,
83 const Map<String, SHADER_OBJECT_PARAM_DESC>& samplerParams,
84 UINT64 initialParamVersion
85 );
86
87 /** Constructor for serialization use only. */
88 MaterialParamsBase() = default;
89 virtual ~MaterialParamsBase();
90
91 /**
92 * Returns the value of a shader data parameter with the specified name at the specified array index. If the
93 * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
94 *
95 * @param[in] name Name of the shader parameter.
96 * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
97 * @param[out] output If successful, value of the parameter.
98 *
99 * @tparam T Native type of the parameter.
100 */
101 template <typename T>
102 void getDataParam(const String& name, UINT32 arrayIdx, T& output) const
103 {
104 GpuParamDataType dataType = TGpuDataParamInfo<T>::TypeId;
105
106 const ParamData* param = nullptr;
107 auto result = getParamData(name, ParamType::Data, dataType, arrayIdx, &param);
108 if (result != GetParamResult::Success)
109 return;
110
111 const DataParamInfo& paramInfo = mDataParams[param->index + arrayIdx];
112
113 const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
114 UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
115
116 memcpy(output, &mDataParamsBuffer[paramInfo.offset], sizeof(paramTypeSize));
117 }
118
119 /**
120 * Sets the value of a shader data parameter with the specified name at the specified array index. If the
121 * parameter name, index or type is not valid a warning will be logged and output value will not be set.
122 *
123 * @param[in] name Name of the shader parameter.
124 * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
125 * @param[in] input New value of the parameter.
126 *
127 * @tparam T Native type of the parameter.
128 */
129 template <typename T>
130 void setDataParam(const String& name, UINT32 arrayIdx, const T& input) const
131 {
132 GpuParamDataType dataType = TGpuDataParamInfo<T>::TypeId;
133
134 const ParamData* param = nullptr;
135 auto result = getParamData(name, ParamType::Data, dataType, arrayIdx, &param);
136 if (result != GetParamResult::Success)
137 return;
138
139 const DataParamInfo& paramInfo = mDataParams[param->index + arrayIdx];
140
141 const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
142 UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
143
144 memcpy(&mDataParamsBuffer[paramInfo.offset], input, sizeof(paramTypeSize));
145 }
146
147 /**
148 * Returns the animation curve assigned to a shader data parameter with the specified name at the specified array
149 * index. If the parameter name, index or type is not valid a warning will be logged and output value will not be
150 * retrieved. If no curve has been assigned to this parameter then an empty curve is returned.
151 *
152 * @param[in] name Name of the shader parameter.
153 * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
154 * @return Animation curve assigned to the parameter.
155 *
156 * @tparam T Native type of the parameter.
157 */
158 template <typename T>
159 const TAnimationCurve<T>& getCurveParam(const String& name, UINT32 arrayIdx) const
160 {
161 static TAnimationCurve<T> EMPTY_CURVE;
162 GpuParamDataType dataType = TGpuDataParamInfo<T>::TypeId;
163
164 const ParamData* param = nullptr;
165 auto result = getParamData(name, ParamType::Data, dataType, arrayIdx, &param);
166 if (result != GetParamResult::Success)
167 return EMPTY_CURVE;
168
169 return getCurveParam<T>(*param, arrayIdx);
170 }
171
172 /**
173 * Sets an animation curve to a shader data parameter with the specified name at the specified array index. If the
174 * parameter name, index or type is not valid a warning will be logged and output value will not be set.
175 *
176 * @param[in] name Name of the shader parameter.
177 * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
178 * @param[in] input New value of the parameter.
179 *
180 * @tparam T Native type of the parameter.
181 */
182 template <typename T>
183 void setCurveParam(const String& name, UINT32 arrayIdx, TAnimationCurve<T> input) const
184 {
185 GpuParamDataType dataType = TGpuDataParamInfo<T>::TypeId;
186
187 const ParamData* param = nullptr;
188 auto result = getParamData(name, ParamType::Data, dataType, arrayIdx, &param);
189 if (result != GetParamResult::Success)
190 return;
191
192 setCurveParam(*param, arrayIdx, std::move(input));
193 }
194
195 /**
196 * Returns the color gradient assigned to a shader color parameter with the specified name at the specified array
197 * index. If the parameter name, index or type is not valid a warning will be logged and output value will not be
198 * retrieved. If no gradient has been assigned to this parameter then an empty gradient is returned.
199 *
200 * @param[in] name Name of the shader parameter.
201 * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
202 * @return Color gradient assigned to the parameter.
203 */
204 const ColorGradient& getColorGradientParam(const String& name, UINT32 arrayIdx) const;
205
206 /**
207 * Sets a color gradient to a shader color parameter with the specified name at the specified array index. If the
208 * parameter name, index or type is not valid a warning will be logged and output value will not be set.
209 *
210 * @param[in] name Name of the shader parameter.
211 * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
212 * @param[in] input New value of the parameter.
213 */
214 void setColorGradientParam(const String& name, UINT32 arrayIdx, const ColorGradient& input) const;
215
216 /**
217 * Returns an index of the parameter with the specified name. Index can be used in a call to getParamData(UINT32) to
218 * get the actual parameter data.
219 *
220 * @param[in] name Name of the shader parameter.
221 * @return Index of the parameter, or -1 if not found.
222 */
223 UINT32 getParamIndex(const String& name) const;
224
225 /**
226 * Returns an index of the parameter with the specified name. Index can be used in a call to getParamData(UINT32) to
227 * get the actual parameter data.
228 *
229 * @param[in] name Name of the shader parameter.
230 * @param[in] type Type of the parameter retrieve. Error will be logged if actual type of the parameter
231 * doesn't match.
232 * @param[in] dataType Only relevant if the parameter is a data type. Determines exact data type of the parameter
233 * to retrieve.
234 * @param[in] arrayIdx Array index of the entry to retrieve.
235 * @param[out] output Index of the requested parameter, only valid if success is returned.
236 * @return Success or error state of the request.
237 */
238 GetParamResult getParamIndex(const String& name, ParamType type, GpuParamDataType dataType, UINT32 arrayIdx,
239 UINT32& output) const;
240
241 /**
242 * Returns data about a parameter and reports an error if there is a type or size mismatch, or if the parameter
243 * does exist.
244 *
245 * @param[in] name Name of the shader parameter.
246 * @param[in] type Type of the parameter retrieve. Error will be logged if actual type of the parameter
247 * doesn't match.
248 * @param[in] dataType Only relevant if the parameter is a data type. Determines exact data type of the parameter
249 * to retrieve.
250 * @param[in] arrayIdx Array index of the entry to retrieve.
251 * @param[out] output Object describing the parameter with an index to its data. If the parameter was not found
252 * this value is undefined. This value will still be valid if parameter was found but
253 * some other error was reported.
254 * @return Success or error state of the request.
255 */
256 GetParamResult getParamData(const String& name, ParamType type, GpuParamDataType dataType, UINT32 arrayIdx,
257 const ParamData** output) const;
258
259 /**
260 * Returns information about a parameter at the specified global index, as retrieved by getParamIndex().
261 */
262 const ParamData* getParamData(UINT32 index) const { return &mParams[index]; }
263
264 /** Returns the total number of parameters managed by this object. */
265 UINT32 getNumParams() const { return (UINT32)mParams.size(); }
266
267 /**
268 * Logs an error that was reported by getParamData().
269 *
270 * @param[in] errorCode Information about the error.
271 * @param[in] name Name of the shader parameter for which the error occurred.
272 * @param[in] arrayIdx Array index for which the error occurred.
273 */
274 void reportGetParamError(GetParamResult errorCode, const String& name, UINT32 arrayIdx) const;
275
276 /**
277 * Equivalent to getDataParam(const String&, UINT32, T&) except it uses the internal parameter reference
278 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
279 * object.
280 */
281 template <typename T>
282 void getDataParam(const ParamData& param, UINT32 arrayIdx, T& output) const
283 {
284 GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
285
286 const DataParamInfo& paramInfo = mDataParams[param.index + arrayIdx];
287
288 const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
289 UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
290
291 assert(sizeof(output) == paramTypeSize);
292 memcpy(&output, &mDataParamsBuffer[paramInfo.offset], paramTypeSize);
293 }
294
295 /**
296 * Equivalent to setDataParam(const String&, UINT32, T&) except it uses the internal parameter reference
297 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
298 * object.
299 */
300 template <typename T>
301 void setDataParam(const ParamData& param, UINT32 arrayIdx, const T& input) const
302 {
303 GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
304
305 DataParamInfo& paramInfo = mDataParams[param.index + arrayIdx];
306 if (paramInfo.floatCurve)
307 {
308 bs_pool_free(paramInfo.floatCurve);
309 paramInfo.floatCurve = nullptr;
310 }
311
312 if (paramInfo.colorGradient)
313 {
314 bs_pool_free(paramInfo.colorGradient);
315 paramInfo.colorGradient = nullptr;
316 }
317
318 const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
319 UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
320
321 assert(sizeof(input) == paramTypeSize);
322 memcpy(&mDataParamsBuffer[paramInfo.offset], &input, paramTypeSize);
323
324 param.version = ++mParamVersion;
325 }
326
327 /**
328 * Equivalent to getCurveParam(const String&, UINT32) except it uses the internal parameter reference directly,
329 * avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
330 * object.
331 */
332 template <typename T>
333 const TAnimationCurve<T>& getCurveParam(const ParamData& param, UINT32 arrayIdx) const
334 {
335 GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
336
337 // Only supported for float types
338 if(dataType == GPDT_FLOAT1)
339 {
340 const DataParamInfo& paramInfo = mDataParams[param.index + arrayIdx];
341 if (paramInfo.floatCurve)
342 return *paramInfo.floatCurve;
343 }
344
345 static TAnimationCurve<T> EMPTY_CURVE;
346 return EMPTY_CURVE;
347 }
348
349 /**
350 * Equivalent to setCurveParam(const String&, UINT32, const TAnimationCurve<T>&) except it uses the internal
351 * parameter reference directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid
352 * and belongs to this object.
353 */
354 template <typename T>
355 void setCurveParam(const ParamData& param, UINT32 arrayIdx, TAnimationCurve<T> input) const
356 {
357 GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
358
359 // Only supported for float types
360 if(dataType == GPDT_FLOAT1)
361 {
362 DataParamInfo& paramInfo = mDataParams[param.index + arrayIdx];
363 if(paramInfo.floatCurve)
364 bs_pool_free(paramInfo.floatCurve);
365
366 paramInfo.floatCurve = bs_pool_new<TAnimationCurve<T>>(std::move(input));
367
368 param.version = ++mParamVersion;
369 }
370 }
371
372 /**
373 * Equivalent to getColorGradientParam(const String&, UINT32) except it uses the internal parameter reference
374 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
375 * object.
376 */
377 const ColorGradient& getColorGradientParam(const ParamData& param, UINT32 arrayIdx) const;
378
379 /**
380 * Equivalent to setColorGradientParam(const String&, UINT32, const ColorGradient&) except it uses the internal
381 * parameter reference directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid
382 * and belongs to this object.
383 */
384 void setColorGradientParam(const ParamData& param, UINT32 arrayIdx, const ColorGradient& input) const;
385
386 /** Returns pointer to the internal data buffer for a data parameter at the specified index. */
387 UINT8* getData(UINT32 index) const
388 {
389 return &mDataParamsBuffer[mDataParams[index].offset];
390 }
391
392 /** Returns a counter that gets incremented whenever a parameter gets updated. */
393 UINT64 getParamVersion() const { return mParamVersion; }
394
395 protected:
396 const static UINT32 STATIC_BUFFER_SIZE = 256;
397
398 UnorderedMap<String, UINT32> mParamLookup;
399 Vector<ParamData> mParams;
400
401 DataParamInfo* mDataParams = nullptr;
402 UINT8* mDataParamsBuffer = nullptr;
403
404 UINT32 mDataSize = 0;
405 UINT32 mNumDataParams = 0;
406 UINT32 mNumStructParams = 0;
407 UINT32 mNumTextureParams = 0;
408 UINT32 mNumBufferParams = 0;
409 UINT32 mNumSamplerParams = 0;
410
411 mutable UINT64 mParamVersion = 1;
412 mutable StaticAlloc<STATIC_BUFFER_SIZE> mAlloc;
413 };
414
415 /** Raw data for a single structure parameter. */
416 class BS_CORE_EXPORT MaterialParamStructDataCore
417 {
418 public:
419 UINT8* data;
420 UINT32 dataSize;
421 };
422
423 /** Raw data for a single structure parameter. */
424 class BS_CORE_EXPORT MaterialParamStructData : public IReflectable
425 {
426 public:
427 UINT8* data;
428 UINT32 dataSize;
429
430 friend class MaterialParamStructDataRTTI;
431 static RTTITypeBase* getRTTIStatic();
432 RTTITypeBase* getRTTI() const override;
433 };
434
435 /** Data for a single texture parameter. */
436 class BS_CORE_EXPORT MaterialParamTextureDataCore
437 {
438 public:
439 SPtr<ct::Texture> texture;
440 SPtr<ct::SpriteTexture> spriteTexture;
441 bool isLoadStore;
442 TextureSurface surface;
443 };
444
445 /** Data for a single texture parameter. */
446 class BS_CORE_EXPORT MaterialParamTextureData : public IReflectable
447 {
448 public:
449 HTexture texture;
450 HSpriteTexture spriteTexture;
451 bool isLoadStore;
452 TextureSurface surface;
453
454 friend class MaterialParamTextureDataRTTI;
455 static RTTITypeBase* getRTTIStatic();
456 RTTITypeBase* getRTTI() const override;
457 };
458
459 /** Data for a single buffer parameter. */
460 class BS_CORE_EXPORT MaterialParamBufferDataCore
461 {
462 public:
463 SPtr<ct::GpuBuffer> value;
464 };
465
466 /** Data for a single buffer parameter. */
467 class BS_CORE_EXPORT MaterialParamBufferData
468 {
469 public:
470 SPtr<GpuBuffer> value;
471 };
472
473 /** Data for a single sampler state parameter. */
474 class BS_CORE_EXPORT MaterialParamSamplerStateDataCore
475 {
476 public:
477 SPtr<ct::SamplerState> value;
478 };
479
480 /** Data for a single sampler state parameter. */
481 class BS_CORE_EXPORT MaterialParamSamplerStateData
482 {
483 public:
484 SPtr<SamplerState> value;
485 };
486
487 /** Helper typedefs that reference types used by either core or sim thread implementation of TMaterialParams<Core>. */
488 template<bool Core> struct TMaterialParamsTypes { };
489 template<> struct TMaterialParamsTypes < false >
490 {
491 typedef MaterialParamStructData StructParamDataType;
492 typedef MaterialParamTextureData TextureParamDataType;
493 typedef MaterialParamBufferData BufferParamDataType;
494 typedef MaterialParamSamplerStateData SamplerStateParamDataType;
495 };
496
497 template<> struct TMaterialParamsTypes < true >
498 {
499 typedef MaterialParamStructDataCore StructParamDataType;
500 typedef MaterialParamTextureDataCore TextureParamDataType;
501 typedef MaterialParamBufferDataCore BufferParamDataType;
502 typedef MaterialParamSamplerStateDataCore SamplerStateParamDataType;
503 };
504
505 /** Common code that may be specialized for both MaterialParams and ct::MaterialParams. */
506 template<bool Core>
507 class BS_CORE_EXPORT TMaterialParams : public MaterialParamsBase
508 {
509 public:
510 using GpuParamsType = CoreVariantType<GpuParams, Core>;
511 using TextureType = CoreVariantHandleType<Texture, Core>;
512 using ShaderType = CoreVariantHandleType<Shader, Core>;
513 using SpriteTextureType = CoreVariantHandleType<SpriteTexture, Core>;
514 using BufferType = SPtr<CoreVariantType<GpuBuffer, Core>>;
515 using SamplerType = SPtr<CoreVariantType<SamplerState, Core>>;
516
517 using ParamStructDataType = typename TMaterialParamsTypes<Core>::StructParamDataType;
518 using ParamTextureDataType = typename TMaterialParamsTypes<Core>::TextureParamDataType;
519 using ParamBufferDataType = typename TMaterialParamsTypes<Core>::BufferParamDataType;
520 using ParamSamplerStateDataType = typename TMaterialParamsTypes<Core>::SamplerStateParamDataType;
521
522 /**
523 * Creates a new material params object and initializes enough room for parameters from the provided shader.
524 *
525 * @param[in] shader Shader containing the information about parameters and their types.
526 * @param[in] initialParamVersion Initial version number to assign to the parameters. Usually relevant if
527 * you are replacing an existing MaterialParams object and wish to ensure
528 * version number keeps getting incremented.
529 */
530 TMaterialParams(const ShaderType& shader, UINT64 initialParamVersion);
531
532 /** Constructor for serialization use only. */
533 TMaterialParams() = default;
534
535 virtual ~TMaterialParams();
536
537 /**
538 * Returns the value of a shader structure parameter with the specified name at the specified array index. If the
539 * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
540 *
541 * @param[in] name Name of the shader parameter.
542 * @param[out] value Pre-allocated buffer of @p size bytes where the value will be retrieved.
543 * @param[in] size Size of the buffer into which to write the value. Must match parameter struct's size.
544 * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
545 */
546 void getStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx) const;
547
548 /**
549 * Sets the value of a shader structure parameter with the specified name at the specified array index. If the
550 * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
551 *
552 * @param[in] name Name of the shader parameter.
553 * @param[in] value Buffer of @p size bytes containing the new value of the structure.
554 * @param[in] size Size of the buffer from which to retrieve the value. Must match parameter struct's size.
555 * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
556 */
557 void setStructData(const String& name, const void* value, UINT32 size, UINT32 arrayIdx);
558
559 /**
560 * Returns the value of a shader texture parameter with the specified name. If the parameter name or type is not
561 * valid a warning will be logged and output value will not be retrieved.
562 *
563 * @param[in] name Name of the shader parameter.
564 * @param[out] value Output value of the parameter.
565 * @param[out] surface Surface describing which part of the texture is being accessed.
566 */
567 void getTexture(const String& name, TextureType& value, TextureSurface& surface) const;
568
569 /**
570 * Sets the value of a shader texture parameter with the specified name. If the parameter name or type is not
571 * valid a warning will be logged and output value will not be set.
572 *
573 * @param[in] name Name of the shader parameter.
574 * @param[in] value New value of the parameter.
575 * @param[in] surface Surface describing which part of the texture is being accessed.
576 */
577 void setTexture(const String& name, const TextureType& value,
578 const TextureSurface& surface = TextureSurface::COMPLETE);
579
580 /**
581 * Returns the value of a shader texture parameter with the specified name as a sprite texture. If the parameter
582 * name or type is not valid a warning will be logged and output value will not be retrieved. If the assigned
583 * texture is not a sprite texture then this returns null and you should use one of the getTexture() overloads
584 * instead.
585 *
586 * @param[in] name Name of the shader parameter.
587 * @param[out] value Output value of the parameter.
588 */
589 void getSpriteTexture(const String& name, SpriteTextureType& value) const;
590
591 /**
592 * Assigns a sprite texture to a shader texture parameter with the specified name. If the parameter name or type
593 * is not valid a warning will be logged and output value will not be set.
594 *
595 * @param[in] name Name of the shader parameter.
596 * @param[in] value New value of the parameter.
597 */
598 void setSpriteTexture(const String& name, const SpriteTextureType& value);
599 /**
600 * Returns the value of a shader load/store texture parameter with the specified name. If the parameter name or
601 * type is not valid a warning will be logged and output value will not be retrieved.
602 *
603 * @param[in] name Name of the shader parameter.
604 * @param[out] value Output value of the parameter.
605 * @param[out] surface Surface describing which part of the texture is being accessed.
606 */
607 void getLoadStoreTexture(const String& name, TextureType& value, TextureSurface& surface) const;
608
609 /**
610 * Sets the value of a shader load/store texture parameter with the specified name. If the parameter name or
611 * type is not valid a warning will be logged and the value will not be set.
612 *
613 * @param[in] name Name of the shader parameter.
614 * @param[in] value New value of the parameter.
615 * @param[in] surface Surface describing which part of the texture is being accessed.
616 */
617 void setLoadStoreTexture(const String& name, const TextureType& value, const TextureSurface& surface);
618
619 /**
620 * Returns the value of a shader buffer parameter with the specified name. If the parameter name or type is not
621 * valid a warning will be logged and output value will not be retrieved.
622 *
623 * @param[in] name Name of the shader parameter.
624 * @param[out] value Output value of the parameter.
625 */
626 void getBuffer(const String& name, BufferType& value) const;
627
628 /**
629 * Sets the value of a shader buffer parameter with the specified name. If the parameter name or type is not
630 * valid a warning will be logged and output value will not be set.
631 *
632 * @param[in] name Name of the shader parameter.
633 * @param[in] value New value of the parameter.
634 */
635 void setBuffer(const String& name, const BufferType& value);
636
637 /**
638 * Sets the value of a shader sampler state parameter with the specified name. If the parameter name or type is not
639 * valid a warning will be logged and output value will not be set.
640 *
641 * @param[in] name Name of the shader parameter.
642 * @param[out] value Output value of the parameter.
643 */
644 void getSamplerState(const String& name, SamplerType& value) const;
645
646 /**
647 * Sets the value of a shader sampler state parameter with the specified name. If the parameter name or type is not
648 * valid a warning will be logged and output value will not be set.
649 *
650 * @param[in] name Name of the shader parameter.
651 * @param[in] value New value of the parameter.
652 */
653 void setSamplerState(const String& name, const SamplerType& value);
654
655 /**
656 * Checks does the data parameter with the specified name currently contains animated data. This could be
657 * an animation curve or a color gradient.
658 */
659 bool isAnimated(const String& name, UINT32 arrayIdx = 0);
660
661 /**
662 * Equivalent to getStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter reference
663 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
664 * object.
665 */
666 void getStructData(const ParamData& param, void* value, UINT32 size, UINT32 arrayIdx) const;
667
668 /**
669 * Equivalent to setStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter reference
670 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
671 * object.
672 */
673 void setStructData(const ParamData& param, const void* value, UINT32 size, UINT32 arrayIdx);
674
675 /**
676 * Returns a size of a struct parameter in bytes, using the internal parameter reference. Caller must guarantee the
677 * parameter reference is valid and belongs to this object.
678 */
679 UINT32 getStructSize(const ParamData& param) const;
680
681 /**
682 * Equivalent to getTexture(const String&, HTexture&, TextureSurface&) except it uses the internal parameter
683 * reference directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs
684 * to this object.
685 */
686 void getTexture(const ParamData& param, TextureType& value, TextureSurface& surface) const;
687
688 /**
689 * Equivalent to setTexture(const String&, const HTexture&, const TextureSurface&) except it uses the internal
690 * parameter reference directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid
691 * and belongs to this object.
692 */
693 void setTexture(const ParamData& param, const TextureType& value,
694 const TextureSurface& surface = TextureSurface::COMPLETE);
695
696 /**
697 * Equivalent to getSpriteTexture(const String&, HSpriteTexture&) except it uses the internal parameter reference
698 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
699 * object.
700 */
701 void getSpriteTexture(const ParamData& param, SpriteTextureType& value) const;
702
703 /**
704 * Equivalent to setSpriteTexture(const String&, const HSpriteTexture&) except it uses the internal parameter
705 * reference directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs
706 * to this object.
707 */
708 void setSpriteTexture(const ParamData& param, const SpriteTextureType& value);
709
710 /**
711 * Equivalent to getBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter reference
712 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
713 * object.
714 */
715 void getBuffer(const ParamData& param, BufferType& value) const;
716
717 /**
718 * Equivalent to setBuffer(const String&, const SPtr<GpuBuffer>&) except it uses the internal parameter reference
719 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
720 * object.
721 */
722 void setBuffer(const ParamData& param, const BufferType& value);
723
724 /**
725 * Equivalent to getLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal
726 * parameter reference directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid
727 * and belongs to this object.
728 */
729 void getLoadStoreTexture(const ParamData& param, TextureType& value, TextureSurface& surface) const;
730
731 /**
732 * Equivalent to setLoadStoreTexture(const String&, const HTexture&, TextureSurface&) except it uses the internal
733 * parameter reference directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid
734 * and belongs to this object.
735 */
736 void setLoadStoreTexture(const ParamData& param, const TextureType& value, const TextureSurface& surface);
737
738 /**
739 * Returns the type of texture that is currently assigned to the provided parameter. This can only be called on
740 * on texture parameters. Caller must guarantee the parameter reference is valid, is of a texture type and
741 * belongs to this object.
742 */
743 MateralParamTextureType getTextureType(const ParamData& param) const;
744
745 /**
746 * Checks does the provided parameter have a curve or gradient assigned. This can only be called on data parameters.
747 * Caller must guarantee the parameter reference is valid, is of a data type and belongs to this object.
748
749 */
750 bool isAnimated(const ParamData& param, UINT32 arrayIdx) const;
751
752 /**
753 * Returns a sprite texture that is used for populating the specified data parameter. This is only relevant
754 * for data parameters marked with the ShaderParamAttributeType::SpriteUV attribute.
755 */
756 SpriteTextureType getOwningSpriteTexture(const ParamData& param) const;
757
758 /**
759 * Equivalent to getSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter reference
760 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
761 * object.
762 */
763 void getSamplerState(const ParamData& param, SamplerType& value) const;
764
765 /**
766 * Equivalent to setSamplerState(const String&, const SPtr<SamplerState>&) except it uses the internal parameter
767 * reference directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs
768 * to this object.
769 */
770 void setSamplerState(const ParamData& param, const SamplerType& value);
771
772 /**
773 * Returns the default texture (one assigned when no other is provided), if available for the specified parameter.
774 * Parameter is represented using the internal parameter reference and the caller must guarantee the parameter
775 * eference is valid and belongs to this object.
776 */
777 void getDefaultTexture(const ParamData& param, TextureType& value) const;
778
779 /**
780 * Returns the default sampler state (one assigned when no other is provided), if available for the specified
781 * parameter. Parameter is represented using the internal parameter reference and the caller must guarantee the
782 * parameter reference is valid and belongs to this object.
783 */
784 void getDefaultSamplerState(const ParamData& param, SamplerType& value) const;
785
786 protected:
787 ParamStructDataType* mStructParams = nullptr;
788 ParamTextureDataType* mTextureParams = nullptr;
789 ParamBufferDataType* mBufferParams = nullptr;
790 ParamSamplerStateDataType* mSamplerStateParams = nullptr;
791 TextureType* mDefaultTextureParams = nullptr;
792 SamplerType* mDefaultSamplerStateParams = nullptr;
793 };
794
795 /**
796 * Contains all parameter values set in a Material. This is similar to GpuParams which also stores parameter values,
797 * however GpuParams are built for use on the GPU-side and don't store parameters that don't exist in a compiled GPU
798 * program. This object on the other hand stores all parameters defined in a shader, regardless or not if they actually
799 * exist in the GPU program. Additionally GpuParams are defined per-program (for example vertex, fragment) while this
800 * object exists for the entire material.
801 *
802 * @note
803 * This introduces redundancy as parameters stored by GpuParams and this object are duplicated. If this is an issue the
804 * implementation can be modified to only store parameters not included in GpuParams.
805 * @note
806 * The reason why parameters in this class and GpuParams differ is most often compiler optimizations. If a compiler
807 * optimizes out a variable in a GPU program we should still be able to store it, either for later when the variable
808 * will be introduced, or for other techniques that might have that variable implemented.
809 */
810 class BS_CORE_EXPORT MaterialParams : public IReflectable, public TMaterialParams<false>
811 {
812 public:
813 /** @copydoc TMaterialParams::TMaterialParams(const ShaderType&, UINT32) */
814 MaterialParams(const HShader& shader, UINT64 initialParamVersion = 1);
815
816 /**
817 * Populates the provided buffer with parameters that can be used for syncing this object with its core-thread
818 * counterpart. Can be applied by calling ct::MaterialParams::setSyncData.
819 *
820 * @param[in] buffer Pre-allocated buffer to store the sync data in. Set to null to calculate the size
821 * of the required buffer.
822 * @param[in, out] size Size of the provided allocated buffer. Or if the buffer is null, this parameter will
823 * contain the required buffer size when the method executes.
824 * @param[in] forceAll If false, only the parameters that were changed since the last call will be synced.
825 * Otherwise all parameters will be synced.
826 */
827 void getSyncData(UINT8* buffer, UINT32& size, bool forceAll);
828
829 /** Appends any resources stored by this object to the provided vector. */
830 void getResourceDependencies(Vector<HResource>& resources);
831
832 /** Appends any core objects stored by this object to the provided vector. */
833 void getCoreObjectDependencies(Vector<CoreObject*>& coreObjects);
834
835 private:
836 friend class ct::MaterialParams;
837
838 UINT64 mLastSyncVersion;
839
840 /************************************************************************/
841 /* RTTI */
842 /************************************************************************/
843 public:
844 MaterialParams() { } // Only for serialization
845
846 friend class MaterialParamsRTTI;
847 static RTTITypeBase* getRTTIStatic();
848 RTTITypeBase* getRTTI() const override;
849 };
850
851 namespace ct
852 {
853 /** Core thread version of MaterialParams. */
854 class BS_CORE_EXPORT MaterialParams : public TMaterialParams<true>
855 {
856 public:
857 /** Initializes the core thread version of MaterialParams from its sim thread counterpart. */
858 MaterialParams(const SPtr<Shader>& shader, const SPtr<bs::MaterialParams>& params);
859
860 /** @copydoc TMaterialParams::TMaterialParams(const ShaderType&, UINT32) */
861 MaterialParams(const SPtr<Shader>& shader, UINT64 initialParamVersion = 1);
862
863 /**
864 * Updates the stored parameters from the provided buffer, allowing changes to be transfered between the sim and
865 * core thread material param objects. Buffer must be retrieved from bs::MaterialParams::getSyncData.
866 *
867 * @param[in] buffer Buffer containing the dirty data.
868 * @param[in, out] size Size of the provided buffer.
869 */
870 void setSyncData(UINT8* buffer, UINT32 size);
871 };
872 }
873 /** @} */
874}
875