Browse Source

D3D12: Added temporary staging buffers.

Branimir Karadžić 10 years ago
parent
commit
8e12de0e57
3 changed files with 89 additions and 92 deletions
  1. 2 2
      src/renderer_d3d.h
  2. 56 69
      src/renderer_d3d12.cpp
  3. 31 21
      src/renderer_d3d12.h

+ 2 - 2
src/renderer_d3d.h

@@ -32,9 +32,9 @@ namespace bgfx
 
 #define _DX_RELEASE(_ptr, _expected, _check) \
 			BX_MACRO_BLOCK_BEGIN \
-				if (NULL != _ptr) \
+				if (NULL != (_ptr) ) \
 				{ \
-					ULONG count = _ptr->Release(); \
+					ULONG count = (_ptr)->Release(); \
 					_check(isGraphicsDebuggerPresent() || _expected == count, "%p RefCount is %d (expected %d).", _ptr, count, _expected); BX_UNUSED(count); \
 					_ptr = NULL; \
 				} \

+ 56 - 69
src/renderer_d3d12.cpp

@@ -43,6 +43,23 @@ namespace bgfx { namespace d3d12
 	};
 	BX_STATIC_ASSERT(BX_COUNTOF(s_primInfo) == BX_COUNTOF(s_primName)+1);
 
+	struct DrawIndirectCommand
+	{
+//		D3D12_GPU_VIRTUAL_ADDRESS srv;
+		D3D12_GPU_VIRTUAL_ADDRESS cbv;
+		D3D12_VERTEX_BUFFER_VIEW vbv;
+		D3D12_DRAW_ARGUMENTS draw;
+	};
+
+	struct DrawIndexedIndirectCommand
+	{
+//		D3D12_GPU_VIRTUAL_ADDRESS srv;
+		D3D12_GPU_VIRTUAL_ADDRESS cbv;
+		D3D12_VERTEX_BUFFER_VIEW vbv;
+		D3D12_INDEX_BUFFER_VIEW ibv;
+		D3D12_DRAW_INDEXED_ARGUMENTS drawIndexed;
+	};
+
 	static const uint32_t s_checkMsaa[] =
 	{
 		0,
@@ -775,14 +792,6 @@ namespace bgfx { namespace d3d12
 					{ D3D12_INDIRECT_ARGUMENT_TYPE_DRAW,                 0            },
 				};
 
-				struct DrawIndirectCommand
-				{
-//					D3D12_GPU_VIRTUAL_ADDRESS srv;
-					D3D12_GPU_VIRTUAL_ADDRESS cbv;
-					D3D12_VERTEX_BUFFER_VIEW vbv;
-					D3D12_DRAW_ARGUMENTS draw;
-				};
-
 				D3D12_COMMAND_SIGNATURE_DESC drawCommandSignature =
 				{
 					sizeof(DrawIndirectCommand),
@@ -806,15 +815,6 @@ namespace bgfx { namespace d3d12
 					{ D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED,         0            },
 				};
 
-				struct DrawIndexedIndirectCommand
-				{
-//					D3D12_GPU_VIRTUAL_ADDRESS srv;
-					D3D12_GPU_VIRTUAL_ADDRESS cbv;
-					D3D12_VERTEX_BUFFER_VIEW vbv;
-					D3D12_INDEX_BUFFER_VIEW ibv;
-					D3D12_DRAW_INDEXED_ARGUMENTS drawIndexed;
-				};
-
 				D3D12_COMMAND_SIGNATURE_DESC drawIndexedCommandSignature =
 				{
 					sizeof(DrawIndexedIndirectCommand),
@@ -2673,7 +2673,7 @@ data.NumQualityLevels = 0;
 		{ { DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_UINT,  DXGI_FORMAT_R32G32B32A32_FLOAT }, 16 }, // BGFX_BUFFER_COMPUTE_FORMAT_32x4
 	};
 
-	void BufferD3D12::create(uint32_t _size, void* _data, uint16_t _flags, bool _vertex)
+	void BufferD3D12::create(uint32_t _size, void* _data, uint16_t _flags, bool _vertex, uint32_t _stride)
 	{
 		m_size    = _size;
 		m_flags   = _flags;
@@ -2728,6 +2728,8 @@ data.NumQualityLevels = 0;
 			}
 		}
 
+		stride = 0 == _stride ? stride : _stride;
+
 		m_srvd.Format                      = format;
 		m_srvd.ViewDimension               = D3D12_SRV_DIMENSION_BUFFER;
 		m_srvd.Shader4ComponentMapping     = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
@@ -2749,16 +2751,7 @@ data.NumQualityLevels = 0;
 
 		m_ptr = createCommittedResource(device, HeapProperty::Default, _size, flags);
 
-		if (!needUav)
-		{
-			m_staging = createCommittedResource(device, HeapProperty::Upload, _size);
-		}
-
-		if (m_dynamic)
-		{
-			setState(commandList, D3D12_RESOURCE_STATE_GENERIC_READ);
-		}
-		else
+		if (!m_dynamic)
 		{
 			setState(commandList, D3D12_RESOURCE_STATE_COPY_DEST);
 
@@ -2767,41 +2760,39 @@ data.NumQualityLevels = 0;
 			subresource.RowPitch   = _size;
 			subresource.SlicePitch = subresource.RowPitch;
 
+			ID3D12Resource* staging = createCommittedResource(s_renderD3D12->m_device, HeapProperty::Upload, _size);
+
 			UpdateSubresources<1>(commandList
 				, m_ptr
-				, m_staging
+				, staging
 				, 0
 				, 0
 				, 1
 				, &subresource
 				);
 
-			setState(commandList, D3D12_RESOURCE_STATE_GENERIC_READ);
+			s_renderD3D12->m_cmd.release(staging);
 		}
+
+		setState(commandList, D3D12_RESOURCE_STATE_GENERIC_READ);
 	}
 
