| 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 "RenderAPI/BsGpuParam.h" |
| 7 | #include "CoreThread/BsCoreObject.h" |
| 8 | #include "Resources/BsIResourceListener.h" |
| 9 | #include "Math/BsMatrixNxM.h" |
| 10 | |
| 11 | namespace bs |
| 12 | { |
| 13 | /** @addtogroup Implementation |
| 14 | * @{ |
| 15 | */ |
| 16 | |
| 17 | /** Helper structure whose specializations convert an engine data type into a GPU program data parameter type. */ |
| 18 | template<class T> struct TGpuDataParamInfo { enum { TypeId = GPDT_STRUCT };}; |
| 19 | template<> struct TGpuDataParamInfo < float > { enum { TypeId = GPDT_FLOAT1 }; }; |
| 20 | template<> struct TGpuDataParamInfo < Vector2 > { enum { TypeId = GPDT_FLOAT2 }; }; |
| 21 | template<> struct TGpuDataParamInfo < Vector3 > { enum { TypeId = GPDT_FLOAT3 }; }; |
| 22 | template<> struct TGpuDataParamInfo < Vector4 > { enum { TypeId = GPDT_FLOAT4 }; }; |
| 23 | template<> struct TGpuDataParamInfo < int > { enum { TypeId = GPDT_INT1 }; }; |
| 24 | template<> struct TGpuDataParamInfo < Vector2I > { enum { TypeId = GPDT_INT2 }; }; |
| 25 | template<> struct TGpuDataParamInfo < Vector3I > { enum { TypeId = GPDT_INT3 }; }; |
| 26 | template<> struct TGpuDataParamInfo < Vector4I > { enum { TypeId = GPDT_INT4 }; }; |
| 27 | template<> struct TGpuDataParamInfo < Matrix2 > { enum { TypeId = GPDT_MATRIX_2X2 }; }; |
| 28 | template<> struct TGpuDataParamInfo < Matrix2x3 > { enum { TypeId = GPDT_MATRIX_2X3 }; }; |
| 29 | template<> struct TGpuDataParamInfo < Matrix2x4 > { enum { TypeId = GPDT_MATRIX_2X4 }; }; |
| 30 | template<> struct TGpuDataParamInfo < Matrix3 > { enum { TypeId = GPDT_MATRIX_3X3 }; }; |
| 31 | template<> struct TGpuDataParamInfo < Matrix3x2 > { enum { TypeId = GPDT_MATRIX_3X2 }; }; |
| 32 | template<> struct TGpuDataParamInfo < Matrix3x4 > { enum { TypeId = GPDT_MATRIX_3X4 }; }; |
| 33 | template<> struct TGpuDataParamInfo < Matrix4 > { enum { TypeId = GPDT_MATRIX_4X4 }; }; |
| 34 | template<> struct TGpuDataParamInfo < Matrix4x2 > { enum { TypeId = GPDT_MATRIX_4X2 }; }; |
| 35 | template<> struct TGpuDataParamInfo < Matrix4x3 > { enum { TypeId = GPDT_MATRIX_4X3 }; }; |
| 36 | template<> struct TGpuDataParamInfo < Color > { enum { TypeId = GPDT_COLOR }; }; |
| 37 | |
| 38 | class GpuPipelineParamInfoBase; |
| 39 | |
| 40 | /** Contains functionality common for both sim and core thread version of GpuParams. */ |
| 41 | class BS_CORE_EXPORT GpuParamsBase |
| 42 | { |
| 43 | public: |
| 44 | virtual ~GpuParamsBase() = default; |
| 45 | |
| 46 | // Note: Disallow copy/assign because it would require some care when copying (copy internal data shared_ptr and |
| 47 | // all the internal buffers too). Trivial to implement but not needed at this time. Un-delete and implement if necessary. |
| 48 | GpuParamsBase(const GpuParamsBase& other) = delete; |
| 49 | GpuParamsBase& operator=(const GpuParamsBase& rhs) = delete; |
| 50 | |
| 51 | /** Returns a description of all stored parameters. */ |
| 52 | SPtr<GpuParamDesc> getParamDesc(GpuProgramType type) const; |
| 53 | |
| 54 | /** Gets the object that contains the processed information about all parameters. */ |
| 55 | SPtr<GpuPipelineParamInfoBase> getParamInfo() const { return mParamInfo; } |
| 56 | |
| 57 | /** |
| 58 | * Returns the size of a data parameter with the specified name, in bytes. Returns 0 if such parameter doesn't exist. |
| 59 | */ |
| 60 | UINT32 getDataParamSize(GpuProgramType type, const String& name) const; |
| 61 | |
| 62 | /** Checks if parameter with the specified name exists. */ |
| 63 | bool hasParam(GpuProgramType type, const String& name) const; |
| 64 | |
| 65 | /** Checks if texture parameter with the specified name exists. */ |
| 66 | bool hasTexture(GpuProgramType type, const String& name) const; |
| 67 | |
| 68 | /** Checks if load/store texture parameter with the specified name exists. */ |
| 69 | bool hasLoadStoreTexture(GpuProgramType type, const String& name) const; |
| 70 | |
| 71 | /** Checks if buffer parameter with the specified name exists. */ |
| 72 | bool hasBuffer(GpuProgramType type, const String& name) const; |
| 73 | |
| 74 | /** Checks if sampler state parameter with the specified name exists. */ |
| 75 | bool hasSamplerState(GpuProgramType type, const String& name) const; |
| 76 | |
| 77 | /** Checks if a parameter block with the specified name exists. */ |
| 78 | bool hasParamBlock(GpuProgramType type, const String& name) const; |
| 79 | |
| 80 | /** Gets a descriptor for a parameter block buffer with the specified name. */ |
| 81 | GpuParamBlockDesc* getParamBlockDesc(GpuProgramType type, const String& name) const; |
| 82 | |
| 83 | /** Marks the sim thread object as dirty, causing it to sync its contents with its core thread counterpart. */ |
| 84 | virtual void _markCoreDirty() { } |
| 85 | |
| 86 | /** @copydoc IResourceListener::markListenerResourcesDirty */ |
| 87 | virtual void _markResourcesDirty() { } |
| 88 | |
| 89 | protected: |
| 90 | GpuParamsBase(const SPtr<GpuPipelineParamInfoBase>& paramInfo); |
| 91 | |
| 92 | /** Gets a descriptor for a data parameter with the specified name. */ |
| 93 | GpuParamDataDesc* getParamDesc(GpuProgramType type, const String& name) const; |
| 94 | |
| 95 | SPtr<GpuPipelineParamInfoBase> mParamInfo; |
| 96 | }; |
| 97 | |
| 98 | /** Templated version of GpuParams that contains functionality for both sim and core thread versions of stored data. */ |
| 99 | template <bool Core> |
| 100 | class BS_CORE_EXPORT TGpuParams : public GpuParamsBase |
| 101 | { |
| 102 | public: |
| 103 | using GpuParamsType = CoreVariantType<GpuParams, Core>; |
| 104 | using TextureType = CoreVariantHandleType<Texture, Core>; |
| 105 | using BufferType = SPtr<CoreVariantType<GpuBuffer, Core>>; |
| 106 | using SamplerType = SPtr<CoreVariantType<SamplerState, Core>>; |
| 107 | using ParamsBufferType = SPtr<CoreVariantType<GpuParamBlockBuffer, Core>>; |
| 108 | |
| 109 | virtual ~TGpuParams(); |
| 110 | |
| 111 | /** |
| 112 | * Returns a handle for the parameter with the specified name. Handle may then be stored and used for quickly |
| 113 | * setting or retrieving values to/from that parameter. |
| 114 | * |
| 115 | * Throws exception if parameter with that name and type doesn't exist. |
| 116 | * |
| 117 | * Parameter handles will be invalidated when their parent GpuParams object changes. |
| 118 | */ |
| 119 | template<class T> void getParam(GpuProgramType type, const String& name, TGpuDataParam<T, Core>& output) const; |
| 120 | |
| 121 | /** @copydoc getParam */ |
| 122 | void getStructParam(GpuProgramType type, const String& name, TGpuParamStruct<Core>& output) const; |
| 123 | |
| 124 | /** @copydoc getParam */ |
| 125 | void getTextureParam(GpuProgramType type, const String& name, TGpuParamTexture<Core>& output) const; |
| 126 | |
| 127 | /** @copydoc getParam */ |
| 128 | void getLoadStoreTextureParam(GpuProgramType type, const String& name, TGpuParamLoadStoreTexture<Core>& output) const; |
| 129 | |
| 130 | /** @copydoc getParam */ |
| 131 | void getBufferParam(GpuProgramType type, const String& name, TGpuParamBuffer<Core>& output) const; |
| 132 | |
| 133 | /** @copydoc getParam */ |
| 134 | void getSamplerStateParam(GpuProgramType type, const String& name, TGpuParamSampState<Core>& output) const; |
| 135 | |
| 136 | /** Gets a parameter block buffer from the specified set/slot combination. */ |
| 137 | ParamsBufferType getParamBlockBuffer(UINT32 set, UINT32 slot) const; |
| 138 | |
| 139 | /** Gets a texture bound to the specified set/slot combination. */ |
| 140 | TextureType getTexture(UINT32 set, UINT32 slot) const; |
| 141 | |
| 142 | /** Gets a load/store texture bound to the specified set/slot combination. */ |
| 143 | TextureType getLoadStoreTexture(UINT32 set, UINT32 slot) const; |
| 144 | |
| 145 | /** Gets a buffer bound to the specified set/slot combination. */ |
| 146 | BufferType getBuffer(UINT32 set, UINT32 slot) const; |
| 147 | |
| 148 | /** Gets a sampler state bound to the specified set/slot combination. */ |
| 149 | SamplerType getSamplerState(UINT32 set, UINT32 slot) const; |
| 150 | |
| 151 | /** Gets information that determines which texture surfaces to bind as a sampled texture parameter. */ |
| 152 | const TextureSurface& getTextureSurface(UINT32 set, UINT32 slot) const; |
| 153 | |
| 154 | /** Gets information that determines which texture surfaces to bind as a load/store parameter. */ |
| 155 | const TextureSurface& getLoadStoreSurface(UINT32 set, UINT32 slot) const; |
| 156 | |
| 157 | /** |
| 158 | * Assigns the provided parameter block buffer to a buffer with the specified name, for the specified GPU program |
| 159 | * stage. Any following parameter reads or writes that are referencing that buffer will use the new buffer. |
| 160 | * |
| 161 | * It is up to the caller to guarantee the provided buffer matches parameter block descriptor for this slot. |
| 162 | */ |
| 163 | void setParamBlockBuffer(GpuProgramType type, const String& name, const ParamsBufferType& paramBlockBuffer); |
| 164 | |
| 165 | /** |
| 166 | * Assigns the provided parameter block buffer to a buffer with the specified name, for any stages that reference |
| 167 | * the buffer. Any following parameter reads or writes that are referencing that buffer will use the new buffer. |
| 168 | * |
| 169 | * It is up to the caller to guarantee the provided buffer matches parameter block descriptor for this slot. |
| 170 | * It is up to the caller that all stages using this buffer name refer to the same buffer type. |
| 171 | */ |
| 172 | void setParamBlockBuffer(const String& name, const ParamsBufferType& paramBlockBuffer); |
| 173 | |
| 174 | /** |
| 175 | * Sets the parameter buffer with the specified set/slot combination.Any following parameter reads or writes that are |
| 176 | * referencing that buffer will use the new buffer. Set/slot information for a specific buffer can be extracted |
| 177 | * from GPUProgram's GpuParamDesc structure. |
| 178 | * |
| 179 | * It is up to the caller to guarantee the provided buffer matches parameter block descriptor for this slot. |
| 180 | */ |
| 181 | virtual void setParamBlockBuffer(UINT32 set, UINT32 slot, const ParamsBufferType& paramBlockBuffer); |
| 182 | |
| 183 | /** Sets a texture at the specified set/slot combination. */ |
| 184 | virtual void setTexture(UINT32 set, UINT32 slot, const TextureType& texture, |
| 185 | const TextureSurface& surface = TextureSurface::COMPLETE); |
| 186 | |
| 187 | /** Sets a load/store texture at the specified set/slot combination. */ |
| 188 | virtual void setLoadStoreTexture(UINT32 set, UINT32 slot, const TextureType& texture, const TextureSurface& surface); |
| 189 | |
| 190 | /** Sets a buffer at the specified set/slot combination. */ |
| 191 | virtual void setBuffer(UINT32 set, UINT32 slot, const BufferType& buffer); |
| 192 | |
| 193 | /** Sets a sampler state at the specified set/slot combination. */ |
| 194 | virtual void setSamplerState(UINT32 set, UINT32 slot, const SamplerType& sampler); |
| 195 | |
| 196 | /** Assigns a data value to the parameter with the specified name. */ |
| 197 | template<class T> void setParam(GpuProgramType type, const String& name, const T& value) |
| 198 | { TGpuDataParam<T, Core> param; getParam(type, name, param); param.set(value); } |
| 199 | |
| 200 | /** Assigns a texture to the parameter with the specified name. */ |
| 201 | void setTexture(GpuProgramType type, const String& name, const TextureType& texture, |
| 202 | const TextureSurface& surface = TextureSurface::COMPLETE) |
| 203 | { TGpuParamTexture<Core> param; getTextureParam(type, name, param); param.set(texture, surface); } |
| 204 | |
| 205 | /** Assigns a load/store texture to the parameter with the specified name. */ |
| 206 | void setLoadStoreTexture(GpuProgramType type, const String& name, const TextureType& texture, const TextureSurface& surface) |
| 207 | { TGpuParamLoadStoreTexture<Core> param; getLoadStoreTextureParam(type, name, param); param.set(texture, surface); } |
| 208 | |
| 209 | /** Assigns a buffer to the parameter with the specified name. */ |
| 210 | void setBuffer(GpuProgramType type, const String& name, const BufferType& buffer) |
| 211 | { TGpuParamBuffer<Core> param; getBufferParam(type, name, param); param.set(buffer); } |
| 212 | |
| 213 | /** Assigns a sampler state to the parameter with the specified name. */ |
| 214 | void setSamplerState(GpuProgramType type, const String& name, const SamplerType& sampler) |
| 215 | { TGpuParamSampState<Core> param; getSamplerStateParam(type, name, param); param.set(sampler); } |
| 216 | |
| 217 | protected: |
| 218 | TGpuParams(const SPtr<GpuPipelineParamInfoBase>& paramInfo); |
| 219 | |
| 220 | /** @copydoc CoreObject::getThisPtr */ |
| 221 | virtual SPtr<GpuParamsType> _getThisPtr() const = 0; |
| 222 | |
| 223 | /** Data for a single bound texture. */ |
| 224 | struct TextureData |
| 225 | { |
| 226 | TextureType texture; |
| 227 | TextureSurface surface; |
| 228 | }; |
| 229 | |
| 230 | ParamsBufferType* mParamBlockBuffers = nullptr; |
| 231 | TextureData* mSampledTextureData = nullptr; |
| 232 | TextureData* mLoadStoreTextureData = nullptr; |
| 233 | BufferType* mBuffers = nullptr; |
| 234 | SamplerType* mSamplerStates = nullptr; |
| 235 | }; |
| 236 | |
| 237 | /** @} */ |
| 238 | |
| 239 | /** @addtogroup RenderAPI |
| 240 | * @{ |
| 241 | */ |
| 242 | |
| 243 | /** |
| 244 | * Contains descriptions for all parameters in a set of programs (ones for each stage) and allows you to write and read |
| 245 | * those parameters. All parameter values are stored internally on the CPU, and are only submitted to the GPU once the |
| 246 | * parameters are bound to the pipeline. |
| 247 | * |
| 248 | * @note Sim thread only. |
| 249 | */ |
| 250 | class BS_CORE_EXPORT GpuParams : public CoreObject, public TGpuParams<false>, public IResourceListener |
| 251 | { |
| 252 | public: |
| 253 | ~GpuParams() { } |
| 254 | |
| 255 | /** Retrieves a core implementation of a mesh usable only from the core thread. */ |
| 256 | SPtr<ct::GpuParams> getCore() const; |
| 257 | |
| 258 | /** |
| 259 | * Creates new GpuParams object that can serve for changing the GPU program parameters on the specified pipeline. |
| 260 | * |
| 261 | * @param[in] pipelineState Pipeline state for which this object can set parameters for. |
| 262 | * @return New GpuParams object. |
| 263 | */ |
| 264 | static SPtr<GpuParams> create(const SPtr<GraphicsPipelineState>& pipelineState); |
| 265 | |
| 266 | /** @copydoc GpuParams::create(const SPtr<GraphicsPipelineState>&) */ |
| 267 | static SPtr<GpuParams> create(const SPtr<ComputePipelineState>& pipelineState); |
| 268 | |
| 269 | /** |
| 270 | * Creates a new set of GPU parameters using an object describing the parameters for a pipeline. |
| 271 | * |
| 272 | * @param[in] paramInfo Description of GPU parameters for a specific GPU pipeline state. |
| 273 | */ |
| 274 | static SPtr<GpuParams> create(const SPtr<GpuPipelineParamInfo>& paramInfo); |
| 275 | |
| 276 | /** Contains a lookup table for sizes of all data parameters. Sizes are in bytes. */ |
| 277 | const static GpuDataParamInfos PARAM_SIZES; |
| 278 | |
| 279 | /** @name Internal |
| 280 | * @{ |
| 281 | */ |
| 282 | |
| 283 | /** @copydoc GpuParamsBase::_markCoreDirty */ |
| 284 | void _markCoreDirty() override; |
| 285 | |
| 286 | /** @copydoc IResourceListener::markListenerResourcesDirty */ |
| 287 | void _markResourcesDirty() override; |
| 288 | |
| 289 | /** @} */ |
| 290 | protected: |
| 291 | friend class HardwareBufferManager; |
| 292 | |
| 293 | GpuParams(const SPtr<GpuPipelineParamInfo>& paramInfo); |
| 294 | |
| 295 | /** @copydoc CoreObject::getThisPtr */ |
| 296 | SPtr<GpuParams> _getThisPtr() const override; |
| 297 | |
| 298 | /** @copydoc CoreObject::createCore */ |
| 299 | SPtr<ct::CoreObject> createCore() const override; |
| 300 | |
| 301 | /** @copydoc CoreObject::syncToCore */ |
| 302 | CoreSyncData syncToCore(FrameAlloc* allocator) override; |
| 303 | |
| 304 | /** @copydoc IResourceListener::getListenerResources */ |
| 305 | void getListenerResources(Vector<HResource>& resources) override; |
| 306 | |
| 307 | /** @copydoc IResourceListener::notifyResourceLoaded */ |
| 308 | void notifyResourceLoaded(const HResource& resource) override { markCoreDirty(); } |
| 309 | |
| 310 | /** @copydoc IResourceListener::notifyResourceChanged */ |
| 311 | void notifyResourceChanged(const HResource& resource) override { markCoreDirty(); } |
| 312 | }; |
| 313 | |
| 314 | /** @} */ |
| 315 | |
| 316 | namespace ct |
| 317 | { |
| 318 | /** @addtogroup RenderAPI-Internal |
| 319 | * @{ |
| 320 | */ |
| 321 | |
| 322 | /** |
| 323 | * Core thread version of bs::GpuParams. |
| 324 | * |
| 325 | * @note Core thread only. |
| 326 | */ |
| 327 | class BS_CORE_EXPORT GpuParams : public CoreObject, public TGpuParams<true> |
| 328 | { |
| 329 | public: |
| 330 | virtual ~GpuParams() { } |
| 331 | |
| 332 | /** |
| 333 | * @copydoc bs::GpuParams::create(const SPtr<GraphicsPipelineState>&) |
| 334 | * @param[in] deviceMask Mask that determines on which GPU devices should the buffer be created on. |
| 335 | */ |
| 336 | static SPtr<GpuParams> create(const SPtr<GraphicsPipelineState>& pipelineState, |
| 337 | GpuDeviceFlags deviceMask = GDF_DEFAULT); |
| 338 | |
| 339 | /** |
| 340 | * @copydoc bs::GpuParams::create(const SPtr<ComputePipelineState>&) |
| 341 | * @param[in] deviceMask Mask that determines on which GPU devices should the buffer be created on. |
| 342 | */ |
| 343 | static SPtr<GpuParams> create(const SPtr<ComputePipelineState>& pipelineState, |
| 344 | GpuDeviceFlags deviceMask = GDF_DEFAULT); |
| 345 | |
| 346 | /** |
| 347 | * @copydoc bs::GpuParams::create(const SPtr<GpuPipelineParamInfo>&) |
| 348 | * @param[in] deviceMask Mask that determines on which GPU devices should the buffer be created on. |
| 349 | */ |
| 350 | static SPtr<GpuParams> create(const SPtr<GpuPipelineParamInfo>& paramInfo, |
| 351 | GpuDeviceFlags deviceMask = GDF_DEFAULT); |
| 352 | |
| 353 | protected: |
| 354 | friend class bs::GpuParams; |
| 355 | friend class HardwareBufferManager; |
| 356 | |
| 357 | GpuParams(const SPtr<GpuPipelineParamInfo>& paramInfo, GpuDeviceFlags deviceMask); |
| 358 | |
| 359 | /** @copydoc CoreObject::getThisPtr */ |
| 360 | SPtr<GpuParams> _getThisPtr() const override; |
| 361 | |
| 362 | /** @copydoc CoreObject::syncToCore */ |
| 363 | void syncToCore(const CoreSyncData& data) override; |
| 364 | }; |
| 365 | |
| 366 | /** @} */ |
| 367 | } |
| 368 | } |