D3D12: Added temporary staging buffers.

This commit is contained in:
Branimir Karadžić 2015-08-08 18:06:33 -07:00
parent 437656b870
commit 8e12de0e57
3 changed files with 89 additions and 92 deletions

View file

@ -32,9 +32,9 @@ namespace bgfx
#define _DX_RELEASE(_ptr, _expected, _check) \ #define _DX_RELEASE(_ptr, _expected, _check) \
BX_MACRO_BLOCK_BEGIN \ 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); \ _check(isGraphicsDebuggerPresent() || _expected == count, "%p RefCount is %d (expected %d).", _ptr, count, _expected); BX_UNUSED(count); \
_ptr = NULL; \ _ptr = NULL; \
} \ } \

View file

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

View file

@ -107,7 +107,6 @@ namespace bgfx { namespace d3d12
{ {
BufferD3D12() BufferD3D12()
: m_ptr(NULL) : m_ptr(NULL)
, m_staging(NULL)
, m_state(D3D12_RESOURCE_STATE_COMMON) , m_state(D3D12_RESOURCE_STATE_COMMON)
, m_size(0) , m_size(0)
, m_flags(BGFX_BUFFER_NONE) , 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 update(ID3D12GraphicsCommandList* _commandList, uint32_t _offset, uint32_t _size, void* _data, bool _discard = false);
void destroy() void destroy()
@ -123,17 +122,15 @@ namespace bgfx { namespace d3d12
if (NULL != m_ptr) if (NULL != m_ptr)
{ {
DX_RELEASE(m_ptr, 0); DX_RELEASE(m_ptr, 0);
DX_RELEASE(m_staging, 0);
m_dynamic = false; 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_SHADER_RESOURCE_VIEW_DESC m_srvd;
D3D12_UNORDERED_ACCESS_VIEW_DESC m_uavd; D3D12_UNORDERED_ACCESS_VIEW_DESC m_uavd;
ID3D12Resource* m_ptr; ID3D12Resource* m_ptr;
ID3D12Resource* m_staging;
D3D12_RESOURCE_STATES m_state; D3D12_RESOURCE_STATES m_state;
uint32_t m_size; uint32_t m_size;
uint16_t m_flags; uint16_t m_flags;
@ -240,7 +237,6 @@ namespace bgfx { namespace d3d12
TextureD3D12() TextureD3D12()
: m_ptr(NULL) : m_ptr(NULL)
, m_staging(NULL)
, m_state(D3D12_RESOURCE_STATE_COMMON) , m_state(D3D12_RESOURCE_STATE_COMMON)
, m_numMips(0) , 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 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 commit(uint8_t _stage, uint32_t _flags = BGFX_SAMPLER_DEFAULT_FLAGS);
void resolve(); 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_SHADER_RESOURCE_VIEW_DESC m_srvd;
D3D12_UNORDERED_ACCESS_VIEW_DESC m_uavd; D3D12_UNORDERED_ACCESS_VIEW_DESC m_uavd;
ID3D12Resource* m_ptr; ID3D12Resource* m_ptr;
ID3D12Resource* m_staging;
D3D12_RESOURCE_STATES m_state; D3D12_RESOURCE_STATES m_state;
uint32_t m_flags; uint32_t m_flags;
uint16_t m_samplerIdx; uint16_t m_samplerIdx;
@ -358,11 +353,7 @@ namespace bgfx { namespace d3d12
{ {
while (0 == m_control.reserve(1) ) while (0 == m_control.reserve(1) )
{ {
CommandList& commandList = m_commandList[m_control.m_read]; consume();
WaitForSingleObject(commandList.m_event, INFINITE);
CloseHandle(commandList.m_event);
m_control.consume(1);
} }
CommandList& commandList = m_commandList[m_control.m_current]; CommandList& commandList = m_commandList[m_control.m_current];
@ -393,14 +384,7 @@ namespace bgfx { namespace d3d12
{ {
while (0 < m_control.available() ) while (0 < m_control.available() )
{ {
CommandList& commandList = m_commandList[m_control.m_read]; consume();
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);
if (!_finishAll if (!_finishAll
&& _waitFence <= m_completedFence) && _waitFence <= m_completedFence)
@ -412,6 +396,30 @@ namespace bgfx { namespace d3d12
BX_CHECK(0 == m_control.available(), ""); 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 struct CommandList
{ {
ID3D12GraphicsCommandList* m_commandList; ID3D12GraphicsCommandList* m_commandList;
@ -424,6 +432,8 @@ namespace bgfx { namespace d3d12
uint64_t m_completedFence; uint64_t m_completedFence;
ID3D12Fence* m_fence; ID3D12Fence* m_fence;
CommandList m_commandList[4]; CommandList m_commandList[4];
typedef stl::vector<ID3D12Resource*> ResourceArray;
ResourceArray m_release[4];
bx::RingBufferControl m_control; bx::RingBufferControl m_control;
}; };