summaryrefslogtreecommitdiffstats
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
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
-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
-rw-r--r--UnitTests/DiligentCoreAPITest/CMakeLists.txt14
-rw-r--r--UnitTests/DiligentCoreAPITest/include/GL/TestingEnvironmentGL.h16
-rw-r--r--UnitTests/DiligentCoreAPITest/include/GL/TestingSwapChainGL.h6
-rw-r--r--UnitTests/DiligentCoreAPITest/src/GL/DrawCommandRefenceGL.cpp78
-rw-r--r--UnitTests/DiligentCoreAPITest/src/GL/TestingEnvironmentGL.cpp93
-rw-r--r--UnitTests/DiligentCoreAPITest/src/GL/TestingSwapChainGL.cpp100
-rw-r--r--UnitTests/DiligentCoreAPITest/src/TestingEnvironment.cpp3
-rw-r--r--UnitTests/DiligentCoreAPITest/src/main.cpp1
22 files changed, 567 insertions, 37 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);
diff --git a/UnitTests/DiligentCoreAPITest/CMakeLists.txt b/UnitTests/DiligentCoreAPITest/CMakeLists.txt
index 9232aefd..f0c2673c 100644
--- a/UnitTests/DiligentCoreAPITest/CMakeLists.txt
+++ b/UnitTests/DiligentCoreAPITest/CMakeLists.txt
@@ -88,10 +88,18 @@ endif()
if(GL_SUPPORTED OR GLES_SUPPORTED)
target_link_libraries(DiligentCoreAPITest PRIVATE Diligent-HLSL2GLSLConverterLib)
-endif()
-if(GL_SUPPORTED)
- target_link_libraries(DiligentCoreAPITest PRIVATE glew-static)
+ if(PLATFORM_WIN32)
+ target_link_libraries(DiligentCoreAPITest PRIVATE glew-static opengl32.lib)
+ elseif(PLATFORM_LINUX)
+ target_link_libraries(DiligentCoreAPITest PRIVATE glew-static)
+ elseif(PLATFORM_MACOS)
+ find_package(OpenGL REQUIRED)
+ target_link_libraries(DiligentCoreAPITest PRIVATE glew-static ${OPENGL_LIBRARY})
+ else()
+ message(FATAL_ERROR "Unsupported platform")
+ endif()
+
endif()
if(VULKAN_SUPPORTED)
diff --git a/UnitTests/DiligentCoreAPITest/include/GL/TestingEnvironmentGL.h b/UnitTests/DiligentCoreAPITest/include/GL/TestingEnvironmentGL.h
index 981d6a1f..306e1d8f 100644
--- a/UnitTests/DiligentCoreAPITest/include/GL/TestingEnvironmentGL.h
+++ b/UnitTests/DiligentCoreAPITest/include/GL/TestingEnvironmentGL.h
@@ -23,6 +23,15 @@
#pragma once
+#ifndef GLEW_STATIC
+# define GLEW_STATIC // Must be defined to use static version of glew
+#endif
+#ifndef GLEW_NO_GLU
+# define GLEW_NO_GLU
+#endif
+
+#include "GL/glew.h"
+
#include "TestingEnvironment.h"
namespace Diligent
@@ -35,10 +44,17 @@ class TestingEnvironmentGL final : public TestingEnvironment
{
public:
TestingEnvironmentGL(DeviceType deviceType, ADAPTER_TYPE AdapterType, const SwapChainDesc& SCDesc);
+ ~TestingEnvironmentGL();
static TestingEnvironmentGL* GetInstance() { return ValidatedCast<TestingEnvironmentGL>(TestingEnvironment::GetInstance()); }
+ GLuint CompileGLShader(const char* Source, GLenum ShaderType);
+ GLuint LinkProgram(GLuint Shaders[], GLuint NumShaders);
+
+ GLuint GetDummyVAO() { return m_DummyVAO; }
+
private:
+ GLuint m_DummyVAO = 0;
};
} // namespace Testing
diff --git a/UnitTests/DiligentCoreAPITest/include/GL/TestingSwapChainGL.h b/UnitTests/DiligentCoreAPITest/include/GL/TestingSwapChainGL.h
index 3a5058e8..fa6c3c37 100644
--- a/UnitTests/DiligentCoreAPITest/include/GL/TestingSwapChainGL.h
+++ b/UnitTests/DiligentCoreAPITest/include/GL/TestingSwapChainGL.h
@@ -37,10 +37,16 @@ public:
IRenderDevice* pDevice,
IDeviceContext* pContext,
const SwapChainDesc& SCDesc);
+ ~TestingSwapChainGL();
virtual void TakeSnapshot() override final;
+ void BindFramebuffer();
+
private:
+ GLuint m_RenderTarget = 0;
+ GLuint m_DepthBuffer = 0;
+ GLuint m_FBO = 0;
};
} // namespace Testing
diff --git a/UnitTests/DiligentCoreAPITest/src/GL/DrawCommandRefenceGL.cpp b/UnitTests/DiligentCoreAPITest/src/GL/DrawCommandRefenceGL.cpp
index 18acef04..8f9e748e 100644
--- a/UnitTests/DiligentCoreAPITest/src/GL/DrawCommandRefenceGL.cpp
+++ b/UnitTests/DiligentCoreAPITest/src/GL/DrawCommandRefenceGL.cpp
@@ -22,6 +22,7 @@
*/
#include "GL/TestingEnvironmentGL.h"
+#include "GL/TestingSwapChainGL.h"
namespace Diligent
{
@@ -30,13 +31,90 @@ namespace Testing
{
static const char* VSSource = R"(
+#version 420 core
+
+#ifndef GL_ES
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+#endif
+
+layout(location = 0) out vec3 out_Color;
+
+void main()
+{
+ vec4 Pos[4];
+ Pos[0] = vec4(-0.5, -0.5, 0.0, 1.0);
+ Pos[1] = vec4(-0.5, +0.5, 0.0, 1.0);
+ Pos[2] = vec4(+0.5, -0.5, 0.0, 1.0);
+ Pos[3] = vec4(+0.5, +0.5, 0.0, 1.0);
+
+ vec3 Col[4];
+ Col[0] = vec3(1.0, 0.0, 0.0);
+ Col[1] = vec3(0.0, 1.0, 0.0);
+ Col[2] = vec3(0.0, 0.0, 1.0);
+ Col[3] = vec3(1.0, 1.0, 1.0);
+
+ gl_Position = Pos[gl_VertexID];
+ out_Color = Col[gl_VertexID];
+}
)";
static const char* PSSource = R"(
+#version 420 core
+
+layout(location = 0) in vec3 in_Color;
+layout(location = 0) out vec4 out_Color;
+
+void main()
+{
+ out_Color = vec4(in_Color, 1.0);
+}
)";
void RenderDrawCommandRefenceGL(ISwapChain* pSwapChain)
{
+ auto* pEnv = TestingEnvironmentGL::GetInstance();
+ auto* pContext = pEnv->GetDeviceContext();
+ auto* pTestingSwapChainGL = ValidatedCast<TestingSwapChainGL>(pSwapChain);
+
+ const auto& SCDesc = pTestingSwapChainGL->GetDesc();
+
+ GLuint glShaders[2] = {};
+ glShaders[0] = pEnv->CompileGLShader(VSSource, GL_VERTEX_SHADER);
+ ASSERT_NE(glShaders[0], 0u);
+ glShaders[1] = pEnv->CompileGLShader(PSSource, GL_FRAGMENT_SHADER);
+ ASSERT_NE(glShaders[1], 0u);
+ auto glProg = pEnv->LinkProgram(glShaders, 2);
+ ASSERT_NE(glProg, 0u);
+
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_BLEND);
+ glDisable(GL_CULL_FACE);
+ if (glPolygonMode != nullptr)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+ pTestingSwapChainGL->BindFramebuffer();
+ glViewport(0, 0, SCDesc.Width, SCDesc.Height);
+ glUseProgram(glProg);
+ glBindVertexArray(pEnv->GetDummyVAO());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glBindVertexArray(0);
+ glUseProgram(0);
+
+ // Make sure Diligent Engine will reset all GL states
+ pContext->InvalidateState();
+
+ for(int i = 0; i < _countof(glShaders); ++i)
+ {
+ if (glShaders[i] != 0)
+ glDeleteShader(glShaders[i]);
+ }
+ if (glProg != 0)
+ glDeleteProgram(glProg);
}
} // namespace Testing
diff --git a/UnitTests/DiligentCoreAPITest/src/GL/TestingEnvironmentGL.cpp b/UnitTests/DiligentCoreAPITest/src/GL/TestingEnvironmentGL.cpp
index 538cc051..a78318cb 100644
--- a/UnitTests/DiligentCoreAPITest/src/GL/TestingEnvironmentGL.cpp
+++ b/UnitTests/DiligentCoreAPITest/src/GL/TestingEnvironmentGL.cpp
@@ -37,15 +37,106 @@ void CreateTestingSwapChainGL(IRenderDevice* pDevice,
TestingEnvironmentGL::TestingEnvironmentGL(DeviceType deviceType, ADAPTER_TYPE AdapterType, const SwapChainDesc& SCDesc) :
TestingEnvironment{deviceType, AdapterType, SCDesc}
{
+ // Initialize GLEW
+ auto err = glewInit();
+ if (GLEW_OK != err)
+ LOG_ERROR_AND_THROW("Failed to initialize GLEW");
+
if (m_pSwapChain == nullptr)
{
CreateTestingSwapChainGL(m_pDevice, m_pDeviceContext, SCDesc, &m_pSwapChain);
}
+
+ glGenVertexArrays(1, &m_DummyVAO);
+}
+
+TestingEnvironmentGL::~TestingEnvironmentGL()
+{
+ glDeleteVertexArrays(1, &m_DummyVAO);
+}
+
+GLuint TestingEnvironmentGL::CompileGLShader(const char* Source, GLenum ShaderType)
+{
+ GLuint glShader = glCreateShader(ShaderType);
+
+ const char* ShaderStrings[] = {Source};
+ GLint Lenghts[] = {static_cast<GLint>(strlen(Source))};
+
+ // Provide source strings (the strings will be saved in internal OpenGL memory)
+ glShaderSource(glShader, _countof(ShaderStrings), ShaderStrings, Lenghts);
+ // When the shader is compiled, it will be compiled as if all of the given strings were concatenated end-to-end.
+ glCompileShader(glShader);
+ GLint compiled = GL_FALSE;
+ // Get compilation status
+ glGetShaderiv(glShader, GL_COMPILE_STATUS, &compiled);
+ if (!compiled)
+ {
+ int infoLogLen = 0;
+ // The function glGetShaderiv() tells how many bytes to allocate; the length includes the NULL terminator.
+ glGetShaderiv(glShader, GL_INFO_LOG_LENGTH, &infoLogLen);
+
+ std::vector<GLchar> infoLog(infoLogLen);
+ if (infoLogLen > 0)
+ {
+ int charsWritten = 0;
+ // Get the log. infoLogLen is the size of infoLog. This tells OpenGL how many bytes at maximum it will write
+ // charsWritten is a return value, specifying how many bytes it actually wrote. One may pass NULL if he
+ // doesn't care
+ glGetShaderInfoLog(glShader, infoLogLen, &charsWritten, infoLog.data());
+ VERIFY(charsWritten == infoLogLen - 1, "Unexpected info log length");
+ LOG_ERROR("Failed to compile GL shader\n", infoLog.data());
+ }
+ }
+
+ return glShader;
+}
+
+GLuint TestingEnvironmentGL::LinkProgram(GLuint Shaders[], GLuint NumShaders)
+{
+ auto glProg = glCreateProgram();
+
+ for (Uint32 i = 0; i < NumShaders; ++i)
+ {
+ glAttachShader(glProg, Shaders[i]);
+ VERIFY_EXPR(glGetError() == GL_NO_ERROR);
+ }
+
+ glLinkProgram(glProg);
+ int IsLinked = GL_FALSE;
+ glGetProgramiv(glProg, GL_LINK_STATUS, &IsLinked);
+ if (!IsLinked)
+ {
+ int LengthWithNull = 0, Length = 0;
+ // Notice that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv.
+ // The length of the info log includes a null terminator.
+ glGetProgramiv(glProg, GL_INFO_LOG_LENGTH, &LengthWithNull);
+
+ // The maxLength includes the NULL character
+ std::vector<char> shaderProgramInfoLog(LengthWithNull);
+
+ // Notice that glGetProgramInfoLog is used, not glGetShaderInfoLog.
+ glGetProgramInfoLog(glProg, LengthWithNull, &Length, shaderProgramInfoLog.data());
+ VERIFY(Length == LengthWithNull - 1, "Incorrect program info log len");
+ LOG_ERROR_MESSAGE("Failed to link shader program:\n", shaderProgramInfoLog.data(), '\n');
+ }
+
+ for (Uint32 i = 0; i < NumShaders; ++i)
+ {
+ glDetachShader(glProg, Shaders[i]);
+ }
+ return glProg;
}
TestingEnvironment* CreateTestingEnvironmentGL(DeviceType deviceType, ADAPTER_TYPE AdapterType, const SwapChainDesc& SCDesc)
{
- return new TestingEnvironmentGL{deviceType, AdapterType, SCDesc};
+ try
+ {
+ return new TestingEnvironmentGL{deviceType, AdapterType, SCDesc};
+ }
+ catch (...)
+ {
+ return nullptr;
+ }
}
} // namespace Testing
diff --git a/UnitTests/DiligentCoreAPITest/src/GL/TestingSwapChainGL.cpp b/UnitTests/DiligentCoreAPITest/src/GL/TestingSwapChainGL.cpp
index b5e36936..9c3cea64 100644
--- a/UnitTests/DiligentCoreAPITest/src/GL/TestingSwapChainGL.cpp
+++ b/UnitTests/DiligentCoreAPITest/src/GL/TestingSwapChainGL.cpp
@@ -21,6 +21,7 @@
* of the possibility of such damages.
*/
+#include "GL/TestingEnvironmentGL.h"
#include "GL/TestingSwapChainGL.h"
namespace Diligent
@@ -41,10 +42,98 @@ TestingSwapChainGL::TestingSwapChainGL(IReferenceCounters* pRefCounters,
SCDesc //
}
{
+ {
+ glGenTextures(1, &m_RenderTarget);
+ if (glGetError() != GL_NO_ERROR)
+ LOG_ERROR_AND_THROW("Failed to create render target texture");
+
+ GLenum RenderTargetFmt = 0;
+ switch (m_SwapChainDesc.ColorBufferFormat)
+ {
+ case TEX_FORMAT_RGBA8_UNORM:
+ RenderTargetFmt = GL_RGBA8;
+ break;
+
+ default:
+ UNSUPPORTED("Texture format ", GetTextureFormatAttribs(m_SwapChainDesc.ColorBufferFormat).Name, " is not a supported color buffer format");
+ }
+
+ glBindTexture(GL_TEXTURE_2D, m_RenderTarget);
+ // levels format width height
+ glTexStorage2D(GL_TEXTURE_2D, 1, RenderTargetFmt, m_SwapChainDesc.Width, m_SwapChainDesc.Height);
+ if (glGetError() != GL_NO_ERROR)
+ LOG_ERROR_AND_THROW("Failed to allocate render target texture");
+ }
+
+
+ {
+ glGenTextures(1, &m_DepthBuffer);
+ if (glGetError() != GL_NO_ERROR)
+ LOG_ERROR_AND_THROW("Failed to create depth texture");
+
+ GLenum DepthBufferFmt = 0;
+ switch (m_SwapChainDesc.DepthBufferFormat)
+ {
+ case TEX_FORMAT_D32_FLOAT:
+ DepthBufferFmt = GL_DEPTH_COMPONENT32F;
+ break;
+
+ default:
+ UNSUPPORTED("Texture format ", GetTextureFormatAttribs(m_SwapChainDesc.DepthBufferFormat).Name, " is not a supported depth buffer format");
+ }
+
+ glBindTexture(GL_TEXTURE_2D, m_DepthBuffer);
+ // levels format width height
+ glTexStorage2D(GL_TEXTURE_2D, 1, DepthBufferFmt, m_SwapChainDesc.Width, m_SwapChainDesc.Height);
+ if (glGetError() != GL_NO_ERROR)
+ LOG_ERROR_AND_THROW("Failed to allocate render target texture");
+ }
+
+ {
+ glGenFramebuffers(1, &m_FBO);
+ if (glGetError() != GL_NO_ERROR)
+ LOG_ERROR_AND_THROW("Failed to create FBO");
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, m_FBO);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_RenderTarget, 0);
+ glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_RenderTarget, 0);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_DepthBuffer, 0);
+ glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_DepthBuffer, 0);
+ static const GLenum DrawBuffers[] = {GL_COLOR_ATTACHMENT0};
+ glDrawBuffers(1, DrawBuffers);
+ GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (Status != GL_FRAMEBUFFER_COMPLETE)
+ LOG_ERROR_AND_THROW("FBO is incomplete");
+ }
+
+ // Make sure Diligent Engine will reset all GL states
+ pContext->InvalidateState();
+}
+
+void TestingSwapChainGL::BindFramebuffer()
+{
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, m_FBO);
+}
+
+TestingSwapChainGL::~TestingSwapChainGL()
+{
+ if (m_RenderTarget != 0)
+ glDeleteTextures(1, &m_RenderTarget);
+ if (m_DepthBuffer != 0)
+ glDeleteTextures(1, &m_DepthBuffer);
+ if (m_FBO != 0)
+ glDeleteFramebuffers(1, &m_FBO);
}
void TestingSwapChainGL::TakeSnapshot()
{
+ m_ReferenceDataPitch = m_SwapChainDesc.Width * 4;
+ m_ReferenceData.resize(m_SwapChainDesc.Height * m_ReferenceDataPitch);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, m_FBO);
+ glReadPixels(0, 0, m_SwapChainDesc.Width, m_SwapChainDesc.Height, GL_RGBA, GL_UNSIGNED_BYTE, m_ReferenceData.data());
}
void CreateTestingSwapChainGL(IRenderDevice* pDevice,
@@ -52,8 +141,15 @@ void CreateTestingSwapChainGL(IRenderDevice* pDevice,
const SwapChainDesc& SCDesc,
ISwapChain** ppSwapChain)
{
- TestingSwapChainGL* pTestingSC(MakeNewRCObj<TestingSwapChainGL>()(pDevice, pContext, SCDesc));
- pTestingSC->QueryInterface(IID_SwapChain, reinterpret_cast<IObject**>(ppSwapChain));
+ try
+ {
+ TestingSwapChainGL* pTestingSC(MakeNewRCObj<TestingSwapChainGL>()(pDevice, pContext, SCDesc));
+ pTestingSC->QueryInterface(IID_SwapChain, reinterpret_cast<IObject**>(ppSwapChain));
+ }
+ catch (...)
+ {
+ *ppSwapChain = nullptr;
+ }
}
} // namespace Testing
diff --git a/UnitTests/DiligentCoreAPITest/src/TestingEnvironment.cpp b/UnitTests/DiligentCoreAPITest/src/TestingEnvironment.cpp
index e187fc3e..dca742a8 100644
--- a/UnitTests/DiligentCoreAPITest/src/TestingEnvironment.cpp
+++ b/UnitTests/DiligentCoreAPITest/src/TestingEnvironment.cpp
@@ -274,8 +274,9 @@ TestingEnvironment::TestingEnvironment(DeviceType deviceType, ADAPTER_TYPE Adapt
NumDeferredCtx = 0;
}
ppContexts.resize(1 + NumDeferredCtx);
+ RefCntAutoPtr<ISwapChain> pSwapChain; // We will use testing swap chain instead
pFactoryOpenGL->CreateDeviceAndSwapChainGL(
- CreateInfo, &m_pDevice, ppContexts.data(), SCDesc, &m_pSwapChain);
+ CreateInfo, &m_pDevice, ppContexts.data(), SCDesc, &pSwapChain);
}
break;
#endif
diff --git a/UnitTests/DiligentCoreAPITest/src/main.cpp b/UnitTests/DiligentCoreAPITest/src/main.cpp
index 4db55c5a..bacaca9f 100644
--- a/UnitTests/DiligentCoreAPITest/src/main.cpp
+++ b/UnitTests/DiligentCoreAPITest/src/main.cpp
@@ -171,5 +171,6 @@ int main(int argc, char** argv)
::testing::AddGlobalTestEnvironment(pEnv);
auto ret_val = RUN_ALL_TESTS();
+ std::cout << "\n\n\n";
return ret_val;
}