1 /*
2  * Copyright 2011-2019 Branimir Karadzic. All rights reserved.
3  * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
4  */
5 
6 #ifndef BGFX_RENDERER_H_HEADER_GUARD
7 #define BGFX_RENDERER_H_HEADER_GUARD
8 
9 #include "bgfx_p.h"
10 
11 namespace bgfx
12 {
13 	inline constexpr uint32_t toAbgr8(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a = 0xff)
14 	{
15 		return 0
16 			| (uint32_t(_r)<<24)
17 			| (uint32_t(_g)<<16)
18 			| (uint32_t(_b)<< 8)
19 			| (uint32_t(_a)    )
20 			;
21 	}
22 
23 	constexpr uint32_t kColorFrame    = toAbgr8(0xff, 0xd7, 0xc9);
24 	constexpr uint32_t kColorView     = toAbgr8(0xe4, 0xb4, 0x8e);
25 	constexpr uint32_t kColorDraw     = toAbgr8(0xc6, 0xe5, 0xb9);
26 	constexpr uint32_t kColorCompute  = toAbgr8(0xa7, 0xdb, 0xd8);
27 	constexpr uint32_t kColorMarker   = toAbgr8(0xff, 0x00, 0x00);
28 	constexpr uint32_t kColorResource = toAbgr8(0xff, 0x40, 0x20);
29 
30 	struct BlitState
31 	{
BlitStateBlitState32 		BlitState(const Frame* _frame)
33 			: m_frame(_frame)
34 			, m_item(0)
35 		{
36 			m_key.decode(_frame->m_blitKeys[0]);
37 		}
38 
hasItemBlitState39 		bool hasItem(uint16_t _view) const
40 		{
41 			return m_item < m_frame->m_numBlitItems
42 				&& m_key.m_view <= _view
43 				;
44 		}
45 
advanceBlitState46 		const BlitItem& advance()
47 		{
48 			const BlitItem& bi = m_frame->m_blitItem[m_key.m_item];
49 
50 			++m_item;
51 			m_key.decode(m_frame->m_blitKeys[m_item]);
52 
53 			return bi;
54 		}
55 
56 		const Frame* m_frame;
57 		BlitKey  m_key;
58 		uint16_t m_item;
59 	};
60 
61 	struct ViewState
62 	{
ViewStateViewState63 		ViewState()
64 		{
65 		}
66 
ViewStateViewState67 		ViewState(Frame* _frame)
68 		{
69 			reset(_frame);
70 		}
71 
resetViewState72 		void reset(Frame* _frame)
73 		{
74 			m_alphaRef = 0.0f;
75 			m_invViewCached = UINT16_MAX;
76 			m_invProjCached = UINT16_MAX;
77 			m_invViewProjCached = UINT16_MAX;
78 
79 			m_view = m_viewTmp;
80 
81 			for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii)
82 			{
83 				bx::memCopy(&m_view[ii].un.f4x4, &_frame->m_view[ii].m_view.un.f4x4, sizeof(Matrix4) );
84 			}
85 
86 			for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii)
87 			{
88 				bx::float4x4_mul(&m_viewProj[ii].un.f4x4
89 					, &m_view[ii].un.f4x4
90 					, &_frame->m_view[ii].m_proj.un.f4x4
91 					);
92 			}
93 		}
94 
95 		template<uint16_t mtxRegs, typename RendererContext, typename Program, typename Draw>
setPredefinedViewState96 		void setPredefined(RendererContext* _renderer, uint16_t _view, const Program& _program, const Frame* _frame, const Draw& _draw)
97 		{
98 			const FrameCache& frameCache = _frame->m_frameCache;
99 
100 			for (uint32_t ii = 0, num = _program.m_numPredefined; ii < num; ++ii)
101 			{
102 				const PredefinedUniform& predefined = _program.m_predefined[ii];
103 				uint8_t flags = predefined.m_type&BGFX_UNIFORM_FRAGMENTBIT;
104 				switch (predefined.m_type&(~BGFX_UNIFORM_FRAGMENTBIT) )
105 				{
106 				case PredefinedUniform::ViewRect:
107 					{
108 						float frect[4];
109 						frect[0] = m_rect.m_x;
110 						frect[1] = m_rect.m_y;
111 						frect[2] = m_rect.m_width;
112 						frect[3] = m_rect.m_height;
113 
114 						_renderer->setShaderUniform4f(flags
115 							, predefined.m_loc
116 							, &frect[0]
117 							, 1
118 							);
119 					}
120 					break;
121 
122 				case PredefinedUniform::ViewTexel:
123 					{
124 						float frect[4];
125 						frect[0] = 1.0f/float(m_rect.m_width);
126 						frect[1] = 1.0f/float(m_rect.m_height);
127 
128 						_renderer->setShaderUniform4f(flags
129 							, predefined.m_loc
130 							, &frect[0]
131 							, 1
132 							);
133 					}
134 					break;
135 
136 				case PredefinedUniform::View:
137 					{
138 						_renderer->setShaderUniform4x4f(flags
139 							, predefined.m_loc
140 							, m_view[_view].un.val
141 							, bx::uint32_min(mtxRegs, predefined.m_count)
142 							);
143 					}
144 					break;
145 
146 				case PredefinedUniform::InvView:
147 					{
148 						if (_view != m_invViewCached)
149 						{
150 							m_invViewCached = _view;
151 							bx::float4x4_inverse(&m_invView.un.f4x4
152 								, &m_view[_view].un.f4x4
153 								);
154 						}
155 
156 						_renderer->setShaderUniform4x4f(flags
157 							, predefined.m_loc
158 							, m_invView.un.val
159 							, bx::uint32_min(mtxRegs, predefined.m_count)
160 							);
161 					}
162 					break;
163 
164 				case PredefinedUniform::Proj:
165 					{
166 						_renderer->setShaderUniform4x4f(flags
167 							, predefined.m_loc
168 							, _frame->m_view[_view].m_proj.un.val
169 							, bx::uint32_min(mtxRegs, predefined.m_count)
170 							);
171 					}
172 					break;
173 
174 				case PredefinedUniform::InvProj:
175 					{
176 						if (_view != m_invProjCached)
177 						{
178 							m_invProjCached = _view;
179 							bx::float4x4_inverse(&m_invProj.un.f4x4
180 								, &_frame->m_view[_view].m_proj.un.f4x4
181 								);
182 						}
183 
184 						_renderer->setShaderUniform4x4f(flags
185 							, predefined.m_loc
186 							, m_invProj.un.val
187 							, bx::uint32_min(mtxRegs, predefined.m_count)
188 							);
189 					}
190 					break;
191 
192 				case PredefinedUniform::ViewProj:
193 					{
194 						_renderer->setShaderUniform4x4f(flags
195 							, predefined.m_loc
196 							, m_viewProj[_view].un.val
197 							, bx::uint32_min(mtxRegs, predefined.m_count)
198 							);
199 					}
200 					break;
201 
202 				case PredefinedUniform::InvViewProj:
203 					{
204 						if (_view != m_invViewProjCached)
205 						{
206 							m_invViewProjCached = _view;
207 							bx::float4x4_inverse(&m_invViewProj.un.f4x4
208 								, &m_viewProj[_view].un.f4x4
209 								);
210 						}
211 
212 						_renderer->setShaderUniform4x4f(flags
213 							, predefined.m_loc
214 							, m_invViewProj.un.val
215 							, bx::uint32_min(mtxRegs, predefined.m_count)
216 							);
217 					}
218 					break;
219 
220 				case PredefinedUniform::Model:
221 					{
222 						const Matrix4& model = frameCache.m_matrixCache.m_cache[_draw.m_startMatrix];
223 						_renderer->setShaderUniform4x4f(flags
224 							, predefined.m_loc
225 							, model.un.val
226 							, bx::uint32_min(_draw.m_numMatrices*mtxRegs, predefined.m_count)
227 							);
228 					}
229 					break;
230 
231 				case PredefinedUniform::ModelView:
232 					{
233 						Matrix4 modelView;
234 						const Matrix4& model = frameCache.m_matrixCache.m_cache[_draw.m_startMatrix];
235 						bx::float4x4_mul(&modelView.un.f4x4
236 							, &model.un.f4x4
237 							, &m_view[_view].un.f4x4
238 							);
239 						_renderer->setShaderUniform4x4f(flags
240 							, predefined.m_loc
241 							, modelView.un.val
242 							, bx::uint32_min(mtxRegs, predefined.m_count)
243 							);
244 					}
245 					break;
246 
247 				case PredefinedUniform::ModelViewProj:
248 					{
249 						Matrix4 modelViewProj;
250 						const Matrix4& model = frameCache.m_matrixCache.m_cache[_draw.m_startMatrix];
251 						bx::float4x4_mul(&modelViewProj.un.f4x4
252 							, &model.un.f4x4
253 							, &m_viewProj[_view].un.f4x4
254 							);
255 						_renderer->setShaderUniform4x4f(flags
256 							, predefined.m_loc
257 							, modelViewProj.un.val
258 							, bx::uint32_min(mtxRegs, predefined.m_count)
259 							);
260 					}
261 					break;
262 
263 				case PredefinedUniform::AlphaRef:
264 					{
265 						_renderer->setShaderUniform4f(flags
266 							, predefined.m_loc
267 							, &m_alphaRef
268 							, 1
269 							);
270 					}
271 					break;
272 
273 				default:
274 					BX_CHECK(false, "predefined %d not handled", predefined.m_type);
275 					break;
276 				}
277 			}
278 		}
279 
280 		Matrix4  m_viewTmp[BGFX_CONFIG_MAX_VIEWS];
281 		Matrix4  m_viewProj[BGFX_CONFIG_MAX_VIEWS];
282 		Matrix4* m_view;
283 		Rect     m_rect;
284 		Matrix4  m_invView;
285 		Matrix4  m_invProj;
286 		Matrix4  m_invViewProj;
287 		float    m_alphaRef;
288 		uint16_t m_invViewCached;
289 		uint16_t m_invProjCached;
290 		uint16_t m_invViewProjCached;
291 	};
292 
293 	template <typename Ty, uint16_t MaxHandleT>
294 	class StateCacheLru
295 	{
296 	public:
add(uint64_t _key,const Ty & _value,uint16_t _parent)297 		Ty* add(uint64_t _key, const Ty& _value, uint16_t _parent)
298 		{
299 			uint16_t handle = m_alloc.alloc();
300 			if (UINT16_MAX == handle)
301 			{
302 				uint16_t back = m_alloc.getBack();
303 				invalidate(back);
304 				handle = m_alloc.alloc();
305 			}
306 
307 			BX_CHECK(UINT16_MAX != handle, "Failed to find handle.");
308 
309 			Data& data = m_data[handle];
310 			data.m_hash   = _key;
311 			data.m_value  = _value;
312 			data.m_parent = _parent;
313 			m_hashMap.insert(stl::make_pair(_key, handle) );
314 
315 			return &m_data[handle].m_value;
316 		}
317 
find(uint64_t _key)318 		Ty* find(uint64_t _key)
319 		{
320 			HashMap::iterator it = m_hashMap.find(_key);
321 			if (it != m_hashMap.end() )
322 			{
323 				uint16_t handle = it->second;
324 				m_alloc.touch(handle);
325 				return &m_data[handle].m_value;
326 			}
327 
328 			return NULL;
329 		}
330 
invalidate(uint64_t _key)331 		void invalidate(uint64_t _key)
332 		{
333 			HashMap::iterator it = m_hashMap.find(_key);
334 			if (it != m_hashMap.end() )
335 			{
336 				uint16_t handle = it->second;
337 				m_alloc.free(handle);
338 				m_hashMap.erase(it);
339 				release(m_data[handle].m_value);
340 			}
341 		}
342 
invalidate(uint16_t _handle)343 		void invalidate(uint16_t _handle)
344 		{
345 			if (m_alloc.isValid(_handle) )
346 			{
347 				m_alloc.free(_handle);
348 				Data& data = m_data[_handle];
349 				m_hashMap.erase(m_hashMap.find(data.m_hash) );
350 				release(data.m_value);
351 			}
352 		}
353 
invalidateWithParent(uint16_t _parent)354 		void invalidateWithParent(uint16_t _parent)
355 		{
356 			for (uint16_t ii = 0; ii < m_alloc.getNumHandles();)
357 			{
358 				uint16_t handle = m_alloc.getHandleAt(ii);
359 				Data& data = m_data[handle];
360 
361 				if (data.m_parent == _parent)
362 				{
363 					m_alloc.free(handle);
364 					m_hashMap.erase(m_hashMap.find(data.m_hash) );
365 					release(data.m_value);
366 				}
367 				else
368 				{
369 					++ii;
370 				}
371 			}
372 		}
373 
invalidate()374 		void invalidate()
375 		{
376 			for (uint16_t ii = 0, num = m_alloc.getNumHandles(); ii < num; ++ii)
377 			{
378 				uint16_t handle = m_alloc.getHandleAt(ii);
379 				Data& data = m_data[handle];
380 				release(data.m_value);
381 			}
382 
383 			m_hashMap.clear();
384 			m_alloc.reset();
385 		}
386 
getCount()387 		uint32_t getCount() const
388 		{
389 			return uint32_t(m_hashMap.size() );
390 		}
391 
392 	private:
393 		typedef stl::unordered_map<uint64_t, uint16_t> HashMap;
394 		HashMap m_hashMap;
395 		bx::HandleAllocLruT<MaxHandleT> m_alloc;
396 		struct Data
397 		{
398 			uint64_t m_hash;
399 			Ty m_value;
400 			uint16_t m_parent;
401 		};
402 
403 		Data m_data[MaxHandleT];
404 	};
405 
406 	class StateCache
407 	{
408 	public:
add(uint64_t _key,uint16_t _value)409 		void add(uint64_t _key, uint16_t _value)
410 		{
411 			invalidate(_key);
412 			m_hashMap.insert(stl::make_pair(_key, _value) );
413 		}
414 
find(uint64_t _key)415 		uint16_t find(uint64_t _key)
416 		{
417 			HashMap::iterator it = m_hashMap.find(_key);
418 			if (it != m_hashMap.end() )
419 			{
420 				return it->second;
421 			}
422 
423 			return UINT16_MAX;
424 		}
425 
invalidate(uint64_t _key)426 		void invalidate(uint64_t _key)
427 		{
428 			HashMap::iterator it = m_hashMap.find(_key);
429 			if (it != m_hashMap.end() )
430 			{
431 				m_hashMap.erase(it);
432 			}
433 		}
434 
invalidate()435 		void invalidate()
436 		{
437 			m_hashMap.clear();
438 		}
439 
getCount()440 		uint32_t getCount() const
441 		{
442 			return uint32_t(m_hashMap.size() );
443 		}
444 
445 	private:
446 		typedef stl::unordered_map<uint64_t, uint16_t> HashMap;
447 		HashMap m_hashMap;
448 	};
449 
hasVertexStreamChanged(const RenderDraw & _current,const RenderDraw & _new)450 	inline bool hasVertexStreamChanged(const RenderDraw& _current, const RenderDraw& _new)
451 	{
452 		if (_current.m_streamMask             != _new.m_streamMask
453 		||  _current.m_instanceDataBuffer.idx != _new.m_instanceDataBuffer.idx
454 		||  _current.m_instanceDataOffset     != _new.m_instanceDataOffset
455 		||  _current.m_instanceDataStride     != _new.m_instanceDataStride)
456 		{
457 			return true;
458 		}
459 
460 		for (uint32_t idx = 0, streamMask = _new.m_streamMask
461 			; 0 != streamMask
462 			; streamMask >>= 1, idx += 1
463 			)
464 		{
465 			const uint32_t ntz = bx::uint32_cnttz(streamMask);
466 			streamMask >>= ntz;
467 			idx         += ntz;
468 
469 			if (_current.m_stream[idx].m_handle.idx  != _new.m_stream[idx].m_handle.idx
470 			||  _current.m_stream[idx].m_startVertex != _new.m_stream[idx].m_startVertex)
471 			{
472 				return true;
473 			}
474 		}
475 
476 		return false;
477 	}
478 
479 	template<typename Ty>
480 	struct Profiler
481 	{
482 		Profiler(Frame* _frame, Ty& _gpuTimer, const char (*_viewName)[BGFX_CONFIG_MAX_VIEW_NAME], bool _enabled = true)
m_viewNameProfiler483 			: m_viewName(_viewName)
484 			, m_frame(_frame)
485 			, m_gpuTimer(_gpuTimer)
486 			, m_queryIdx(UINT32_MAX)
487 			, m_numViews(0)
488 			, m_enabled(_enabled && 0 != (_frame->m_debug & BGFX_DEBUG_PROFILER) )
489 		{
490 		}
491 
~ProfilerProfiler492 		~Profiler()
493 		{
494 			m_frame->m_perfStats.numViews = m_numViews;
495 		}
496 
beginProfiler497 		void begin(uint16_t _view)
498 		{
499 			if (m_enabled)
500 			{
501 				ViewStats& viewStats = m_frame->m_perfStats.viewStats[m_numViews];
502 				viewStats.cpuTimeBegin = bx::getHPCounter();
503 
504 				m_queryIdx = m_gpuTimer.begin(_view);
505 
506 				viewStats.view = ViewId(_view);
507 				bx::strCopy(viewStats.name
508 					, BGFX_CONFIG_MAX_VIEW_NAME
509 					, &m_viewName[_view][BGFX_CONFIG_MAX_VIEW_NAME_RESERVED]
510 					);
511 			}
512 		}
513 
endProfiler514 		void end()
515 		{
516 			if (m_enabled
517 			&&  UINT32_MAX != m_queryIdx)
518 			{
519 				m_gpuTimer.end(m_queryIdx);
520 
521 				ViewStats& viewStats = m_frame->m_perfStats.viewStats[m_numViews];
522 				const typename Ty::Result& result = m_gpuTimer.m_result[viewStats.view];
523 
524 				viewStats.cpuTimeEnd = bx::getHPCounter();
525 				viewStats.gpuTimeBegin = result.m_begin;
526 				viewStats.gpuTimeEnd = result.m_end;
527 
528 				++m_numViews;
529 				m_queryIdx = UINT32_MAX;
530 			}
531 		}
532 
533 		const char (*m_viewName)[BGFX_CONFIG_MAX_VIEW_NAME];
534 		Frame*   m_frame;
535 		Ty&      m_gpuTimer;
536 		uint32_t m_queryIdx;
537 		uint16_t m_numViews;
538 		bool     m_enabled;
539 	};
540 
541 } // namespace bgfx
542 
543 #endif // BGFX_RENDERER_H_HEADER_GUARD
544