Browse Source

D3D: Added state cache LRU.

Branimir Karadžić 10 years ago
parent
commit
06a865cb7b
4 changed files with 108 additions and 31 deletions
  1. 63 0
      src/renderer_d3d.h
  2. 1 0
      src/renderer_d3d11.cpp
  3. 41 29
      src/renderer_d3d12.cpp
  4. 3 2
      src/renderer_d3d12.h

+ 63 - 0
src/renderer_d3d.h

@@ -192,6 +192,69 @@ namespace bgfx
 		HashMap m_hashMap;
 	};
 
+	template <typename Ty, uint16_t MaxHandleT>
+	class StateCacheLru
+	{
+	public:
+		void add(uint64_t _hash, Ty _value)
+		{
+			uint16_t handle = m_alloc.alloc();
+			if (UINT16_MAX == handle)
+			{
+				uint16_t back = m_alloc.getBack();
+				m_alloc.free(back);
+				HashMap::iterator it = m_hashMap.find(m_data[back].m_hash);
+				if (it != m_hashMap.end() )
+				{
+					m_hashMap.erase(it);
+				}
+
+				handle = m_alloc.alloc();
+			}
+
+			BX_CHECK(UINT16_MAX != handle, "Failed to find handle.");
+
+			Data& data = m_data[handle];
+			data.m_hash  = _hash;
+			data.m_value = _value;
+			m_hashMap.insert(stl::make_pair(_hash, handle) );
+		}
+
+		Ty* find(uint64_t _hash)
+		{
+			HashMap::iterator it = m_hashMap.find(_hash);
+			if (it != m_hashMap.end() )
+			{
+				return &m_data[it->second].m_value;
+			}
+
+			return NULL;
+		}
+
+		void invalidate()
+		{
+			m_hashMap.clear();
+			m_alloc.reset();
+		}
+
+		uint32_t getCount() const
+		{
+			return uint32_t(m_hashMap.size() );
+		}
+
+	private:
+		typedef stl::unordered_map<uint64_t, uint16_t> HashMap;
+		HashMap m_hashMap;
+		bx::HandleAllocLruT<MaxHandleT> m_alloc;
+		struct Data
+		{
+			uint64_t m_hash;
+			Ty m_value;
+		};
+
+		Data m_data[MaxHandleT];
+	};
+
 } // namespace bgfx
 
 #endif // BGFX_RENDERER_D3D_H_HEADER_GUARD

+ 1 - 0
src/renderer_d3d11.cpp

@@ -680,6 +680,7 @@ namespace bgfx { namespace d3d11
 					uint32_t flags = 0
 						| D3D11_CREATE_DEVICE_SINGLETHREADED
 						| D3D11_CREATE_DEVICE_BGRA_SUPPORT
+//						| D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
 						| (BX_ENABLED(BGFX_CONFIG_DEBUG) ? D3D11_CREATE_DEVICE_DEBUG : 0)
 						;
 

+ 41 - 29
src/renderer_d3d12.cpp

@@ -702,7 +702,7 @@ namespace bgfx { namespace d3d12
 						filter.DenyList.pCategoryList = catlist;
 						m_infoQueue->PushStorageFilter(&filter);
 
-						DX_RELEASE(m_infoQueue, 19);
+						DX_RELEASE_WARNONLY(m_infoQueue, 19);
 					}
 				}
 
@@ -3690,6 +3690,7 @@ data.NumQualityLevels = 0;
 		scratchBuffer.reset(gpuHandle);
 
 		D3D12_GPU_VIRTUAL_ADDRESS gpuAddress = {};