-	void BufferD3D12::update(ID3D12GraphicsCommandList* _commandList, uint32_t /*_offset*/, uint32_t _size, void* _data, bool /*_discard*/)
+	void BufferD3D12::update(ID3D12GraphicsCommandList* _commandList, uint32_t _offset, uint32_t _size, void* _data, bool /*_discard*/)
 	{
-		setState(_commandList, D3D12_RESOURCE_STATE_COPY_DEST);
-
-		D3D12_SUBRESOURCE_DATA subresource;
-		subresource.pData      = _data;
-		subresource.RowPitch   = _size;
-		subresource.SlicePitch = subresource.RowPitch;
+		ID3D12Resource* staging = createCommittedResource(s_renderD3D12->m_device, HeapProperty::Upload, _size);
+		uint8_t* data;
+		DX_CHECK(staging->Map(0, nullptr, (void**)&data) );
+		memcpy(data, _data, _size);
+		staging->Unmap(0, NULL);
 
-		UpdateSubresources<1>(_commandList
-			, m_ptr
-			, m_staging
-			, 0
-			, 0
-			, 1
-			, &subresource
-			);
+		D3D12_RESOURCE_STATES state = setState(_commandList, D3D12_RESOURCE_STATE_COPY_DEST);
+		_commandList->CopyBufferRegion(m_ptr, _offset, staging, _offset, _size);
+		setState(_commandList, state);
 
-		setState(_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);
+		s_renderD3D12->m_cmd.release(staging);
 	}
 
-	void BufferD3D12::setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state)
+	D3D12_RESOURCE_STATES BufferD3D12::setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state)
 	{
 		if (m_state != _state)
 		{
@@ -2811,8 +2802,10 @@ data.NumQualityLevels = 0;
 				, _state
 				);
 
-			m_state = _state;
+			bx::xchg(m_state, _state);
 		}
+
+		return _state;
 	}
 
 	void VertexBufferD3D12::create(uint32_t _size, void* _data, VertexDeclHandle _declHandle, uint16_t _flags)
@@ -3267,13 +3260,13 @@ data.NumQualityLevels = 0;
 
 			if (kk != 0)
 			{
-				m_staging = createCommittedResource(device, HeapProperty::Upload, totalSize);
+				ID3D12Resource* staging = createCommittedResource(s_renderD3D12->m_device, HeapProperty::Upload, totalSize);
 
 				setState(commandList,D3D12_RESOURCE_STATE_COPY_DEST);
 
 				uint64_t result = UpdateSubresources(commandList
 					, m_ptr
-					, m_staging
+					, staging
 					, 0
 					, 0
 					, numSrd
@@ -3283,11 +3276,11 @@ data.NumQualityLevels = 0;
 				BX_TRACE("Update subresource %" PRId64, result);
 
 				setState(commandList, state);
+
+				s_renderD3D12->m_cmd.release(staging);
 			}
 			else
 			{
-				m_staging = NULL;
-
 				setState(commandList, state);
 			}
 
@@ -3312,9 +3305,6 @@ data.NumQualityLevels = 0;
 		{
 			DX_RELEASE(m_ptr, 0);
 			m_ptr = NULL;
-
-			DX_RELEASE(m_staging, 0);
-			m_staging = NULL;
 		}
 	}
 
