summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineOpenGL
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2019-12-18 08:19:10 +0000
committerassiduous <assiduous@diligentgraphics.com>2019-12-18 08:19:10 +0000
commit59eebd09f5980e42ae53b886b2c321605dc4e1b2 (patch)
tree6d8f3f619f15e48b1a8ba48d03456e0f6b424898 /Graphics/GraphicsEngineOpenGL
parentFixed Core API test crash on the server by dynamically loading vulkan entry p... (diff)
downloadDiligentCore-59eebd09f5980e42ae53b886b2c321605dc4e1b2.tar.gz
DiligentCore-59eebd09f5980e42ae53b886b2c321605dc4e1b2.zip
Implemented staging textures in OpenGL backend; enabled draw command reference in GL test
Diffstat (limited to 'Graphics/GraphicsEngineOpenGL')
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h1
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h11
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h4
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h8
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp26
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp129
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp6
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp6
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp6
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp6
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp6
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp72
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/TextureCubeArray_OGL.cpp6
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/TextureCube_OGL.cpp6
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);