From 3494f0538a108730f9bb25d79416136d2b329af4 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Sun, 25 Nov 2018 12:08:42 -0800 Subject: Renamed/moved IBuffer::Map() to IDeviceContext::MapBuffer() Renamed/moved IBuffer::Unmap() to IDeviceContext::UnmapBuffer() Closed https://github.com/DiligentGraphics/DiligentCore/issues/30 (Removed map type, map flag parameters from IBuffer::Unmap function) --- .../GraphicsEngineD3D12/include/BufferD3D12Impl.h | 8 +- .../include/DeviceContextD3D12Impl.h | 10 ++ .../GraphicsEngineD3D12/interface/BufferD3D12.h | 2 + .../GraphicsEngineD3D12/src/BufferD3D12Impl.cpp | 121 --------------------- .../src/DeviceContextD3D12Impl.cpp | 121 +++++++++++++++++++++ 5 files changed, 134 insertions(+), 128 deletions(-) (limited to 'Graphics/GraphicsEngineD3D12') diff --git a/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.h index 60bb6907..6d187b53 100644 --- a/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.h @@ -60,9 +60,6 @@ public: virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override; - virtual void Map( IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags, PVoid &pMappedData )override; - virtual void Unmap( IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags )override; - #ifdef DEVELOPMENT void DvpVerifyDynamicAllocation(class DeviceContextD3D12Impl* pCtx)const; #endif @@ -92,12 +89,9 @@ private: void CreateCBV( D3D12_CPU_DESCRIPTOR_HANDLE CBVDescriptor ); DescriptorHeapAllocation m_CBVDescriptorAllocation; -#ifdef _DEBUG - std::vector< std::pair, STDAllocatorRawMem> > m_DbgMapType; -#endif - friend class DeviceContextD3D12Impl; // Array of dynamic allocations for every device context + // sizeof(D3D12DynamicAllocation) == 40 (x64) std::vector > m_DynamicData; }; diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h index 0af2b72a..8f36d9c0 100644 --- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h @@ -92,6 +92,10 @@ public: virtual void CopyBuffer(IBuffer *pSrcBuffer, Uint32 SrcOffset, IBuffer *pDstBuffer, Uint32 DstOffset, Uint32 Size)override final; + virtual void MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, Uint32 MapFlags, PVoid& pMappedData)override final; + + virtual void UnmapBuffer(IBuffer* pBuffer)override final; + virtual void UpdateTexture(ITexture* pTexture, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData)override final; virtual void CopyTexture(ITexture* pSrcTexture, @@ -255,6 +259,12 @@ private: }; }; std::unordered_map m_MappedTextures; + + struct MappedBufferInfo + { + MAP_TYPE MapType; + }; + std::unordered_map m_MappedBuffers; }; } diff --git a/Graphics/GraphicsEngineD3D12/interface/BufferD3D12.h b/Graphics/GraphicsEngineD3D12/interface/BufferD3D12.h index d4741e01..cd33e740 100644 --- a/Graphics/GraphicsEngineD3D12/interface/BufferD3D12.h +++ b/Graphics/GraphicsEngineD3D12/interface/BufferD3D12.h @@ -31,6 +31,8 @@ namespace Diligent { +class IDeviceContext; + // {3E9B15ED-A289-48DC-8214-C6E3E6177378} static constexpr INTERFACE_ID IID_BufferD3D12 = { 0x3e9b15ed, 0xa289, 0x48dc, { 0x82, 0x14, 0xc6, 0xe3, 0xe6, 0x17, 0x73, 0x78 } }; diff --git a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp index 82a94489..af521f11 100644 --- a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp @@ -48,14 +48,6 @@ BufferD3D12Impl :: BufferD3D12Impl(IReferenceCounters* pRefCounters, BuffDesc, false }, -#ifdef _DEBUG - m_DbgMapType - { - 1 + pRenderDeviceD3D12->GetNumDeferredContexts(), - std::make_pair(static_cast(-1), static_cast(-1)), - STD_ALLOCATOR_RAW_MEM(D3D12DynamicAllocation, GetRawAllocator(), "Allocator for vector>") - }, -#endif m_DynamicData { BuffDesc.Usage == USAGE_DYNAMIC ? (1 + pRenderDeviceD3D12->GetNumDeferredContexts()) : 0, @@ -276,9 +268,6 @@ BufferD3D12Impl :: BufferD3D12Impl(IReferenceCounters* pRefCounters, BufferDescFromD3D12Resource(BuffDesc, pd3d12Buffer), false }, -#ifdef _DEBUG - m_DbgMapType(1 + pRenderDeviceD3D12->GetNumDeferredContexts(), std::make_pair(static_cast(-1), static_cast(-1)), STD_ALLOCATOR_RAW_MEM(D3D12DynamicAllocation, GetRawAllocator(), "Allocator for vector>")), -#endif m_DynamicData { BuffDesc.Usage == USAGE_DYNAMIC ? (1 + pRenderDeviceD3D12->GetNumDeferredContexts()) : 0, @@ -305,116 +294,6 @@ BufferD3D12Impl :: ~BufferD3D12Impl() IMPLEMENT_QUERY_INTERFACE( BufferD3D12Impl, IID_BufferD3D12, TBufferBase ) -void BufferD3D12Impl :: Map(IDeviceContext* pContext, MAP_TYPE MapType, Uint32 MapFlags, PVoid &pMappedData) -{ - TBufferBase::Map( pContext, MapType, MapFlags, pMappedData ); - auto *pDeviceContextD3D12 = ValidatedCast(pContext); -#ifdef _DEBUG - if(pDeviceContextD3D12 != nullptr) - m_DbgMapType[pDeviceContextD3D12->GetContextId()] = std::make_pair(MapType, MapFlags); -#endif - if (MapType == MAP_READ ) - { - LOG_WARNING_MESSAGE_ONCE("Mapping CPU buffer for reading on D3D12 currently requires flushing context and idling GPU"); - pDeviceContextD3D12->Flush(); - auto *pDeviceD3D12 = ValidatedCast(GetDevice()); - pDeviceD3D12->IdleGPU(); - - VERIFY(m_Desc.Usage == USAGE_CPU_ACCESSIBLE, "Buffer must be created as USAGE_CPU_ACCESSIBLE to be mapped for reading"); - D3D12_RANGE MapRange; - MapRange.Begin = 0; - MapRange.End = m_Desc.uiSizeInBytes; - m_pd3d12Resource->Map(0, &MapRange, &pMappedData); - } - else if(MapType == MAP_WRITE) - { - if (m_Desc.Usage == USAGE_CPU_ACCESSIBLE) - { - VERIFY(m_pd3d12Resource != nullptr, "USAGE_CPU_ACCESSIBLE buffer mapped for writing must intialize D3D12 resource"); - if (MapFlags & MAP_FLAG_DISCARD) - { - - } - m_pd3d12Resource->Map(0, nullptr, &pMappedData); - } - else if (m_Desc.Usage == USAGE_DYNAMIC) - { - VERIFY( (MapFlags & (MAP_FLAG_DISCARD | MAP_FLAG_DO_NOT_SYNCHRONIZE)) != 0, "D3D12 buffer must be mapped for writing with MAP_FLAG_DISCARD or MAP_FLAG_DO_NOT_SYNCHRONIZE flag"); - - auto *pCtxD3D12 = ValidatedCast(pContext); - auto ContextId = pDeviceContextD3D12->GetContextId(); - if ((MapFlags & MAP_FLAG_DISCARD) != 0 || m_DynamicData[ContextId].CPUAddress == nullptr) - { - size_t Alignment = (m_Desc.BindFlags & BIND_UNIFORM_BUFFER) ? D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT : 16; - m_DynamicData[ContextId] = pCtxD3D12->AllocateDynamicSpace(m_Desc.uiSizeInBytes, Alignment); - } - else - { - VERIFY_EXPR(MapFlags & MAP_FLAG_DO_NOT_SYNCHRONIZE); - // Reuse previously mapped region - } - pMappedData = m_DynamicData[ContextId].CPUAddress; - } - else - { - LOG_ERROR("Only USAGE_DYNAMIC and USAGE_CPU_ACCESSIBLE D3D12 buffers can be mapped for writing"); - } - } - else if(MapType == MAP_READ_WRITE) - { - LOG_ERROR("MAP_READ_WRITE is not supported on D3D12"); - } - else - { - LOG_ERROR("Only MAP_WRITE_DISCARD and MAP_READ are currently implemented in D3D12"); - } -} - -void BufferD3D12Impl::Unmap( IDeviceContext* pContext, MAP_TYPE MapType, Uint32 MapFlags ) -{ - TBufferBase::Unmap( pContext, MapType, MapFlags ); - auto *pDeviceContextD3D12 = ValidatedCast(pContext); - Uint32 CtxId = pDeviceContextD3D12 != nullptr ? pDeviceContextD3D12->GetContextId() : static_cast(-1); -#ifdef _DEBUG - if (pDeviceContextD3D12 != nullptr) - { - VERIFY(m_DbgMapType[CtxId].first == MapType, "Map type does not match the type provided to Map()"); - VERIFY(m_DbgMapType[CtxId].second == MapFlags, "Map flags do not match the flags provided to Map()"); - } -#endif - - if (MapType == MAP_READ ) - { - D3D12_RANGE MapRange; - // It is valid to specify the CPU didn't write any data by passing a range where End is less than or equal to Begin. - MapRange.Begin = 1; - MapRange.End = 0; - m_pd3d12Resource->Unmap(0, &MapRange); - } - else if(MapType == MAP_WRITE) - { - if (m_Desc.Usage == USAGE_CPU_ACCESSIBLE) - { - VERIFY(m_pd3d12Resource != nullptr, "USAGE_CPU_ACCESSIBLE buffer mapped for writing must intialize D3D12 resource"); - m_pd3d12Resource->Unmap(0, nullptr); - } - else if (m_Desc.Usage == USAGE_DYNAMIC) - { - VERIFY(MapFlags & (MAP_FLAG_DISCARD | MAP_FLAG_DO_NOT_SYNCHRONIZE), "D3D12 buffer must be mapped for writing with MAP_FLAG_DISCARD or MAP_FLAG_DO_NOT_SYNCHRONIZE flag"); - // Copy data into the resource - if (m_pd3d12Resource) - { - pDeviceContextD3D12->UpdateBufferRegion(this, m_DynamicData[CtxId], 0, m_Desc.uiSizeInBytes); - } - } - } - -#ifdef _DEBUG - if(pDeviceContextD3D12 != nullptr) - m_DbgMapType[CtxId] = std::make_pair(static_cast(-1), static_cast(-1)); -#endif -} - void BufferD3D12Impl::CreateViewInternal( const BufferViewDesc& OrigViewDesc, IBufferView** ppView, bool bIsDefaultView ) { VERIFY( ppView != nullptr, "Null pointer provided" ); diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 629ed589..02b87b13 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -693,6 +693,16 @@ namespace Diligent void DeviceContextD3D12Impl::FinishFrame() { +#ifdef DEVELOPMENT + for(const auto& MappedBuffIt : m_MappedBuffers) + { + const auto& BuffDesc = MappedBuffIt.first->GetDesc(); + if (BuffDesc.Usage == USAGE_DYNAMIC) + { + LOG_WARNING_MESSAGE("Dynamic buffer '", BuffDesc.Name, "' is still mapped when finishing the frame. The contents of the buffer and mapped address will become invalid"); + } + } +#endif if (GetNumCommandsInCtx() != 0) { LOG_ERROR_MESSAGE(m_bIsDeferred ? @@ -937,6 +947,117 @@ namespace Diligent ++m_State.NumCommands; } + void DeviceContextD3D12Impl::MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, Uint32 MapFlags, PVoid& pMappedData) + { + TDeviceContextBase::MapBuffer(pBuffer, MapType, MapFlags, pMappedData); + auto* pBufferD3D12 = ValidatedCast(pBuffer); + const auto& BuffDesc = pBufferD3D12->GetDesc(); + auto* pd3d12Resource = pBufferD3D12->m_pd3d12Resource.p; + +#ifdef DEVELOPMENT + if (m_MappedBuffers.find(pBufferD3D12) != m_MappedBuffers.end()) + { + LOG_ERROR_MESSAGE("Buffer '", BuffDesc.Name, "' has already been mapped"); + } +#endif + + if (MapType == MAP_READ) + { + LOG_WARNING_MESSAGE_ONCE("Mapping CPU buffer for reading on D3D12 currently requires flushing context and idling GPU"); + Flush(); + m_pDevice.RawPtr()->IdleGPU(); + VERIFY(BuffDesc.Usage == USAGE_CPU_ACCESSIBLE, "Buffer must be created as USAGE_CPU_ACCESSIBLE to be mapped for reading"); + D3D12_RANGE MapRange; + MapRange.Begin = 0; + MapRange.End = BuffDesc.uiSizeInBytes; + pd3d12Resource->Map(0, &MapRange, &pMappedData); + } + else if(MapType == MAP_WRITE) + { + if (BuffDesc.Usage == USAGE_CPU_ACCESSIBLE) + { + VERIFY(pd3d12Resource != nullptr, "USAGE_CPU_ACCESSIBLE buffer mapped for writing must intialize D3D12 resource"); + if (MapFlags & MAP_FLAG_DISCARD) + { + + } + pd3d12Resource->Map(0, nullptr, &pMappedData); + } + else if (BuffDesc.Usage == USAGE_DYNAMIC) + { + VERIFY( (MapFlags & (MAP_FLAG_DISCARD | MAP_FLAG_DO_NOT_SYNCHRONIZE)) != 0, "D3D12 buffer must be mapped for writing with MAP_FLAG_DISCARD or MAP_FLAG_DO_NOT_SYNCHRONIZE flag"); + auto& DynamicData = pBufferD3D12->m_DynamicData[m_ContextId]; + if ((MapFlags & MAP_FLAG_DISCARD) != 0 || DynamicData.CPUAddress == nullptr) + { + size_t Alignment = (BuffDesc.BindFlags & BIND_UNIFORM_BUFFER) ? D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT : 16; + DynamicData = AllocateDynamicSpace(BuffDesc.uiSizeInBytes, Alignment); + } + else + { + VERIFY_EXPR(MapFlags & MAP_FLAG_DO_NOT_SYNCHRONIZE); + // Reuse previously mapped region + } + pMappedData = DynamicData.CPUAddress; + } + else + { + LOG_ERROR("Only USAGE_DYNAMIC and USAGE_CPU_ACCESSIBLE D3D12 buffers can be mapped for writing"); + } + } + else if(MapType == MAP_READ_WRITE) + { + LOG_ERROR("MAP_READ_WRITE is not supported in D3D12"); + } + else + { + LOG_ERROR("Only MAP_WRITE_DISCARD and MAP_READ are currently implemented in D3D12"); + } + m_MappedBuffers[pBufferD3D12] = MappedBufferInfo{MapType}; + } + + void DeviceContextD3D12Impl::UnmapBuffer(IBuffer* pBuffer) + { + TDeviceContextBase::UnmapBuffer(pBuffer); + auto* pBufferD3D12 = ValidatedCast(pBuffer); + auto MappedBufferIt = m_MappedBuffers.find(pBufferD3D12); + if (MappedBufferIt == m_MappedBuffers.end()) + { + LOG_ERROR_MESSAGE("Buffer '", pBufferD3D12->GetDesc().Name, "' has not been mapped."); + return; + } + const auto& MapInfo = MappedBufferIt->second; + const auto& BuffDesc = pBufferD3D12->GetDesc(); + auto* pd3d12Resource = pBufferD3D12->m_pd3d12Resource.p; + + auto MapType = MapInfo.MapType; + if (MapType == MAP_READ ) + { + D3D12_RANGE MapRange; + // It is valid to specify the CPU didn't write any data by passing a range where End is less than or equal to Begin. + MapRange.Begin = 1; + MapRange.End = 0; + pd3d12Resource->Unmap(0, &MapRange); + } + else if(MapType == MAP_WRITE) + { + if (BuffDesc.Usage == USAGE_CPU_ACCESSIBLE) + { + VERIFY(pd3d12Resource != nullptr, "USAGE_CPU_ACCESSIBLE buffer mapped for writing must intialize D3D12 resource"); + pd3d12Resource->Unmap(0, nullptr); + } + else if (BuffDesc.Usage == USAGE_DYNAMIC) + { + // Copy data into the resource + if (pd3d12Resource) + { + UpdateBufferRegion(pBufferD3D12, pBufferD3D12->m_DynamicData[m_ContextId], 0, BuffDesc.uiSizeInBytes); + } + } + } + + m_MappedBuffers.erase(MappedBufferIt); + } + void DeviceContextD3D12Impl::UpdateTexture(ITexture* pTexture, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData) { TDeviceContextBase::UpdateTexture( pTexture, MipLevel, Slice, DstBox, SubresData ); -- cgit v1.2.3