@@ -3327,12 +3317,6 @@ data.NumQualityLevels = 0;
 		const uint32_t rectpitch = _rect.m_width*bpp/8;
 		const uint32_t srcpitch  = UINT16_MAX == _pitch ? rectpitch : _pitch;
 
-		s_renderD3D12->m_cmd.finish(s_renderD3D12->m_cmd.kick() );
-		s_renderD3D12->m_commandList = s_renderD3D12->m_cmd.alloc();
-		_commandList = s_renderD3D12->m_commandList;
-
-		DX_RELEASE(m_staging, 0);
-
 		D3D12_RESOURCE_DESC desc = m_ptr->GetDesc();
 
 		desc.Height = _rect.m_height;
@@ -3351,17 +3335,16 @@ data.NumQualityLevels = 0;
 			, &totalBytes
 			);
 
-		m_staging = createCommittedResource(s_renderD3D12->m_device, HeapProperty::Upload, totalBytes);
-		DX_NAME(m_staging, "texture %4d: staging, update", this - s_renderD3D12->m_textures);
+		ID3D12Resource* staging = createCommittedResource(s_renderD3D12->m_device, HeapProperty::Upload, totalBytes);
 
 		uint8_t* data;
 
-		DX_CHECK(m_staging->Map(0, NULL, (void**)&data) );
+		DX_CHECK(staging->Map(0, NULL, (void**)&data) );
 		for (uint32_t ii = 0, height = _rect.m_height; ii < height; ++ii)
 		{
 			memcpy(&data[ii*rowPitch], &_mem->data[ii*srcpitch], srcpitch);
 		}
-		m_staging->Unmap(0, NULL);
+		staging->Unmap(0, NULL);
 
 		D3D12_BOX box;
 		box.left   = 0;
@@ -3371,11 +3354,13 @@ data.NumQualityLevels = 0;
 		box.front  = _z;
 		box.back   = _z+_depth;
 
-		D3D12_TEXTURE_COPY_LOCATION dst = { m_ptr,     D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, { subres } };
-		D3D12_TEXTURE_COPY_LOCATION src = { m_staging, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,  layout     };
+		D3D12_TEXTURE_COPY_LOCATION dst = { m_ptr,   D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, { subres } };
+		D3D12_TEXTURE_COPY_LOCATION src = { staging, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,  layout     };
 		_commandList->CopyTextureRegion(&dst, _rect.m_x, _rect.m_y, 0, &src, &box);
 
 		setState(_commandList, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
+
+		s_renderD3D12->m_cmd.release(staging);
 	}
 
 	void TextureD3D12::commit(uint8_t _stage, uint32_t _flags)
@@ -3387,7 +3372,7 @@ data.NumQualityLevels = 0;
 	{
 	}
 
-	void TextureD3D12::setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state)
+	D3D12_RESOURCE_STATES TextureD3D12::setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state)
 	{
 		if (m_state != _state)
 		{
@@ -3397,8 +3382,10 @@ data.NumQualityLevels = 0;
 				, _state
 				);
 
-			m_state = _state;
+			bx::xchg(m_state, _state);
 		}
+
+		return _state;
 	}
 
 	void FrameBufferD3D12::create(uint8_t _num, const TextureHandle* _handles)

+ 31 - 21
src/renderer_d3d12.h

