Branimir Karadžić 3 недель назад
Родитель
Сommit
d9d99f51ad
2 измененных файлов с 150 добавлено и 29 удалено
  1. 103 25
      src/renderer_d3d12.cpp
  2. 47 4
      src/renderer_d3d12.h

+ 103 - 25
src/renderer_d3d12.cpp

@@ -656,6 +656,8 @@ namespace bgfx { namespace d3d12
 		}
 	}
 
+	typedef HRESULT (WINAPI* PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)(uint32_t _numFeatures, const IID* _iids, void* _configurationStructs, uint32_t* _configurationStructSizes);
+
 #if USE_D3D12_DYNAMIC_LIB
 	static PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES D3D12EnableExperimentalFeatures;
 	static PFN_D3D12_CREATE_DEVICE                D3D12CreateDevice;
@@ -4108,22 +4110,25 @@ namespace bgfx { namespace d3d12
 		queueDesc.Priority = 0;
 		queueDesc.Flags    = D3D12_COMMAND_QUEUE_FLAG_NONE;
 		queueDesc.NodeMask = 1;
-		DX_CHECK(_device->CreateCommandQueue(&queueDesc
+		DX_CHECK(_device->CreateCommandQueue(
+			  &queueDesc
 			, IID_ID3D12CommandQueue
 			, (void**)&m_commandQueue
 			) );
 
 		m_completedFence = 0;
 		m_currentFence   = 0;
-		DX_CHECK(_device->CreateFence(0
+		DX_CHECK(_device->CreateFence(
+			  0
 			, D3D12_FENCE_FLAG_NONE
 			, IID_ID3D12Fence
 			, (void**)&m_fence
 			) );
 
-		for (uint32_t ii = 0; ii < BX_COUNTOF(m_commandList); ++ii)
+		for (uint32_t ii = 0; ii < kMaxCommandLists; ++ii)
 		{
-			DX_CHECK(_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT
+			DX_CHECK(_device->CreateCommandAllocator(
+				  D3D12_COMMAND_LIST_TYPE_DIRECT
 				, IID_ID3D12CommandAllocator
 				, (void**)&m_commandList[ii].m_commandAllocator
 				) );
@@ -4138,6 +4143,30 @@ namespace bgfx { namespace d3d12
 
 			DX_CHECK(m_commandList[ii].m_commandList->Close() );
 		}
+
+		const D3D12_QUERY_HEAP_DESC queryHeapDesc =
+		{
+			.Type     = D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS,
+			.Count    = kMaxCommandLists,
+			.NodeMask = 1,
+		};
+
+		DX_CHECK(_device->CreateQueryHeap(
+			  &queryHeapDesc
+			, IID_ID3D12QueryHeap
+			, (void**)&m_pipelineStatsQueryHeap
+			) );
+		setDebugObjectName(m_pipelineStatsQueryHeap, "Pipeline Statistics Query Heap");
+
+		m_pipelineStatsReadBack = createCommittedResource(_device, HeapProperty::ReadBack, kMaxCommandLists*sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS) );
+		setDebugObjectName(m_pipelineStatsReadBack, "Pipeline Statistics Read-Back");
+
+		const D3D12_RANGE range =
+		{
+			.Begin = 0,
+			.End = kMaxCommandLists*sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS),
+		};
+		m_pipelineStatsReadBack->Map(0, &range, (void**)&m_pipelineStats);
 	}
 
 	void CommandQueueD3D12::shutdown()
@@ -4146,13 +4175,22 @@ namespace bgfx { namespace d3d12
 
 		DX_RELEASE(m_fence, 0);
 
-		for (uint32_t ii = 0; ii < BX_COUNTOF(m_commandList); ++ii)
+		for (uint32_t ii = 0; ii < kMaxCommandLists; ++ii)
 		{
 			DX_RELEASE(m_commandList[ii].m_commandAllocator, 0);
 			DX_RELEASE(m_commandList[ii].m_commandList, 0);
 		}
 
 		DX_RELEASE(m_commandQueue, 0);
+
+		const D3D12_RANGE range =
+		{
+			.Begin = 0,
+			.End = kMaxCommandLists*sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS),
+		};
+		m_pipelineStatsReadBack->Unmap(0, &range);
+		DX_RELEASE(m_pipelineStatsQueryHeap, 0);
+		DX_RELEASE(m_pipelineStatsReadBack, 0);
 	}
 
 	ID3D12GraphicsCommandList* CommandQueueD3D12::alloc()
@@ -4165,12 +4203,33 @@ namespace bgfx { namespace d3d12
 		CommandList& commandList = m_commandList[m_control.m_current];
 		DX_CHECK(commandList.m_commandAllocator->Reset() );
 		DX_CHECK(commandList.m_commandList->Reset(commandList.m_commandAllocator, NULL) );
+		commandList.m_commandList->BeginQuery(
+			  m_pipelineStatsQueryHeap
+			, D3D12_QUERY_TYPE_PIPELINE_STATISTICS
+			, m_control.m_current
+			);
 		return commandList.m_commandList;
 	}
 
 	uint64_t CommandQueueD3D12::kick()
 	{
-		CommandList& commandList = m_commandList[m_control.m_current];
+		const uint32_t currentIdx = m_control.m_current;
+		CommandList& commandList = m_commandList[currentIdx];
+
+		commandList.m_commandList->EndQuery(
+			  m_pipelineStatsQueryHeap
+			, D3D12_QUERY_TYPE_PIPELINE_STATISTICS
+			, currentIdx
+			);
+		commandList.m_commandList->ResolveQueryData(
+			  m_pipelineStatsQueryHeap
+			, D3D12_QUERY_TYPE_PIPELINE_STATISTICS
+			, currentIdx
+			, 1
+			, m_pipelineStatsReadBack
+			, currentIdx*sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS)
+			);
+
 		DX_CHECK(commandList.m_commandList->Close() );
 
 		ID3D12CommandList* commandLists[] = { commandList.m_commandList };
@@ -4247,6 +4306,8 @@ namespace bgfx { namespace d3d12
 			}
 			ra.clear();
 
+			m_pipelineStatsSum.add(m_pipelineStats[m_control.m_read]);
+
 			m_control.consume(1);
 
 			return true;
@@ -6138,24 +6199,32 @@ namespace bgfx { namespace d3d12
 
 	void TimerQueryD3D12::init()
 	{
-		D3D12_QUERY_HEAP_DESC queryHeapDesc;
-		queryHeapDesc.Count    = m_control.m_size * 2;
-		queryHeapDesc.NodeMask = 1;
-		queryHeapDesc.Type     = D3D12_QUERY_HEAP_TYPE_TIMESTAMP;
-		DX_CHECK(s_renderD3D12->m_device->CreateQueryHeap(&queryHeapDesc
+		ID3D12Device* device = s_renderD3D12->m_device;
+
+		D3D12_QUERY_HEAP_DESC queryHeapDesc =
+		{
+			.Type     = D3D12_QUERY_HEAP_TYPE_TIMESTAMP,
+			.Count    = m_control.m_size * 2,
+			.NodeMask = 1,
+		};
+
+		DX_CHECK(device->CreateQueryHeap(
+			  &queryHeapDesc
 			, IID_ID3D12QueryHeap
 			, (void**)&m_queryHeap
 			) );
+		setDebugObjectName(m_queryHeap, "Timer Query Heap");
 
 		const uint32_t size = queryHeapDesc.Count*sizeof(uint64_t);
-		m_readback = createCommittedResource(s_renderD3D12->m_device
+		m_readback = createCommittedResource(device
 			, HeapProperty::ReadBack
 			, size
 			);
+		setDebugObjectName(m_readback, "Timer Query Read-Back");
 
 		DX_CHECK(s_renderD3D12->m_cmd.m_commandQueue->GetTimestampFrequency(&m_frequency) );
 
-		D3D12_RANGE range = { 0, size };
+		D3D12_RANGE range = { .Begin = 0, .End = size };
 		m_readback->Map(0, &range, (void**)&m_queryResult);
 
 		for (uint32_t ii = 0; ii < BX_COUNTOF(m_result); ++ii)
@@ -6178,6 +6247,8 @@ namespace bgfx { namespace d3d12
 
 	uint32_t TimerQueryD3D12::begin(uint32_t _resultIdx, uint32_t _frameNum)
 	{
+		ID3D12GraphicsCommandList* commandList = s_renderD3D12->m_commandList;
+
 		while (0 == m_control.reserve(1) )
 		{
 			m_control.consume(1);
@@ -6192,8 +6263,6 @@ namespace bgfx { namespace d3d12
 		query.m_ready     = false;
 		query.m_frameNum  = _frameNum;
 
-		ID3D12GraphicsCommandList* commandList = s_renderD3D12->m_commandList;
-
 		uint32_t offset = idx * 2 + 0;
 		commandList->EndQuery(m_queryHeap
 			, D3D12_QUERY_TYPE_TIMESTAMP
@@ -6207,13 +6276,13 @@ namespace bgfx { namespace d3d12
 
 	void TimerQueryD3D12::end(uint32_t _idx)
 	{
+		ID3D12GraphicsCommandList* commandList = s_renderD3D12->m_commandList;
+
 		Query& query = m_query[_idx];
 		query.m_ready = true;
 		query.m_fence = s_renderD3D12->m_cmd.m_currentFence - 1;
 		uint32_t offset = _idx * 2;
 
-		ID3D12GraphicsCommandList* commandList = s_renderD3D12->m_commandList;
-
 		commandList->EndQuery(m_queryHeap
 			, D3D12_QUERY_TYPE_TIMESTAMP
 			, offset + 1
@@ -6276,10 +6345,11 @@ namespace bgfx { namespace d3d12
 			) );
 
 		const uint32_t size = BX_COUNTOF(m_handle)*sizeof(uint64_t);
-		m_readback = createCommittedResource(s_renderD3D12->m_device
-						, HeapProperty::ReadBack
-						, size
-						);
+		m_readback = createCommittedResource(
+			  s_renderD3D12->m_device
+			, HeapProperty::ReadBack
+			, size
+			);
 
 		D3D12_RANGE range = { 0, size };
 		m_readback->Map(0, &range, (void**)&m_result);
@@ -6527,9 +6597,6 @@ namespace bgfx { namespace d3d12
 		static ViewState viewState;
 		viewState.reset(_render);
 
-// 		bool wireframe = !!(_render->m_debug&BGFX_DEBUG_WIREFRAME);
-// 		setDebugWireframe(wireframe);
-
 		uint16_t currentSamplerStateIdx = kInvalidHandle;
 		ProgramHandle currentProgram    = BGFX_INVALID_HANDLE;
 		uint32_t currentBindHash        = 0;
@@ -7389,7 +7456,6 @@ namespace bgfx { namespace d3d12
 		{
 			BGFX_D3D12_PROFILER_BEGIN_LITERAL("debugstats", kColorFrame);
 
-//			m_needPresent = true;
 			TextVideoMem& tvm = m_textVideoMem;
 
 			static int64_t next = timeEnd;
@@ -7548,6 +7614,17 @@ namespace bgfx { namespace d3d12
 					);
 				pos++;
 
+				tvm.printf(10, pos++, 0x8b, " Pipeline Statistics:");
+				const CommandQueueD3D12::PipelineStats& pipelineStats = m_cmd.m_pipelineStatsSum;
+				tvm.printf(10, pos++, 0x8b, "     IAVertices: %llu", pipelineStats.IAVertices);
+				tvm.printf(10, pos++, 0x8b, "   IAPrimitives: %llu", pipelineStats.IAPrimitives);
+				tvm.printf(10, pos++, 0x8b, "  VSInvocations: %llu", pipelineStats.VSInvocations);
+				tvm.printf(10, pos++, 0x8b, "   CInvocations: %llu", pipelineStats.CInvocations);
+				tvm.printf(10, pos++, 0x8b, "    CPrimitives: %llu", pipelineStats.CPrimitives);
+				tvm.printf(10, pos++, 0x8b, "  PSInvocations: %llu", pipelineStats.PSInvocations);
+				tvm.printf(10, pos++, 0x8b, "  CSInvocations: %llu", pipelineStats.CSInvocations);
+				pos++;
+
 				double captureMs = double(captureElapsed)*toMs;
 				tvm.printf(10, pos++, 0x8b, "     Capture: %7.4f [ms] ", captureMs);
 
@@ -7616,6 +7693,7 @@ namespace bgfx { namespace d3d12
 #endif // BX_PLATFORM_WINDOWS
 
 		m_backBufferColorFence[m_backBufferColorIdx] = kick();
+		m_cmd.m_pipelineStatsSum.reset();
 	}
 
 } /* namespace d3d12 */ } // namespace bgfx

+ 47 - 4
src/renderer_d3d12.h

@@ -77,8 +77,6 @@ extern "C" uint64_t                    WINAPI bgfx_PIXEventsReplaceBlock(PIXEven
 
 namespace bgfx { namespace d3d12
 {
-	typedef HRESULT (WINAPI* PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)(uint32_t _numFeatures, const IID* _iids, void* _configurationStructs, uint32_t* _configurationStructSizes);
-
 	struct Rdt
 	{
 		enum Enum
@@ -372,6 +370,8 @@ namespace bgfx { namespace d3d12
 
 	struct CommandQueueD3D12
 	{
+		static constexpr uint32_t kMaxCommandLists = 256;
+
 		CommandQueueD3D12()
 			: m_currentFence(0)
 			, m_completedFence(0)
@@ -396,14 +396,57 @@ namespace bgfx { namespace d3d12
 			HANDLE m_event;
 		};
 
+		struct PipelineStats
+		{
+			PipelineStats()
+			{
+				reset();
+			}
+
+			void reset()
+			{
+				IAVertices    = 0;
+				IAPrimitives  = 0;
+				VSInvocations = 0;
+				CInvocations  = 0;
+				CPrimitives   = 0;
+				PSInvocations = 0;
+				CSInvocations = 0;
+			}
+
+			void add(const D3D12_QUERY_DATA_PIPELINE_STATISTICS& _stats)
+			{
+				IAVertices    += _stats.IAVertices;
+				IAPrimitives  += _stats.IAPrimitives;
+				VSInvocations += _stats.VSInvocations;
+				CInvocations  += _stats.CInvocations;
+				CPrimitives   += _stats.CPrimitives;
+				PSInvocations += _stats.PSInvocations;
+				CSInvocations += _stats.CSInvocations;
+			}
+
+			uint64_t IAVertices;
+			uint64_t IAPrimitives;
+			uint64_t VSInvocations;
+			uint64_t CInvocations;
+			uint64_t CPrimitives;
+			uint64_t PSInvocations;
+			uint64_t CSInvocations;
+		};
+
 		ID3D12CommandQueue* m_commandQueue;
 		uint64_t m_currentFence;
 		uint64_t m_completedFence;
 		ID3D12Fence* m_fence;
-		CommandList m_commandList[256];
+		CommandList m_commandList[kMaxCommandLists];
 		typedef stl::vector<ID3D12Resource*> ResourceArray;
-		ResourceArray m_release[256];
+		ResourceArray m_release[kMaxCommandLists];
 		bx::RingBufferControl m_control;
+
+		ID3D12Resource*  m_pipelineStatsReadBack;
+		ID3D12QueryHeap* m_pipelineStatsQueryHeap;
+		D3D12_QUERY_DATA_PIPELINE_STATISTICS* m_pipelineStats;
+		PipelineStats m_pipelineStatsSum;
 	};
 
 	struct BatchD3D12