summaryrefslogtreecommitdiffstats
path: root/UnitTests
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 /UnitTests
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 'UnitTests')
-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
8 files changed, 304 insertions, 7 deletions
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;
}