@@ -107,7 +107,6 @@ namespace bgfx { namespace d3d12
 	{
 		BufferD3D12()
 			: m_ptr(NULL)
-			, m_staging(NULL)
 			, m_state(D3D12_RESOURCE_STATE_COMMON)
 			, m_size(0)
 			, m_flags(BGFX_BUFFER_NONE)
@@ -115,7 +114,7 @@ namespace bgfx { namespace d3d12
 		{
 		}
 
-		void create(uint32_t _size, void* _data, uint16_t _flags, bool _vertex);
+		void create(uint32_t _size, void* _data, uint16_t _flags, bool _vertex, uint32_t _stride = 0);
 		void update(ID3D12GraphicsCommandList* _commandList, uint32_t _offset, uint32_t _size, void* _data, bool _discard = false);
 
 		void destroy()
@@ -123,17 +122,15 @@ namespace bgfx { namespace d3d12
 			if (NULL != m_ptr)
 			{
 				DX_RELEASE(m_ptr, 0);
-				DX_RELEASE(m_staging, 0);
 				m_dynamic = false;
 			}
 		}
 
-		void setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state);
+		D3D12_RESOURCE_STATES setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state);
 
 		D3D12_SHADER_RESOURCE_VIEW_DESC  m_srvd;
 		D3D12_UNORDERED_ACCESS_VIEW_DESC m_uavd;
 		ID3D12Resource* m_ptr;
-		ID3D12Resource* m_staging;
 		D3D12_RESOURCE_STATES m_state;
 		uint32_t m_size;
 		uint16_t m_flags;
@@ -240,7 +237,6 @@ namespace bgfx { namespace d3d12
 
 		TextureD3D12()
 			: m_ptr(NULL)
-			, m_staging(NULL)
 			, m_state(D3D12_RESOURCE_STATE_COMMON)
 			, m_numMips(0)
 		{
@@ -251,12 +247,11 @@ namespace bgfx { namespace d3d12
 		void update(ID3D12GraphicsCommandList* _commandList, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem);
 		void commit(uint8_t _stage, uint32_t _flags = BGFX_SAMPLER_DEFAULT_FLAGS);
 		void resolve();
-		void setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state);
+		D3D12_RESOURCE_STATES setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state);
 
 		D3D12_SHADER_RESOURCE_VIEW_DESC  m_srvd;
 		D3D12_UNORDERED_ACCESS_VIEW_DESC m_uavd;
 		ID3D12Resource* m_ptr;
-		ID3D12Resource* m_staging;
 		D3D12_RESOURCE_STATES m_state;
 		uint32_t m_flags;
 		uint16_t m_samplerIdx;
@@ -358,11 +353,7 @@ namespace bgfx { namespace d3d12
 		{
 			while (0 == m_control.reserve(1) )
 			{
-				CommandList& commandList = m_commandList[m_control.m_read];
-				WaitForSingleObject(commandList.m_event, INFINITE);
-				CloseHandle(commandList.m_event);
-
-				m_control.consume(1);
+				consume();
 			}
 
 			CommandList& commandList = m_commandList[m_control.m_current];
@@ -393,14 +384,7 @@ namespace bgfx { namespace d3d12
 		{
 			while (0 < m_control.available() )
 			{
-				CommandList& commandList = m_commandList[m_control.m_read];
-				WaitForSingleObject(commandList.m_event, INFINITE);
-				CloseHandle(commandList.m_event);
-				commandList.m_event = NULL;
-				m_completedFence = m_fence->GetCompletedValue();
-				m_commandQueue->Wait(m_fence, m_completedFence);
-
-				m_control.consume(1);
+				consume();
 
 				if (!_finishAll
 				&&  _waitFence <= m_completedFence)
@@ -412,6 +396,30 @@ namespace bgfx { namespace d3d12
 			BX_CHECK(0 == m_control.available(), "");
 		}
 
+		void release(ID3D12Resource* _ptr)
+		{
+			m_release[m_control.m_current].push_back(_ptr);
+		}
+
+		void consume()
+		{
+			CommandList& commandList = m_commandList[m_control.m_read];
+			WaitForSingleObject(commandList.m_event, INFINITE);
+			CloseHandle(commandList.m_event);
+			commandList.m_event = NULL;
+			m_completedFence = m_fence->GetCompletedValue();
+			m_commandQueue->Wait(m_fence, m_completedFence);
+
+			ResourceArray& ra = m_release[m_control.m_read];
+			for (ResourceArray::iterator it = ra.begin(), itEnd = ra.end(); it != itEnd; ++it)
+			{
+				DX_RELEASE(*it, 0);
+			}
+			ra.clear();
+
+			m_control.consume(1);
+		}
+
 		struct CommandList
 		{
 			ID3D12GraphicsCommandList* m_commandList;
@@ -424,6 +432,8 @@ namespace bgfx { namespace d3d12
 		uint64_t m_completedFence;
 		ID3D12Fence* m_fence;
 		CommandList m_commandList[4];
+		typedef stl::vector<ID3D12Resource*> ResourceArray;
+		ResourceArray m_release[4];
 		bx::RingBufferControl m_control;
 	};