| 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 | |
| 12 | namespace 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, ¶m); |
| 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, ¶m); |
| 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, ¶m); |
| 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, ¶m); |
| 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 | |