diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2019-12-18 08:19:10 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2019-12-18 08:19:10 +0000 |
| commit | 59eebd09f5980e42ae53b886b2c321605dc4e1b2 (patch) | |
| tree | 6d8f3f619f15e48b1a8ba48d03456e0f6b424898 /Graphics/GraphicsEngineOpenGL | |
| parent | Fixed Core API test crash on the server by dynamically loading vulkan entry p... (diff) | |
| download | DiligentCore-59eebd09f5980e42ae53b886b2c321605dc4e1b2.tar.gz DiligentCore-59eebd09f5980e42ae53b886b2c321605dc4e1b2.zip | |
Implemented staging textures in OpenGL backend; enabled draw command reference in GL test
Diffstat (limited to 'Graphics/GraphicsEngineOpenGL')
14 files changed, 263 insertions, 30 deletions
diff --git a/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h index 2747ff66..8c1e44f2 100644 --- a/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h @@ -67,6 +67,7 @@ public: void UpdateData(GLContextState& CtxState, Uint32 Offset, Uint32 Size, const PVoid pData); void CopyData(GLContextState& CtxState, BufferGLImpl& SrcBufferGL, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size); void Map(GLContextState& CtxState, MAP_TYPE MapType, Uint32 MapFlags, PVoid& pMappedData); + void MapRange(GLContextState& CtxState, MAP_TYPE MapType, Uint32 MapFlags, Uint32 Offset, Uint32 Length, PVoid& pMappedData); void Unmap(GLContextState& CtxState); void BufferMemoryBarrier(Uint32 RequiredBarriers, class GLContextState& GLContextState); diff --git a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h index 60525d6e..5ba8baaf 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h +++ b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h @@ -94,11 +94,11 @@ inline GLenum TypeToGLType(VALUE_TYPE Value) return GLType; } -inline GLenum UsageToGLUsage(USAGE Usage) +inline GLenum UsageToGLUsage(const BufferDesc& Desc) { // http://www.informit.com/articles/article.aspx?p=2033340&seqNum=2 // https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glBufferData.xml - switch (Usage) + switch (Desc.Usage) { // STATIC: The data store contents will be modified once and used many times. // STREAM: The data store contents will be modified once and used at MOST a few times. @@ -108,7 +108,12 @@ inline GLenum UsageToGLUsage(USAGE Usage) case USAGE_STATIC: return GL_STATIC_DRAW; case USAGE_DEFAULT: return GL_STATIC_DRAW; case USAGE_DYNAMIC: return GL_DYNAMIC_DRAW; - case USAGE_STAGING: return GL_DYNAMIC_READ; + case USAGE_STAGING: + if(Desc.CPUAccessFlags & CPU_ACCESS_READ) + return GL_STATIC_READ; + else + return GL_STATIC_COPY; + default: UNEXPECTED( "Unknow usage" ); return 0; // clang-format on } diff --git a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h index d7d94679..1f2bf173 100644 --- a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h @@ -64,8 +64,8 @@ public: virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override; /// Implementation of IRenderDevice::CreateBuffer() in OpenGL backend. - void CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, IBuffer** ppBufferLayout, bool bIsDeviceInternal); - virtual void CreateBuffer(const BufferDesc& BuffDesc, const BufferData* BuffData, IBuffer** ppBufferLayout) override final; + void CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, IBuffer** ppBuffer, bool bIsDeviceInternal); + virtual void CreateBuffer(const BufferDesc& BuffDesc, const BufferData* BuffData, IBuffer** ppBuffer) override final; /// Implementation of IRenderDevice::CreateShader() in OpenGL backend. void CreateShader(const ShaderCreateInfo& ShaderCreateInfo, IShader** ppShader, bool bIsDeviceInternal); diff --git a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h index 132ba912..6a98d417 100644 --- a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h +++ b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h @@ -110,6 +110,13 @@ public: const Box& DstBox, const TextureSubResData& SubresData) = 0; + static Uint32 GetPBODataOffset(const TextureDesc& TexDesc, Uint32 ArraySlice, Uint32 MipLevel); + + IBuffer* GetPBO() + { + return m_pPBO; + } + protected: virtual void CreateViewInternal(const struct TextureViewDesc& ViewDesc, class ITextureView** ppView, @@ -118,6 +125,7 @@ protected: void SetDefaultGLParameters(); GLObjectWrappers::GLTextureObj m_GlTexture; + RefCntAutoPtr<IBuffer> m_pPBO; // For staging textures const GLenum m_BindTarget; const GLenum m_GLTexFormat; //Uint32 m_uiMapTarget; diff --git a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp index e11f1765..9c1f58e2 100644 --- a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp @@ -54,8 +54,13 @@ static GLenum GetBufferBindTarget(const BufferDesc& Desc) #endif Target = GL_DRAW_INDIRECT_BUFFER; } - else if (Desc.Usage == USAGE_STAGING && Desc.CPUAccessFlags == CPU_ACCESS_WRITE) - Target = GL_PIXEL_UNPACK_BUFFER; + else if (Desc.Usage == USAGE_STAGING) + { + if (Desc.CPUAccessFlags == CPU_ACCESS_WRITE) + Target = GL_PIXEL_UNPACK_BUFFER; + else if (Desc.CPUAccessFlags == CPU_ACCESS_READ) + Target = GL_PIXEL_PACK_BUFFER; + } return Target; } @@ -77,7 +82,7 @@ BufferGLImpl::BufferGLImpl(IReferenceCounters* pRefCounters, }, m_GlBuffer {true }, // Create buffer immediately m_BindTarget {GetBufferBindTarget(BuffDesc) }, - m_GLUsageHint {UsageToGLUsage(BuffDesc.Usage)} + m_GLUsageHint {UsageToGLUsage(BuffDesc)} // clang-format on { if (BuffDesc.Usage == USAGE_STATIC && (pBuffData == nullptr || pBuffData->pData == nullptr)) @@ -189,7 +194,7 @@ BufferGLImpl::BufferGLImpl(IReferenceCounters* pRefCounters, // Attach to external buffer handle m_GlBuffer {true, GLObjectWrappers::GLBufferObjCreateReleaseHelper(GLHandle)}, m_BindTarget {GetBufferBindTarget(m_Desc) }, - m_GLUsageHint {UsageToGLUsage(BuffDesc.Usage)} + m_GLUsageHint {UsageToGLUsage(BuffDesc)} // clang-format on { } @@ -201,7 +206,7 @@ BufferGLImpl::~BufferGLImpl() IMPLEMENT_QUERY_INTERFACE(BufferGLImpl, IID_BufferGL, TBufferBase) -void BufferGLImpl ::UpdateData(GLContextState& CtxState, Uint32 Offset, Uint32 Size, const PVoid pData) +void BufferGLImpl::UpdateData(GLContextState& CtxState, Uint32 Offset, Uint32 Size, const PVoid pData) { BufferMemoryBarrier( GL_BUFFER_UPDATE_BARRIER_BIT, // Reads or writes to buffer objects via any OpenGL API functions that allow @@ -221,7 +226,7 @@ void BufferGLImpl ::UpdateData(GLContextState& CtxState, Uint32 Offset, Uint32 S } -void BufferGLImpl ::CopyData(GLContextState& CtxState, BufferGLImpl& SrcBufferGL, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size) +void BufferGLImpl::CopyData(GLContextState& CtxState, BufferGLImpl& SrcBufferGL, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size) { BufferMemoryBarrier( GL_BUFFER_UPDATE_BARRIER_BIT, // Reads or writes to buffer objects via any OpenGL API functions that allow @@ -247,7 +252,12 @@ void BufferGLImpl ::CopyData(GLContextState& CtxState, BufferGLImpl& SrcBufferGL CtxState.BindBuffer(GL_COPY_WRITE_BUFFER, GLObjectWrappers::GLBufferObj::Null(), ResetVAO); } -void BufferGLImpl ::Map(GLContextState& CtxState, MAP_TYPE MapType, Uint32 MapFlags, PVoid& pMappedData) +void BufferGLImpl::Map(GLContextState& CtxState, MAP_TYPE MapType, Uint32 MapFlags, PVoid& pMappedData) +{ + MapRange(CtxState, MapType, MapFlags, 0, m_Desc.uiSizeInBytes, pMappedData); +} + +void BufferGLImpl::MapRange(GLContextState& CtxState, MAP_TYPE MapType, Uint32 MapFlags, Uint32 Offset, Uint32 Length, PVoid& pMappedData) { BufferMemoryBarrier( GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT, // Access by the client to persistent mapped regions of buffer @@ -303,7 +313,7 @@ void BufferGLImpl ::Map(GLContextState& CtxState, MAP_TYPE MapType, Uint32 MapFl default: UNEXPECTED("Unknown map type"); } - pMappedData = glMapBufferRange(m_BindTarget, 0, m_Desc.uiSizeInBytes, Access); + pMappedData = glMapBufferRange(m_BindTarget, Offset, Length, Access); CHECK_GL_ERROR("glMapBufferRange() failed"); VERIFY(pMappedData, "Map failed"); } diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp index 916c30a8..807a0b0a 100644 --- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp @@ -1123,8 +1123,102 @@ void DeviceContextGLImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs) TDeviceContextBase::CopyTexture(CopyAttribs); auto* pSrcTexGL = ValidatedCast<TextureBaseGL>(CopyAttribs.pSrcTexture); auto* pDstTexGL = ValidatedCast<TextureBaseGL>(CopyAttribs.pDstTexture); - pDstTexGL->CopyData(this, pSrcTexGL, CopyAttribs.SrcMipLevel, CopyAttribs.SrcSlice, CopyAttribs.pSrcBox, - CopyAttribs.DstMipLevel, CopyAttribs.DstSlice, CopyAttribs.DstX, CopyAttribs.DstY, CopyAttribs.DstZ); + + const auto& SrcTexDesc = pSrcTexGL->GetDesc(); + const auto& DstTexDesc = pDstTexGL->GetDesc(); + + auto SrcMipLevelAttribs = GetMipLevelProperties(SrcTexDesc, CopyAttribs.SrcMipLevel); + + Box FullSrcBox; + FullSrcBox.MaxX = SrcMipLevelAttribs.LogicalWidth; + FullSrcBox.MaxY = SrcMipLevelAttribs.LogicalHeight; + FullSrcBox.MaxZ = SrcMipLevelAttribs.Depth; + auto* pSrcBox = CopyAttribs.pSrcBox != nullptr ? CopyAttribs.pSrcBox : &FullSrcBox; + + if (SrcTexDesc.Usage == USAGE_STAGING && DstTexDesc.Usage != USAGE_STAGING) + { + TextureSubResData SubresData; + SubresData.pData = nullptr; + SubresData.pSrcBuffer = pSrcTexGL->GetPBO(); + SubresData.SrcOffset = TextureBaseGL::GetPBODataOffset(SrcTexDesc, CopyAttribs.SrcSlice, CopyAttribs.SrcMipLevel); + SubresData.Stride = SrcMipLevelAttribs.RowSize; + SubresData.DepthStride = SrcMipLevelAttribs.DepthSliceSize; + + const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format); + SubresData.SrcOffset += + // For compressed-block formats, RowSize is the size of one compressed row. + // For non-compressed formats, BlockHeight is 1. + (pSrcBox->MinZ * SrcMipLevelAttribs.StorageHeight + pSrcBox->MinY) / SrcFmtAttribs.BlockHeight * SrcMipLevelAttribs.RowSize + + // For non-compressed formats, BlockWidth is 1. + (pSrcBox->MinX / SrcFmtAttribs.BlockWidth) * SrcFmtAttribs.GetElementSize(); + + Box DstBox; + DstBox.MinX = CopyAttribs.DstX; + DstBox.MinY = CopyAttribs.DstY; + DstBox.MinZ = CopyAttribs.DstZ; + DstBox.MaxX = DstBox.MinX + pSrcBox->MaxX - pSrcBox->MinX; + DstBox.MaxY = DstBox.MinY + pSrcBox->MaxY - pSrcBox->MinY; + DstBox.MaxZ = DstBox.MinZ + pSrcBox->MaxZ - pSrcBox->MinZ; + pDstTexGL->UpdateData(m_ContextState, CopyAttribs.DstMipLevel, CopyAttribs.DstSlice, DstBox, SubresData); + } + else if (SrcTexDesc.Usage != USAGE_STAGING && DstTexDesc.Usage == USAGE_STAGING) + { + auto CurrentNativeGLContext = m_ContextState.GetCurrentGLContext(); + auto& FBOCache = m_pDevice->GetFBOCache(CurrentNativeGLContext); + + { + TextureViewDesc SrcTexViewDesc; + SrcTexViewDesc.ViewType = TEXTURE_VIEW_RENDER_TARGET; + SrcTexViewDesc.MostDetailedMip = CopyAttribs.SrcMipLevel; + SrcTexViewDesc.FirstArraySlice = CopyAttribs.SrcSlice; + TextureViewGLImpl SrcTexView // + { + nullptr, // pRefCounters + m_pDevice, + SrcTexViewDesc, + pSrcTexGL, + false, // bCreateGLViewTex + false // bIsDefaultView + }; + + TextureViewGLImpl* pSrcViews[] = {&SrcTexView}; + const auto& SrcFBO = FBOCache.GetFBO(1, pSrcViews, nullptr, m_ContextState); + glBindFramebuffer(GL_READ_FRAMEBUFFER, SrcFBO); + DEV_CHECK_GL_ERROR("Failed to bind FBO as read framebuffer"); + } + + auto* pDstBuffer = ValidatedCast<BufferGLImpl>(pDstTexGL->GetPBO()); + VERIFY(pDstBuffer != nullptr, "Internal staging buffer must not be null"); + auto DstOffset = TextureBaseGL::GetPBODataOffset(DstTexDesc, CopyAttribs.DstSlice, CopyAttribs.DstMipLevel); + + auto DstMipLevelAttribs = GetMipLevelProperties(DstTexDesc, CopyAttribs.DstMipLevel); + + const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format); + DstOffset += + // For compressed-block formats, RowSize is the size of one compressed row. + // For non-compressed formats, BlockHeight is 1. + (CopyAttribs.DstZ * DstMipLevelAttribs.StorageHeight + CopyAttribs.DstY) / DstFmtAttribs.BlockHeight * DstMipLevelAttribs.RowSize + + // For non-compressed formats, BlockWidth is 1. + (CopyAttribs.DstX / DstFmtAttribs.BlockWidth) * DstFmtAttribs.GetElementSize(); + + m_ContextState.BindBuffer(GL_PIXEL_PACK_BUFFER, pDstBuffer->GetGLHandle(), true); + + const auto& TransferAttribs = GetNativePixelTransferAttribs(SrcTexDesc.Format); + glReadPixels(pSrcBox->MinX, pSrcBox->MinY, pSrcBox->MaxX - pSrcBox->MinX, pSrcBox->MaxY - pSrcBox->MinY, + TransferAttribs.PixelFormat, TransferAttribs.DataType, reinterpret_cast<void*>(static_cast<size_t>(DstOffset))); + DEV_CHECK_GL_ERROR("Failed to read pixel from framebuffer to pixel pack buffer"); + + m_ContextState.BindBuffer(GL_PIXEL_PACK_BUFFER, GLObjectWrappers::GLBufferObj::Null(), true); + // Restore original FBO + m_ContextState.InvalidateFBO(); + CommitRenderTargets(); + } + else + { + VERIFY(SrcTexDesc.Usage != USAGE_STAGING && DstTexDesc.Usage != USAGE_STAGING, "Copying between staging textures is not supported"); + pDstTexGL->CopyData(this, pSrcTexGL, CopyAttribs.SrcMipLevel, CopyAttribs.SrcSlice, CopyAttribs.pSrcBox, + CopyAttribs.DstMipLevel, CopyAttribs.DstSlice, CopyAttribs.DstX, CopyAttribs.DstY, CopyAttribs.DstZ); + } } void DeviceContextGLImpl::MapTextureSubresource(ITexture* pTexture, @@ -1136,15 +1230,40 @@ void DeviceContextGLImpl::MapTextureSubresource(ITexture* pTextu MappedTextureSubresource& MappedData) { TDeviceContextBase::MapTextureSubresource(pTexture, MipLevel, ArraySlice, MapType, MapFlags, pMapRegion, MappedData); - LOG_ERROR_MESSAGE("Texture mapping is not supported in OpenGL"); - MappedData = MappedTextureSubresource{}; + auto* pTexGL = ValidatedCast<TextureBaseGL>(pTexture); + const auto& TexDesc = pTexGL->GetDesc(); + if (TexDesc.Usage == USAGE_STAGING) + { + auto PBOOffset = TextureBaseGL::GetPBODataOffset(TexDesc, ArraySlice, MipLevel); + auto MipLevelAttribs = GetMipLevelProperties(TexDesc, MipLevel); + auto pPBO = ValidatedCast<BufferGLImpl>(pTexGL->GetPBO()); + pPBO->MapRange(m_ContextState, MapType, MapFlags, PBOOffset, MipLevelAttribs.MipSize, MappedData.pData); + + MappedData.Stride = MipLevelAttribs.RowSize; + MappedData.DepthStride = MipLevelAttribs.MipSize; + } + else + { + LOG_ERROR_MESSAGE("Only staging textures can be mapped in OpenGL"); + MappedData = MappedTextureSubresource{}; + } } void DeviceContextGLImpl::UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice) { TDeviceContextBase::UnmapTextureSubresource(pTexture, MipLevel, ArraySlice); - LOG_ERROR_MESSAGE("Texture mapping is not supported in OpenGL"); + auto* pTexGL = ValidatedCast<TextureBaseGL>(pTexture); + const auto& TexDesc = pTexGL->GetDesc(); + if (TexDesc.Usage == USAGE_STAGING) + { + auto pPBO = ValidatedCast<BufferGLImpl>(pTexGL->GetPBO()); + pPBO->Unmap(m_ContextState); + } + else + { + LOG_ERROR_MESSAGE("Only staging textures can be mapped in OpenGL"); + } } void DeviceContextGLImpl::GenerateMips(ITextureView* pTexView) diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp index 1dc43a13..14ada4dd 100644 --- a/Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp @@ -52,6 +52,12 @@ Texture1DArray_OGL::Texture1DArray_OGL(IReferenceCounters* pRefCounters, } // clang-format on { + if (TexDesc.Usage == USAGE_STAGING) + { + // We will use PBO initialized by TextureBaseGL + return; + } + GLState.BindTexture(-1, m_BindTarget, m_GlTexture); // levels format width height diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp index 95fb1123..5bff6605 100644 --- a/Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp @@ -52,6 +52,12 @@ Texture1D_OGL::Texture1D_OGL(IReferenceCounters* pRefCounters, } // clang-format on { + if (TexDesc.Usage == USAGE_STAGING) + { + // We will use PBO initialized by TextureBaseGL + return; + } + GLState.BindTexture(-1, m_BindTarget, m_GlTexture); // levels format width diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp index c333becc..6466749b 100644 --- a/Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp @@ -53,6 +53,12 @@ Texture2DArray_OGL::Texture2DArray_OGL(IReferenceCounters* pRefCounters, } // clang-format on { + if (TexDesc.Usage == USAGE_STAGING) + { + // We will use PBO initialized by TextureBaseGL + return; + } + GLState.BindTexture(-1, m_BindTarget, m_GlTexture); if (m_Desc.SampleCount > 1) diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp index 598a6280..5d82e317 100644 --- a/Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp @@ -53,6 +53,12 @@ Texture2D_OGL::Texture2D_OGL(IReferenceCounters* pRefCounters, } // clang-format on { + if (TexDesc.Usage == USAGE_STAGING) + { + // We will use PBO initialized by TextureBaseGL + return; + } + GLState.BindTexture(-1, m_BindTarget, m_GlTexture); if (m_Desc.SampleCount > 1) diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp index 319ab0f0..5164fcdc 100644 --- a/Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp @@ -53,6 +53,12 @@ Texture3D_OGL::Texture3D_OGL(IReferenceCounters* pRefCounters, } // clang-format on { + if (TexDesc.Usage == USAGE_STAGING) + { + // We will use PBO initialized by TextureBaseGL + return; + } + GLState.BindTexture(-1, m_BindTarget, m_GlTexture); // levels format width height depth diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp index 0aefa95f..740e73b7 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp @@ -35,6 +35,38 @@ namespace Diligent { + +Uint32 TextureBaseGL::GetPBODataOffset(const TextureDesc& TexDesc, Uint32 ArraySlice, Uint32 MipLevel) +{ + VERIFY_EXPR(ArraySlice < TexDesc.ArraySize && MipLevel < TexDesc.MipLevels || ArraySlice == TexDesc.ArraySize && MipLevel == 0); + + Uint32 Offset = 0; + if (ArraySlice > 0) + { + Uint32 ArraySliceSize = 0; + for (Uint32 mip = 0; mip < TexDesc.MipLevels; ++mip) + { + auto MipInfo = GetMipLevelProperties(TexDesc, mip); + ArraySliceSize += (MipInfo.MipSize + 3) & (~3); + } + + Offset = ArraySliceSize; + 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) + Offset *= TexDesc.ArraySize; + } + + for (Uint32 mip = 0; mip < MipLevel; ++mip) + { + auto MipInfo = GetMipLevelProperties(TexDesc, mip); + Offset += (MipInfo.MipSize + 3) & (~3); + } + + return Offset; +} + TextureBaseGL::TextureBaseGL(IReferenceCounters* pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, RenderDeviceGLImpl* pDeviceGL, @@ -51,7 +83,7 @@ TextureBaseGL::TextureBaseGL(IReferenceCounters* pRefCounters, TexDesc, bIsDeviceInternal }, - m_GlTexture {true }, // Create Texture immediately + m_GlTexture {TexDesc.Usage != USAGE_STAGING}, m_BindTarget {BindTarget }, m_GLTexFormat {TexFormatToGLInternalTexFormat(m_Desc.Format, m_Desc.BindFlags)} //m_uiMapTarget(0) @@ -60,6 +92,22 @@ TextureBaseGL::TextureBaseGL(IReferenceCounters* pRefCounters, VERIFY(m_GLTexFormat != 0, "Unsupported texture format"); if (TexDesc.Usage == USAGE_STATIC && pInitData == nullptr) LOG_ERROR_AND_THROW("Static Texture must be initialized with data at creation time"); + + if (TexDesc.Usage == USAGE_STAGING) + { + BufferDesc StagingBufferDesc; + std::string StagingBuffName = "Internal staging buffer of texture '"; + StagingBuffName += m_Desc.Name; + StagingBuffName += '\''; + StagingBufferDesc.Name = StagingBuffName.c_str(); + + StagingBufferDesc.uiSizeInBytes = GetPBODataOffset(m_Desc, m_Desc.ArraySize, 0); + StagingBufferDesc.Usage = USAGE_STAGING; + StagingBufferDesc.CPUAccessFlags = TexDesc.CPUAccessFlags; + + pDeviceGL->CreateBuffer(StagingBufferDesc, nullptr, &m_pPBO); + VERIFY_EXPR(m_pPBO); + } } static GLenum GetTextureInternalFormat(GLContextState& GLState, GLenum BindTarget, const GLObjectWrappers::GLTextureObj& GLTex, TEXTURE_FORMAT TexFmtFromDesc) @@ -389,7 +437,7 @@ void TextureBaseGL::UpdateData(GLContextState& CtxState, Uint32 MipLevel, Uint32 TextureMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT, CtxState); } -//void TextureBaseGL :: UpdateData(Uint32 Offset, Uint32 Size, const PVoid pData) +//void TextureBaseGL::UpdateData(Uint32 Offset, Uint32 Size, const PVoid pData) //{ // CTexture::UpdateData(Offset, Size, pData); // @@ -399,16 +447,16 @@ void TextureBaseGL::UpdateData(GLContextState& CtxState, Uint32 MipLevel, Uint32 //} // -void TextureBaseGL ::CopyData(DeviceContextGLImpl* pDeviceCtxGL, - TextureBaseGL* pSrcTextureGL, - Uint32 SrcMipLevel, - Uint32 SrcSlice, - const Box* pSrcBox, - Uint32 DstMipLevel, - Uint32 DstSlice, - Uint32 DstX, - Uint32 DstY, - Uint32 DstZ) +void TextureBaseGL::CopyData(DeviceContextGLImpl* pDeviceCtxGL, + TextureBaseGL* pSrcTextureGL, + Uint32 SrcMipLevel, + Uint32 SrcSlice, + const Box* pSrcBox, + Uint32 DstMipLevel, + Uint32 DstSlice, + Uint32 DstX, + Uint32 DstY, + Uint32 DstZ) { const auto& SrcTexDesc = pSrcTextureGL->GetDesc(); diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureCubeArray_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureCubeArray_OGL.cpp index 99c08e2c..9e32c6d8 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TextureCubeArray_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TextureCubeArray_OGL.cpp @@ -53,6 +53,12 @@ TextureCubeArray_OGL::TextureCubeArray_OGL(IReferenceCounters* pRefCounte } // clang-format on { + if (TexDesc.Usage == USAGE_STAGING) + { + // We will use PBO initialized by TextureBaseGL + return; + } + VERIFY(m_Desc.SampleCount == 1, "Multisampled texture cube arrays are not supported"); GLState.BindTexture(-1, m_BindTarget, m_GlTexture); diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureCube_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureCube_OGL.cpp index 0dfa6edc..82bf933d 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TextureCube_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TextureCube_OGL.cpp @@ -53,6 +53,12 @@ TextureCube_OGL::TextureCube_OGL(IReferenceCounters* pRefCounters, } // clang-format on { + if (TexDesc.Usage == USAGE_STAGING) + { + // We will use PBO initialized by TextureBaseGL + return; + } + VERIFY(m_Desc.SampleCount == 1, "Multisampled cubemap textures are not supported"); GLState.BindTexture(-1, m_BindTarget, m_GlTexture); |