+		StateCacheLru<D3D12_GPU_DESCRIPTOR_HANDLE, 64> bindLru;
 
 		setResourceBarrier(m_commandList
 			, m_backBufferColor[m_backBufferColorIdx]
@@ -4069,41 +4070,51 @@ data.NumQualityLevels = 0;
 						; currentBindHash  = bindHash
 						)
 					{
-						D3D12_GPU_DESCRIPTOR_HANDLE srvHandle[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
-						uint32_t samplerFlags[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
+						D3D12_GPU_DESCRIPTOR_HANDLE* srv = bindLru.find(bindHash);
+						if (NULL == srv)
 						{
-							srvHandle[0].ptr = 0;
-							for (uint32_t stage = 0; stage < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++stage)
+							D3D12_GPU_DESCRIPTOR_HANDLE srvHandle[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
+							uint32_t samplerFlags[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
 							{
-								const Binding& sampler = draw.m_bind[stage];
-								if (invalidHandle != sampler.m_idx)
+								srvHandle[0].ptr = 0;
+								for (uint32_t stage = 0; stage < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++stage)
 								{
-									TextureD3D12& texture = m_textures[sampler.m_idx];
-									scratchBuffer.alloc(srvHandle[stage], texture);
-									samplerFlags[stage] = (0 == (BGFX_SAMPLER_DEFAULT_FLAGS & sampler.m_un.m_draw.m_flags)
-										? sampler.m_un.m_draw.m_flags
-										: texture.m_flags
-										) & BGFX_TEXTURE_SAMPLER_BITS_MASK
-										;
+									const Binding& sampler = draw.m_bind[stage];
+									if (invalidHandle != sampler.m_idx)
+									{
+										TextureD3D12& texture = m_textures[sampler.m_idx];
+										scratchBuffer.alloc(srvHandle[stage], texture);
+										samplerFlags[stage] = (0 == (BGFX_SAMPLER_DEFAULT_FLAGS & sampler.m_un.m_draw.m_flags)
+											? sampler.m_un.m_draw.m_flags
+											: texture.m_flags
+											) & BGFX_TEXTURE_SAMPLER_BITS_MASK
+											;
+									}
+									else
+									{
+										memcpy(&srvHandle[stage], &srvHandle[0], sizeof(D3D12_GPU_DESCRIPTOR_HANDLE) );
+										samplerFlags[stage] = 0;
+									}
 								}
-								else
+							}
+
+							if (srvHandle[0].ptr != 0)
+							{
+								uint16_t samplerStateIdx = getSamplerState(samplerFlags);
+								if (samplerStateIdx != currentSamplerStateIdx)
 								{
-									memcpy(&srvHandle[stage], &srvHandle[0], sizeof(D3D12_GPU_DESCRIPTOR_HANDLE) );
-									samplerFlags[stage] = 0;
+									currentSamplerStateIdx = samplerStateIdx;
+									m_commandList->SetGraphicsRootDescriptorTable(Rdt::Sampler, m_samplerAllocator.get(samplerStateIdx) );
 								}
+
+								m_commandList->SetGraphicsRootDescriptorTable(Rdt::SRV, srvHandle[0]);
+
+								bindLru.add(bindHash, srvHandle[0]);
 							}
 						}
-
-						if (srvHandle[0].ptr != 0)
+						else 
 						{
-							uint16_t samplerStateIdx = getSamplerState(samplerFlags);
-							if (samplerStateIdx != currentSamplerStateIdx)
-							{
-								currentSamplerStateIdx = samplerStateIdx;
-								m_commandList->SetGraphicsRootDescriptorTable(Rdt::Sampler, m_samplerAllocator.get(samplerStateIdx) );
-							}
-
-							m_commandList->SetGraphicsRootDescriptorTable(Rdt::SRV, srvHandle[0]);
+							m_commandList->SetGraphicsRootDescriptorTable(Rdt::SRV, *srv);
 						}
 					}
 
@@ -4335,10 +4346,11 @@ data.NumQualityLevels = 0;
 
 				pos++;
 				tvm.printf(10, pos++, 0x8e, " State cache:                                ");
-				tvm.printf(10, pos++, 0x8e, " PSO    | Sampler | Queued                   ");
-				tvm.printf(10, pos++, 0x8e, " %6d |  %6d | %6d"
+				tvm.printf(10, pos++, 0x8e, " PSO    | Sampler | Bind   | Queued          ");
+				tvm.printf(10, pos++, 0x8e, " %6d |  %6d | %6d | %6d"
 					, m_pipelineStateCache.getCount()
 					, m_samplerStateCache.getCount()
+					, bindLru.getCount()
 					, m_cmd.m_control.available()
 					);
 				pos++;

+ 3 - 2
src/renderer_d3d12.h

@@ -297,6 +297,7 @@ namespace bgfx { namespace d3d12
 		CommandQueue()
 			: m_control(BX_COUNTOF(m_commandList) )
 		{
+			BX_STATIC_ASSERT(BX_COUNTOF(m_commandList) == BX_COUNTOF(m_release) );
 		}
 
 		void init(ID3D12Device* _device)
@@ -454,9 +455,9 @@ namespace bgfx { namespace d3d12
 		uint64_t m_currentFence;
 		uint64_t m_completedFence;
 		ID3D12Fence* m_fence;
-		CommandList m_commandList[4];
+		CommandList m_commandList[32];
 		typedef stl::vector<ID3D12Resource*> ResourceArray;
-		ResourceArray m_release[4];
+		ResourceArray m_release[32];
 		bx::RingBufferControl m_control;
 	};