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