diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-09-01 19:02:31 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-09-01 19:02:31 +0000 |
| commit | 590c98bfe02f1758f3828b8e3cc813c0dbee654e (patch) | |
| tree | e5072aad7d2944a6b03aa1141b1a5ced90975959 /Graphics | |
| parent | Disabled notification messages in OpenGL (diff) | |
| download | DiligentCore-590c98bfe02f1758f3828b8e3cc813c0dbee654e.tar.gz DiligentCore-590c98bfe02f1758f3828b8e3cc813c0dbee654e.zip | |
Updated texture map/unmap intererface; implemented texture mapping in D3D12
Diffstat (limited to 'Graphics')
| -rw-r--r-- | Graphics/GraphicsEngine/include/TextureBase.h | 28 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/Texture.h | 28 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/src/Texture.cpp | 56 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.h | 11 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp | 16 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h | 57 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h | 10 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp | 149 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp | 47 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h | 10 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp | 15 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h | 10 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp | 14 |
13 files changed, 333 insertions, 118 deletions
diff --git a/Graphics/GraphicsEngine/include/TextureBase.h b/Graphics/GraphicsEngine/include/TextureBase.h index b20e3761..949d8d98 100644 --- a/Graphics/GraphicsEngine/include/TextureBase.h +++ b/Graphics/GraphicsEngine/include/TextureBase.h @@ -40,6 +40,12 @@ void ValidateUpdateDataParams( const TextureDesc &TexDesc, Uint32 MipLevel, Uint void VliadateCopyTextureDataParams( const TextureDesc& SrcTexDesc, Uint32 SrcMipLevel, Uint32 SrcSlice, const Box* pSrcBox, const TextureDesc& DstTexDesc, Uint32 DstMipLevel, Uint32 DstSlice, Uint32 DstX, Uint32 DstY, Uint32 DstZ ); +void ValidateMapTextureParams(const TextureDesc& TexDesc, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion); /// Base implementation of the ITexture interface @@ -146,10 +152,16 @@ public: Uint32 DstZ )override = 0; /// Base implementaiton of ITexture::Map() - virtual void Map( IDeviceContext* pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource& MappedData )override = 0; + virtual void Map(IDeviceContext* pContext, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData)override = 0; /// Base implementaiton of ITexture::Unmap() - virtual void Unmap( IDeviceContext* pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags )override = 0; + virtual void Unmap( IDeviceContext* pContext, Uint32 MipLevel, Uint32 ArraySlice)override = 0; /// Creates default texture views. @@ -483,12 +495,20 @@ void TextureBase<BaseInterface, TRenderDeviceImpl, TTextureViewImpl, TTexViewObj } template<class BaseInterface, class TRenderDeviceImpl,class TTextureViewImpl, class TTexViewObjAllocator> -void TextureBase<BaseInterface, TRenderDeviceImpl, TTextureViewImpl, TTexViewObjAllocator> :: Map( IDeviceContext* pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource &MappedData ) +void TextureBase<BaseInterface, TRenderDeviceImpl, TTextureViewImpl, TTexViewObjAllocator> :: Map( + IDeviceContext* pContext, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData) { + ValidateMapTextureParams(m_Desc, MipLevel, ArraySlice, MapType, MapFlags, pMapRegion); } template<class BaseInterface, class TRenderDeviceImpl,class TTextureViewImpl, class TTexViewObjAllocator> -void TextureBase<BaseInterface, TRenderDeviceImpl, TTextureViewImpl, TTexViewObjAllocator> :: Unmap( IDeviceContext* pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags ) +void TextureBase<BaseInterface, TRenderDeviceImpl, TTextureViewImpl, TTexViewObjAllocator> :: Unmap(IDeviceContext* pContext, Uint32 MipLevel, Uint32 ArraySlice) { } diff --git a/Graphics/GraphicsEngine/interface/Texture.h b/Graphics/GraphicsEngine/interface/Texture.h index 121a86c3..ba739d96 100644 --- a/Graphics/GraphicsEngine/interface/Texture.h +++ b/Graphics/GraphicsEngine/interface/Texture.h @@ -346,10 +346,30 @@ public: Uint32 DstY, Uint32 DstZ) = 0; - /// Map the texture - not implemented yet - virtual void Map( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource &MappedData ) = 0; - /// Unmap the textute - not implemented yet - virtual void Unmap( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags ) = 0; + /// Map the texture + + /// \param [in] pContext - Pointer to the device context interface to be used to perform the operation. + /// \param [in] MipLevel - Mip level to map. + /// \param [in] ArraySlice - Array slice to map. This parameter must be 0 for non-array textures. + /// \param [in] MapType - Type of the map operation. See Diligent::MAP_TYPE. + /// \param [in] MapFlags - Special map flags. See Diligent::MAP_FLAGS. + /// \param [in] pMapRegion - Texture region to map. If this parameter is null, the entire subresource is mapped. + /// \param [out] MappedData - Mapped texture region data + /// + /// \remarks This method is supported in D3D11, D3D12 and Vulkan backends. In D3D11 backend, only the entire + /// subresource can be mapped, so pMapRegion must either be null, or cover the entire subresource. + /// In D3D11 and Vulkan backends, dynamic textures are no different from non-dynamic textures, and mapping + /// with MAP_FLAG_DISCARD has exactly the same behavior + virtual void Map( IDeviceContext* pContext, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData ) = 0; + + /// Unmap the textute + virtual void Unmap(IDeviceContext *pContext, Uint32 MipLevel, Uint32 ArraySlice) = 0; /// Returns native texture handle specific to the underlying graphics API diff --git a/Graphics/GraphicsEngine/src/Texture.cpp b/Graphics/GraphicsEngine/src/Texture.cpp index 76741d48..3411ee20 100644 --- a/Graphics/GraphicsEngine/src/Texture.cpp +++ b/Graphics/GraphicsEngine/src/Texture.cpp @@ -248,39 +248,31 @@ void VliadateCopyTextureDataParams( const TextureDesc &SrcTexDesc, Uint32 SrcMip ValidateTextureRegion(DstTexDesc, DstMipLevel, DstSlice, DstBox); } +void ValidateMapTextureParams(const TextureDesc& TexDesc, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion) +{ + VERIFY_TEX_PARAMS( MipLevel < TexDesc.MipLevels, "Mip level (", MipLevel, ") is out of allowed range [0, ", TexDesc.MipLevels-1, "]" ); + if (TexDesc.Type == RESOURCE_DIM_TEX_1D_ARRAY || + TexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY || + TexDesc.Type == RESOURCE_DIM_TEX_CUBE || + TexDesc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY) + { + VERIFY_TEX_PARAMS( ArraySlice < TexDesc.ArraySize, "Array slice (", ArraySlice, ") is out of range [0,", TexDesc.ArraySize-1, "]" ); + } + else + { + VERIFY_TEX_PARAMS( ArraySlice == 0, "Array slice (", ArraySlice, ") must be 0 for non-array textures" ); + } -//void CTexture :: Map(MAP_TYPE MapType, Uint32 MapFlags, PVoid &pMappedData) -//{ - //switch(MapType) - //{ - // case MAP_READ: - // VERIFY( "Only buffers with usage USAGE_CPU_ACCESSIBLE can be read from" && m_Desc.Usage == USAGE_CPU_ACCESSIBLE); - // VERIFY( "Buffer being mapped for reading was not created with CPU_ACCESS_READ flag" && (m_Desc.CPUAccessFlags & CPU_ACCESS_READ)); - // break; - - // case MAP_WRITE: - // VERIFY( "Only buffers with usage USAGE_CPU_ACCESSIBLE can be written to" && m_Desc.Usage == USAGE_CPU_ACCESSIBLE ); - // VERIFY( "Buffer being mapped for writing was not created with CPU_ACCESS_WRITE flag" && (m_Desc.CPUAccessFlags & CPU_ACCESS_WRITE)); - // break; - - // case MAP_READ_WRITE: - // VERIFY( "Only buffers with usage USAGE_CPU_ACCESSIBLE can be read and written" && m_Desc.Usage == USAGE_CPU_ACCESSIBLE ); - // VERIFY( "Buffer being mapped for reading & writing was not created with CPU_ACCESS_WRITE flag" && (m_Desc.CPUAccessFlags & CPU_ACCESS_WRITE)); - // VERIFY( "Buffer being mapped for reading & writing was not created with CPU_ACCESS_READ flag" && (m_Desc.CPUAccessFlags & CPU_ACCESS_READ)); - // break; - - // case MAP_WRITE_DISCARD: - // VERIFY( "Only dynamic buffers can be mapped with write discard flag" && m_Desc.Usage == USAGE_DYNAMIC ); - // VERIFY( "Dynamic buffer must be created with CPU_ACCESS_WRITE flag" && (m_Desc.CPUAccessFlags & CPU_ACCESS_WRITE) ); - // break; - - // case MAP_WRITE_NO_OVERWRITE: - // VERIFY( "Only dynamic buffers can be mapped with write no overwrite flag" && m_Desc.Usage == USAGE_DYNAMIC ); - // VERIFY( "Dynamic buffer must be created with CPU_ACCESS_WRITE flag" && (m_Desc.CPUAccessFlags & CPU_ACCESS_WRITE) ); - // break; + if(pMapRegion != nullptr) + { + ValidateTextureRegion(TexDesc, MipLevel, ArraySlice, *pMapRegion); + } - // default: VERIFY("Unknown map type" && false); - //} -//} +} }
\ No newline at end of file diff --git a/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.h b/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.h index 1284c52e..662220a4 100644 --- a/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.h +++ b/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.h @@ -65,8 +65,15 @@ public: virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData )override final; //virtual void CopyData(CTexture *pSrcTexture, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size); - virtual void Map( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource &MappedData )override final; - virtual void Unmap( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags )override final; + virtual void Map( IDeviceContext* pContext, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData )override final; + + virtual void Unmap(IDeviceContext *pContext, Uint32 MipLevel, Uint32 ArraySlice)override final; virtual ID3D11Resource* GetD3D11Texture()override final{ return m_pd3d11Texture; } diff --git a/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp index 625b6668..e672cf86 100644 --- a/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp @@ -213,15 +213,22 @@ void TextureBaseD3D11 :: CopyData(IDeviceContext* pContext, pd3d11DeviceContext->CopySubresourceRegion(m_pd3d11Texture, DstSubRes, DstX, DstY, DstZ, pSrTextureBaseD3D11->GetD3D11Texture(), SrcSubRes, pD3D11SrcBox); } -void TextureBaseD3D11 :: Map( IDeviceContext* pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource& MappedData ) +void TextureBaseD3D11 :: Map(IDeviceContext* pContext, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData) { - TTextureBase::Map( pContext, Subresource, MapType, MapFlags, MappedData ); + TTextureBase::Map(pContext, MipLevel, ArraySlice, MapType, MapFlags, pMapRegion, MappedData); auto* pd3d11DeviceContext = static_cast<DeviceContextD3D11Impl*>(pContext)->GetD3D11DeviceContext(); D3D11_MAP d3d11MapType = static_cast<D3D11_MAP>(0); UINT d3d11MapFlags = 0; MapParamsToD3D11MapParams(MapType, MapFlags, d3d11MapType, d3d11MapFlags); + auto Subresource = D3D11CalcSubresource(MipLevel, ArraySlice, m_Desc.MipLevels); D3D11_MAPPED_SUBRESOURCE MappedTex; auto hr = pd3d11DeviceContext->Map(m_pd3d11Texture, Subresource, d3d11MapType, d3d11MapFlags, &MappedTex); if( FAILED(hr) ) @@ -237,11 +244,12 @@ void TextureBaseD3D11 :: Map( IDeviceContext* pContext, Uint32 Subresource, MAP_ } } -void TextureBaseD3D11::Unmap( IDeviceContext* pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags ) +void TextureBaseD3D11::Unmap( IDeviceContext* pContext, Uint32 MipLevel, Uint32 ArraySlice) { - TTextureBase::Unmap( pContext, Subresource, MapType, MapFlags ); + TTextureBase::Unmap( pContext, MipLevel, ArraySlice); auto* pd3d11DeviceContext = static_cast<DeviceContextD3D11Impl*>(pContext)->GetD3D11DeviceContext(); + auto Subresource = D3D11CalcSubresource(MipLevel, ArraySlice, m_Desc.MipLevels); pd3d11DeviceContext->Unmap(m_pd3d11Texture, Subresource); } diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h index ae006d32..bfde19bb 100644 --- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h @@ -26,15 +26,14 @@ /// \file /// Declaration of Diligent::DeviceContextD3D12Impl class +#include <unordered_map> + #include "DeviceContextD3D12.h" #include "DeviceContextBase.h" #include "GenerateMips.h" #include "BufferD3D12Impl.h" #include "TextureViewD3D12Impl.h" #include "PipelineStateD3D12Impl.h" -#ifdef _DEBUG -# define VERIFY_CONTEXT_BINDINGS -#endif namespace Diligent { @@ -115,7 +114,7 @@ public: Uint32 SrcOffset, Uint32 SrcStride, Uint32 SrcDepthStride, - class TextureD3D12Impl* pTextureD3D12, + class TextureD3D12Impl& TextureD3D12, Uint32 DstSubResIndex, const Box& DstBox); void CopyTextureRegion(ID3D12Resource* pd3d12Buffer, @@ -123,17 +122,29 @@ public: Uint32 SrcStride, Uint32 SrcDepthStride, Uint32 BufferSize, - class TextureD3D12Impl* pTextureD3D12, + class TextureD3D12Impl& TextureD3D12, Uint32 DstSubResIndex, const Box& DstBox); void UpdateTextureRegion(const void* pSrcData, Uint32 SrcStride, Uint32 SrcDepthStride, - class TextureD3D12Impl* pTextureD3D12, + class TextureD3D12Impl& TextureD3D12, Uint32 DstSubResIndex, const Box& DstBox); + void MapTexture( class TextureD3D12Impl& TextureD3D12, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box& MapRegion, + MappedTextureSubresource& MappedData ); + + void UnmapTexture( class TextureD3D12Impl& TextureD3D12, + Uint32 MipLevel, + Uint32 ArraySlice); + void GenerateMips(class TextureViewD3D12Impl *pTexView); struct DynamicAllocation AllocateDynamicSpace(size_t NumBytes, size_t Alignment); @@ -151,6 +162,20 @@ private: void CommitScissorRects(class GraphicsContext &GraphCtx, bool ScissorEnable); void Flush(bool RequestNewCmdCtx); + struct TextureUploadSpace + { + DynamicAllocation Allocation; + Uint32 AlignedOffset = 0; + Uint32 Stride = 0; + Uint32 DepthStride = 0; + Uint32 RowSize = 0; + Uint32 RowCount = 0; + Box Region; + }; + TextureUploadSpace AllocateTextureUploadSpace(TEXTURE_FORMAT TexFmt, + const Box& Region); + + friend class SwapChainD3D12Impl; inline class CommandContext* RequestCmdContext() { @@ -186,6 +211,26 @@ private: const Uint32 m_ContextId; std::vector<std::pair<Uint64, RefCntAutoPtr<IFence> > > m_PendingFences; + + struct TextureUploadAllocationKey + { + TextureD3D12Impl* const Texture; + UINT const Subresource; + + bool operator == (const TextureUploadAllocationKey& rhs)const + { + return Texture == rhs.Texture && + Subresource == rhs.Subresource; + } + struct Hasher + { + size_t operator()(const TextureUploadAllocationKey& Key)const + { + return ComputeHash(Key.Texture, Key.Subresource); + } + }; + }; + std::unordered_map<TextureUploadAllocationKey, TextureUploadSpace, TextureUploadAllocationKey::Hasher> m_TextureUploadAllocations; }; } diff --git a/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h index 95430ade..3a314a37 100644 --- a/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h @@ -63,8 +63,14 @@ public: virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )override final; //virtual void CopyData(CTexture *pSrcTexture, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size); - virtual void Map( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource &MappedData )override final; - virtual void Unmap( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags )override final; + virtual void Map( IDeviceContext* pContext, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData )override final; + virtual void Unmap( IDeviceContext *pContext, Uint32 MipLevel, Uint32 ArraySlice)override final; virtual ID3D12Resource* GetD3D12Texture(){ return GetD3D12Resource(); } diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index ab1ae905..52898a5d 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -759,17 +759,17 @@ namespace Diligent Uint32 SrcStride, Uint32 SrcDepthStride, Uint32 BufferSize, - class TextureD3D12Impl* pTextureD3D12, + class TextureD3D12Impl& TextureD3D12, Uint32 DstSubResIndex, const Box& DstBox) { - const auto& TexDesc = pTextureD3D12->GetDesc(); + const auto& TexDesc = TextureD3D12.GetDesc(); auto *pCmdCtx = RequestCmdContext(); auto *pCmdList = pCmdCtx->GetCommandList(); - auto TextureState = pTextureD3D12->GetState(); + auto TextureState = TextureD3D12.GetState(); D3D12_RESOURCE_BARRIER BarrierDesc; BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - BarrierDesc.Transition.pResource = pTextureD3D12->GetD3D12Resource(); + BarrierDesc.Transition.pResource = TextureD3D12.GetD3D12Resource(); BarrierDesc.Transition.Subresource = DstSubResIndex; BarrierDesc.Transition.StateBefore = TextureState; BarrierDesc.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST; @@ -780,7 +780,7 @@ namespace Diligent D3D12_TEXTURE_COPY_LOCATION DstLocation; DstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - DstLocation.pResource = pTextureD3D12->GetD3D12Resource(); + DstLocation.pResource = TextureD3D12.GetD3D12Resource(); DstLocation.SubresourceIndex = static_cast<UINT>(DstSubResIndex); D3D12_TEXTURE_COPY_LOCATION SrcLocation; @@ -830,7 +830,7 @@ namespace Diligent Uint32 SrcOffset, Uint32 SrcStride, Uint32 SrcDepthStride, - class TextureD3D12Impl* pTextureD3D12, + class TextureD3D12Impl& TextureD3D12, Uint32 DstSubResIndex, const Box& DstBox) { @@ -841,71 +841,136 @@ namespace Diligent RequestCmdContext()->TransitionResource(pBufferD3D12, D3D12_RESOURCE_STATE_GENERIC_READ, true); size_t DataStartByteOffset = 0; auto* pd3d12Buffer = pBufferD3D12->GetD3D12Buffer(DataStartByteOffset, m_ContextId); - CopyTextureRegion(pd3d12Buffer, static_cast<Uint32>(DataStartByteOffset) + SrcOffset, SrcStride, SrcDepthStride, pBufferD3D12->GetDesc().uiSizeInBytes, pTextureD3D12, DstSubResIndex, DstBox); + CopyTextureRegion(pd3d12Buffer, static_cast<Uint32>(DataStartByteOffset) + SrcOffset, SrcStride, SrcDepthStride, pBufferD3D12->GetDesc().uiSizeInBytes, TextureD3D12, DstSubResIndex, DstBox); } - void DeviceContextD3D12Impl::UpdateTextureRegion(const void* pSrcData, - Uint32 SrcStride, - Uint32 SrcDepthStride, - TextureD3D12Impl* pTextureD3D12, - Uint32 DstSubResIndex, - const Box& DstBox) + DeviceContextD3D12Impl::TextureUploadSpace DeviceContextD3D12Impl::AllocateTextureUploadSpace(TEXTURE_FORMAT TexFmt, + const Box& Region) { - const auto& TexDesc = pTextureD3D12->GetDesc(); - const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format); - VERIFY_EXPR(DstBox.MaxX > DstBox.MinX && DstBox.MaxY > DstBox.MinY && DstBox.MaxZ > DstBox.MinZ); - auto UpdateRegionWidth = DstBox.MaxX - DstBox.MinX; - auto UpdateRegionHeight = DstBox.MaxY - DstBox.MinY; - auto UpdateRegionDepth = DstBox.MaxZ - DstBox.MinZ; - Uint32 RowSize = 0; - Uint32 RowCount = 0; + TextureUploadSpace UploadSpace; + VERIFY_EXPR(Region.MaxX > Region.MinX && Region.MaxY > Region.MinY && Region.MaxZ > Region.MinZ); + auto UpdateRegionWidth = Region.MaxX - Region.MinX; + auto UpdateRegionHeight = Region.MaxY - Region.MinY; + auto UpdateRegionDepth = Region.MaxZ - Region.MinZ; + const auto& FmtAttribs = GetTextureFormatAttribs(TexFmt); if(FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED) { // Box must be aligned by the calling function VERIFY_EXPR((UpdateRegionWidth % FmtAttribs.BlockWidth) == 0); VERIFY_EXPR((UpdateRegionHeight % FmtAttribs.BlockHeight) == 0); - RowSize = UpdateRegionWidth / Uint32{FmtAttribs.BlockWidth} * Uint32{FmtAttribs.ComponentSize}; - RowCount = UpdateRegionHeight / FmtAttribs.BlockHeight; + UploadSpace.RowSize = UpdateRegionWidth / Uint32{FmtAttribs.BlockWidth} * Uint32{FmtAttribs.ComponentSize}; + UploadSpace.RowCount = UpdateRegionHeight / FmtAttribs.BlockHeight; } else { - RowSize = UpdateRegionWidth * Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.NumComponents}; - RowCount = UpdateRegionHeight; + UploadSpace.RowSize = UpdateRegionWidth * Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.NumComponents}; + UploadSpace.RowCount = UpdateRegionHeight; } + // RowPitch must be a multiple of 256 (aka. D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) + UploadSpace.Stride = (UploadSpace.RowSize + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT-1) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT-1); + UploadSpace.DepthStride = UploadSpace.RowCount * UploadSpace.Stride; + const auto MemorySize = UpdateRegionDepth * UploadSpace.DepthStride; + UploadSpace.Allocation = AllocateDynamicSpace(MemorySize, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); + UploadSpace.AlignedOffset = (UploadSpace.Allocation.Offset + (D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT-1)) & ~(D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT-1); + UploadSpace.Region = Region; + + return UploadSpace; + } + + void DeviceContextD3D12Impl::UpdateTextureRegion(const void* pSrcData, + Uint32 SrcStride, + Uint32 SrcDepthStride, + TextureD3D12Impl& TextureD3D12, + Uint32 DstSubResIndex, + const Box& DstBox) + { + const auto& TexDesc = TextureD3D12.GetDesc(); + auto UploadSpace = AllocateTextureUploadSpace(TexDesc.Format, DstBox); + auto UpdateRegionDepth = DstBox.MaxZ-DstBox.MinZ; #ifdef _DEBUG { - VERIFY(SrcStride >= RowSize, "Source data stride (", SrcStride, ") is below the image row size (", RowSize, ")"); - const Uint32 PlaneSize = SrcStride * RowCount; + VERIFY(SrcStride >= UploadSpace.RowSize, "Source data stride (", SrcStride, ") is below the image row size (", UploadSpace.RowSize, ")"); + const Uint32 PlaneSize = SrcStride * UploadSpace.RowCount; VERIFY(UpdateRegionDepth == 1 || SrcDepthStride >= PlaneSize, "Source data depth stride (", SrcDepthStride, ") is below the image plane size (", PlaneSize, ")"); } #endif - // RowPitch must be a multiple of 256 (aka. D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) - const auto AlignedStride = (RowSize + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT-1) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT-1); - const auto AlignedDepthStride = RowCount * AlignedStride; - const auto MemorySize = UpdateRegionDepth * AlignedDepthStride; - const auto UploadSpace = AllocateDynamicSpace(MemorySize, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); - const auto AlignedOffset = (UploadSpace.Offset + (D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT-1)) & ~(D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT-1); + const auto AlignedOffset = UploadSpace.AlignedOffset; - for(Uint32 slice = 0; slice < UpdateRegionDepth; ++slice) + for(Uint32 DepthSlice = 0; DepthSlice < UpdateRegionDepth; ++DepthSlice) { - for(Uint32 row = 0; row < RowCount; ++row) + for(Uint32 row = 0; row < UploadSpace.RowCount; ++row) { const auto* pSrcPtr = reinterpret_cast<const Uint8*>(pSrcData) + row * SrcStride - + slice * SrcDepthStride; + + DepthSlice * SrcDepthStride; auto* pDstPtr = - reinterpret_cast<Uint8*>(UploadSpace.CPUAddress) - + (AlignedOffset - UploadSpace.Offset) - + row * AlignedStride - + slice * AlignedDepthStride; + reinterpret_cast<Uint8*>(UploadSpace.Allocation.CPUAddress) + + (AlignedOffset - UploadSpace.Allocation.Offset) + + row * UploadSpace.Stride + + DepthSlice * UploadSpace.DepthStride; - memcpy(pDstPtr, pSrcPtr, RowSize); + memcpy(pDstPtr, pSrcPtr, UploadSpace.RowSize); } } - CopyTextureRegion(UploadSpace.pBuffer, static_cast<Uint32>(AlignedOffset), AlignedStride, AlignedDepthStride, MemorySize, pTextureD3D12, DstSubResIndex, DstBox); + CopyTextureRegion(UploadSpace.Allocation.pBuffer, + static_cast<Uint32>(AlignedOffset), + UploadSpace.Stride, + UploadSpace.DepthStride, + static_cast<Uint32>(UploadSpace.Allocation.Size - (AlignedOffset - UploadSpace.Allocation.Offset)), + TextureD3D12, + DstSubResIndex, + DstBox); + } + + void DeviceContextD3D12Impl::MapTexture( TextureD3D12Impl& TextureD3D12, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box& MapRegion, + MappedTextureSubresource& MappedData ) + { + const auto& TexDesc = TextureD3D12.GetDesc(); + auto UploadSpace = AllocateTextureUploadSpace(TexDesc.Format, MapRegion); + const auto AlignedOffset = (UploadSpace.Allocation.Offset + (D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT-1)) & ~(D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT-1); + MappedData.pData = reinterpret_cast<Uint8*>(UploadSpace.Allocation.CPUAddress) + (UploadSpace.AlignedOffset - UploadSpace.Allocation.Offset); + MappedData.Stride = UploadSpace.Stride; + MappedData.DepthStride = UploadSpace.DepthStride; + + auto Subres = D3D12CalcSubresource(MipLevel, ArraySlice, 0, TexDesc.MipLevels, TexDesc.ArraySize); + auto it = m_TextureUploadAllocations.emplace(TextureUploadAllocationKey{&TextureD3D12, Subres}, std::move(UploadSpace)); + if(!it.second) + LOG_ERROR_MESSAGE("Mip level ", MipLevel, ", slice ", ArraySlice, " of texture '", TexDesc.Name, "' has already been mapped"); } + void DeviceContextD3D12Impl::UnmapTexture( TextureD3D12Impl& TextureD3D12, + Uint32 MipLevel, + Uint32 ArraySlice) + { + const auto& TexDesc = TextureD3D12.GetDesc(); + auto Subres = D3D12CalcSubresource(MipLevel, ArraySlice, 0, TexDesc.MipLevels, TexDesc.ArraySize); + auto UploadSpaceIt = m_TextureUploadAllocations.find(TextureUploadAllocationKey{&TextureD3D12, Subres}); + if(UploadSpaceIt != m_TextureUploadAllocations.end()) + { + auto& UploadSpace = UploadSpaceIt->second; + CopyTextureRegion(UploadSpace.Allocation.pBuffer, + UploadSpace.AlignedOffset, + UploadSpace.Stride, + UploadSpace.DepthStride, + static_cast<Uint32>(UploadSpace.Allocation.Size - (UploadSpace.AlignedOffset - UploadSpace.Allocation.Offset)), + TextureD3D12, + Subres, + UploadSpace.Region); + m_TextureUploadAllocations.erase(UploadSpaceIt); + } + else + { + LOG_ERROR_MESSAGE("Failed to unmap mip level ", MipLevel, ", slice ", ArraySlice, " of texture '", TexDesc.Name, "'. The texture has either been unmapped already or has not been mapped"); + } + } + + void DeviceContextD3D12Impl::GenerateMips(TextureViewD3D12Impl* pTexView) { auto *pCtx = RequestCmdContext(); diff --git a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp index 77d959a6..21eeeca4 100644 --- a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp @@ -438,9 +438,9 @@ void TextureD3D12Impl::UpdateData( IDeviceContext* pContext, auto *pCtxD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pContext); auto DstSubResIndex = D3D12CalcSubresource(MipLevel, Slice, 0, m_Desc.MipLevels, m_Desc.ArraySize); if (SubresData.pSrcBuffer == nullptr) - pCtxD3D12->UpdateTextureRegion(SubresData.pData, SubresData.Stride, SubresData.DepthStride, this, DstSubResIndex, *pBox); + pCtxD3D12->UpdateTextureRegion(SubresData.pData, SubresData.Stride, SubresData.DepthStride, *this, DstSubResIndex, *pBox); else - pCtxD3D12->CopyTextureRegion(SubresData.pSrcBuffer, 0, SubresData.Stride, SubresData.DepthStride, this, DstSubResIndex, *pBox); + pCtxD3D12->CopyTextureRegion(SubresData.pSrcBuffer, 0, SubresData.Stride, SubresData.DepthStride, *this, DstSubResIndex, *pBox); } void TextureD3D12Impl :: CopyData(IDeviceContext* pContext, @@ -477,19 +477,46 @@ void TextureD3D12Impl :: CopyData(IDeviceContext* pContext, pCtxD3D12->CopyTextureRegion(pSrcTexD3D12, SrcSubResIndex, pD3D12SrcBox, this, DstSubResIndex, DstX, DstY, DstZ); } -void TextureD3D12Impl :: Map(IDeviceContext* pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource &MappedData) +void TextureD3D12Impl :: Map( IDeviceContext* pContext, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData ) { - TTextureBase::Map( pContext, Subresource, MapType, MapFlags, MappedData ); - UNSUPPORTED("TextureD3D12Impl::Map() is not implemented"); + TTextureBase::Map(pContext, MipLevel, ArraySlice, MapType, MapFlags, pMapRegion, MappedData); - //static char TmpDummyBuffer[1024*1024*64]; - MappedData.pData = nullptr;//TmpDummyBuffer; + auto* pDeviceContextD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pContext); + MappedData = MappedTextureSubresource{}; + + Box FullExtentBox; + if (pMapRegion == nullptr) + { + FullExtentBox.MaxX = std::max(m_Desc.Width >> MipLevel, 1u); + FullExtentBox.MaxY = std::max(m_Desc.Height >> MipLevel, 1u); + if (m_Desc.Type == RESOURCE_DIM_TEX_3D) + FullExtentBox.MaxZ = std::max(m_Desc.Depth >> MipLevel, 1u); + pMapRegion = &FullExtentBox; + } + + if(MapType == MAP_WRITE) + { + if( (MapFlags & (MAP_FLAG_DISCARD | MAP_FLAG_DO_NOT_SYNCHRONIZE)) != 0 ) + LOG_WARNING_MESSAGE_ONCE("Mapping textures with flags MAP_FLAG_DISCARD or MAP_FLAG_DO_NOT_SYNCHRONIZE has no effect in D3D12 backend"); + pDeviceContextD3D12->MapTexture(*this, MipLevel, ArraySlice, MapType, MapFlags, *pMapRegion, MappedData); + } + else + { + LOG_ERROR("Textures can currently only be mapped for writing in D3D12 backend"); + } } -void TextureD3D12Impl::Unmap( IDeviceContext* pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags ) +void TextureD3D12Impl::Unmap(IDeviceContext* pContext, Uint32 MipLevel, Uint32 ArraySlice) { - TTextureBase::Unmap( pContext, Subresource, MapType, MapFlags ); - UNSUPPORTED("TextureD3D12Impl::Unmap() is not implemented"); + TTextureBase::Unmap(pContext, MipLevel, ArraySlice); + auto* pDeviceContextD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pContext); + pDeviceContextD3D12->UnmapTexture(*this, MipLevel, ArraySlice); } diff --git a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h index 1af707a0..4f80aa05 100644 --- a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h +++ b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h @@ -67,8 +67,14 @@ public: virtual void UpdateData( class GLContextState &CtxState, IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData ); //virtual void CopyData(CTexture *pSrcTexture, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size); - virtual void Map( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource &MappedData )override; - virtual void Unmap( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags )override; + virtual void Map(IDeviceContext* pContext, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData)override; + virtual void Unmap(IDeviceContext *pContext, Uint32 MipLevel, Uint32 ArraySlice)override; const GLObjectWrappers::GLTextureObj& GetGLHandle()const{ return m_GlTexture; } virtual GLenum GetBindTarget()const override final{return m_BindTarget;} diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp index f5e6034b..a0f0820b 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp @@ -494,15 +494,22 @@ void TextureBaseGL :: CopyData(IDeviceContext *pContext, } -void TextureBaseGL :: Map(IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource &MappedData) +void TextureBaseGL :: Map(IDeviceContext* pContext, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData) { - TTextureBase::Map( pContext, Subresource, MapType, MapFlags, MappedData ); + TTextureBase::Map(pContext, MipLevel, ArraySlice, MapType, MapFlags, pMapRegion, MappedData); LOG_ERROR_MESSAGE("Texture mapping is not supported in OpenGL"); + MappedData = MappedTextureSubresource{}; } -void TextureBaseGL::Unmap( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags ) +void TextureBaseGL::Unmap(IDeviceContext* pContext, Uint32 MipLevel, Uint32 ArraySlice) { - TTextureBase::Unmap(pContext, Subresource, MapType, MapFlags); + TTextureBase::Unmap(pContext, MipLevel, ArraySlice); LOG_ERROR_MESSAGE("Texture mapping is not supported in OpenGL"); } diff --git a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h index eee1a938..c4fdcdc5 100644 --- a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h @@ -65,8 +65,14 @@ public: virtual void UpdateData( IDeviceContext* pContext, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData )override; //virtual void CopyData(CTexture* pSrcTexture, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size); - virtual void Map( IDeviceContext* pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource& MappedData )override; - virtual void Unmap( IDeviceContext* pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags )override; + virtual void Map(IDeviceContext* pContext, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData)override; + virtual void Unmap(IDeviceContext* pContext, Uint32 MipLevel, Uint32 ArraySlice)override; virtual VkImage GetVkImage()const override final{ return m_VulkanImage; } virtual void* GetNativeHandle()override final diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp index 796ddf56..5cff0d89 100644 --- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp @@ -555,15 +555,21 @@ void TextureVkImpl :: CopyData(IDeviceContext* pContext, pCtxVk->CopyTextureRegion(pSrcTexVk, this, CopyRegion); } -void TextureVkImpl :: Map(IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource &MappedData) +void TextureVkImpl :: Map(IDeviceContext* pContext, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData) { - TTextureBase::Map( pContext, Subresource, MapType, MapFlags, MappedData ); + TTextureBase::Map(pContext, MipLevel, ArraySlice, MapType, MapFlags, pMapRegion, MappedData); UNEXPECTED("TextureVkImpl::Map() is not implemented"); } -void TextureVkImpl::Unmap( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags ) +void TextureVkImpl::Unmap(IDeviceContext *pContext, Uint32 MipLevel, Uint32 ArraySlice) { - TTextureBase::Unmap( pContext, Subresource, MapType, MapFlags ); + TTextureBase::Unmap(pContext, MipLevel, ArraySlice); UNEXPECTED("TextureVkImpl::Unmap() is not implemented"); } |
