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 | } |