Skip to content

Commit

Permalink
Change glCheck macro to be usable as an expression
Browse files Browse the repository at this point in the history
  • Loading branch information
ZXShady authored and ChrisThrasher committed Sep 25, 2024
1 parent c8cf845 commit 0d33dde
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 70 deletions.
51 changes: 29 additions & 22 deletions src/SFML/Graphics/GLCheck.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,10 @@

#include <filesystem>
#include <string_view>

#include <type_traits>

namespace sf::priv
{
////////////////////////////////////////////////////////////
/// Let's define a macro to quickly check every OpenGL API call
////////////////////////////////////////////////////////////
#ifdef SFML_DEBUG

// In debug mode, perform a test on every OpenGL call
// The do-while loop is needed so that glCheck can be used as a single statement in if/else branches
#define glCheck(expr) \
do \
{ \
expr; \
sf::priv::glCheckError(__FILE__, __LINE__, #expr); \
} while (false)

#else

// Else, we don't add any overhead
#define glCheck(expr) (expr)

#endif

////////////////////////////////////////////////////////////
/// \brief Check the last OpenGL error
///
Expand All @@ -68,4 +47,32 @@ namespace sf::priv
////////////////////////////////////////////////////////////
bool glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);

////////////////////////////////////////////////////////////
/// Let's define a macro to quickly check every OpenGL API call
////////////////////////////////////////////////////////////
#ifdef SFML_DEBUG
// In debug mode, perform a test on every OpenGL call
// The lamdba allows us to call glCheck as an expression and acts as a single statement perfect for if/else statements
#define glCheck(...) \
[](auto&& glCheckInternalFunction) \
{ \
if constexpr (!std::is_void_v<decltype(glCheckInternalFunction())>) \
{ \
const auto glCheckInternalReturnValue = glCheckInternalFunction(); \
sf::priv::glCheckError(__FILE__, static_cast<unsigned int>(__LINE__), #__VA_ARGS__); \
return glCheckInternalReturnValue; \
} \
else \
{ \
glCheckInternalFunction(); \
sf::priv::glCheckError(__FILE__, static_cast<unsigned int>(__LINE__), #__VA_ARGS__); \
} \
}([&]() { return __VA_ARGS__; })
#else

// Else, we don't add any overhead
#define glCheck(...) (__VA_ARGS__)

#endif

} // namespace sf::priv
7 changes: 2 additions & 5 deletions src/SFML/Graphics/RenderTextureImplFBO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,9 +430,7 @@ bool RenderTextureImplFBO::createFrameBuffer()
glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textureId, 0));

// A final check, just to be sure...
GLenum status = 0;
glCheck(status = GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER));
if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE)
if (glCheck(GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER)) != GLEXT_GL_FRAMEBUFFER_COMPLETE)
{
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
err() << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl;
Expand Down Expand Up @@ -486,8 +484,7 @@ bool RenderTextureImplFBO::createFrameBuffer()
}

// A final check, just to be sure...
glCheck(status = GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER));
if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE)
if (glCheck(GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER)) != GLEXT_GL_FRAMEBUFFER_COMPLETE)
{
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
err() << "Impossible to create render texture (failed to link the render buffers to the multisample frame "
Expand Down
19 changes: 8 additions & 11 deletions src/SFML/Graphics/Shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ struct Shader::UniformBinder
if (currentProgram)
{
// Enable program object
glCheck(savedProgram = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT));
savedProgram = glCheck(GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT));
if (currentProgram != savedProgram)
glCheck(GLEXT_glUseProgramObject(currentProgram));

Expand Down Expand Up @@ -865,17 +865,15 @@ bool Shader::compile(std::string_view vertexShaderCode, std::string_view geometr
}

// Create the program
GLEXT_GLhandle shaderProgram{};
glCheck(shaderProgram = GLEXT_glCreateProgramObject());
const GLEXT_GLhandle shaderProgram = glCheck(GLEXT_glCreateProgramObject());

// Create the vertex shader if needed
if (!vertexShaderCode.empty())
{
// Create and compile the shader
GLEXT_GLhandle vertexShader{};
glCheck(vertexShader = GLEXT_glCreateShaderObject(GLEXT_GL_VERTEX_SHADER));
const GLcharARB* sourceCode = vertexShaderCode.data();
const auto sourceCodeLength = static_cast<GLint>(vertexShaderCode.length());
const GLEXT_GLhandle vertexShader = glCheck(GLEXT_glCreateShaderObject(GLEXT_GL_VERTEX_SHADER));
const GLcharARB* sourceCode = vertexShaderCode.data();
const auto sourceCodeLength = static_cast<GLint>(vertexShaderCode.length());
glCheck(GLEXT_glShaderSource(vertexShader, 1, &sourceCode, &sourceCodeLength));
glCheck(GLEXT_glCompileShader(vertexShader));

Expand Down Expand Up @@ -929,10 +927,9 @@ bool Shader::compile(std::string_view vertexShaderCode, std::string_view geometr
if (!fragmentShaderCode.empty())
{
// Create and compile the shader
GLEXT_GLhandle fragmentShader{};
glCheck(fragmentShader = GLEXT_glCreateShaderObject(GLEXT_GL_FRAGMENT_SHADER));
const GLcharARB* sourceCode = fragmentShaderCode.data();
const auto sourceCodeLength = static_cast<GLint>(fragmentShaderCode.length());
const GLEXT_GLhandle fragmentShader = glCheck(GLEXT_glCreateShaderObject(GLEXT_GL_FRAGMENT_SHADER));
const GLcharARB* sourceCode = fragmentShaderCode.data();
const auto sourceCodeLength = static_cast<GLint>(fragmentShaderCode.length());
glCheck(GLEXT_glShaderSource(fragmentShader, 1, &sourceCode, &sourceCodeLength));
glCheck(GLEXT_glCompileShader(fragmentShader));

Expand Down
6 changes: 2 additions & 4 deletions src/SFML/Graphics/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -648,11 +648,9 @@ void Texture::update(const Texture& texture, Vector2u dest)
GLEXT_glFramebufferTexture2D(GLEXT_GL_DRAW_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0));

// A final check, just to be sure...
GLenum sourceStatus = 0;
glCheck(sourceStatus = GLEXT_glCheckFramebufferStatus(GLEXT_GL_READ_FRAMEBUFFER));
const GLenum sourceStatus = glCheck(GLEXT_glCheckFramebufferStatus(GLEXT_GL_READ_FRAMEBUFFER));

GLenum destStatus = 0;
glCheck(destStatus = GLEXT_glCheckFramebufferStatus(GLEXT_GL_DRAW_FRAMEBUFFER));
const GLenum destStatus = glCheck(GLEXT_glCheckFramebufferStatus(GLEXT_GL_DRAW_FRAMEBUFFER));

if ((sourceStatus == GLEXT_GL_FRAMEBUFFER_COMPLETE) && (destStatus == GLEXT_GL_FRAMEBUFFER_COMPLETE))
{
Expand Down
12 changes: 4 additions & 8 deletions src/SFML/Graphics/VertexBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,23 +236,19 @@ bool VertexBuffer::update([[maybe_unused]] const VertexBuffer& vertexBuffer)
nullptr,
VertexBufferImpl::usageToGlEnum(m_usage)));

void* destination = nullptr;
glCheck(destination = GLEXT_glMapBuffer(GLEXT_GL_ARRAY_BUFFER, GLEXT_GL_WRITE_ONLY));
void* const destination = glCheck(GLEXT_glMapBuffer(GLEXT_GL_ARRAY_BUFFER, GLEXT_GL_WRITE_ONLY));

glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, vertexBuffer.m_buffer));

void* source = nullptr;
glCheck(source = GLEXT_glMapBuffer(GLEXT_GL_ARRAY_BUFFER, GLEXT_GL_READ_ONLY));
const void* const source = glCheck(GLEXT_glMapBuffer(GLEXT_GL_ARRAY_BUFFER, GLEXT_GL_READ_ONLY));

std::memcpy(destination, source, sizeof(Vertex) * vertexBuffer.m_size);

GLboolean sourceResult = GL_FALSE;
glCheck(sourceResult = GLEXT_glUnmapBuffer(GLEXT_GL_ARRAY_BUFFER));
const GLboolean sourceResult = glCheck(GLEXT_glUnmapBuffer(GLEXT_GL_ARRAY_BUFFER));

glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));

GLboolean destinationResult = GL_FALSE;
glCheck(destinationResult = GLEXT_glUnmapBuffer(GLEXT_GL_ARRAY_BUFFER));
const GLboolean destinationResult = glCheck(GLEXT_glUnmapBuffer(GLEXT_GL_ARRAY_BUFFER));

glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, 0));

Expand Down
2 changes: 1 addition & 1 deletion src/SFML/Window/EGLCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ bool eglCheckError(const std::filesystem::path& file, unsigned int line, std::st
{
const auto logError = [&](const char* error, const char* description)
{
err() << "An internal EGL call failed in " << file.filename() << " (" << line << ") : "
err() << "An internal EGL call failed in " << file.filename() << "(" << line << ")."
<< "\nExpression:\n " << expression << "\nError description:\n " << error << "\n " << description << '\n'
<< std::endl;

Expand Down
48 changes: 29 additions & 19 deletions src/SFML/Window/EGLCheck.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,37 +35,47 @@

namespace sf::priv
{
////////////////////////////////////////////////////////////
/// \brief Check the last EGL error
///
/// \param file Source file where the call is located
/// \param line Line number of the source file where the call is located
/// \param expression The evaluated expression as a string
///
/// \return `false` if an error occurred, `true` otherwise
///
////////////////////////////////////////////////////////////
bool eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);

////////////////////////////////////////////////////////////
/// Let's define a macro to quickly check every EGL API call
////////////////////////////////////////////////////////////
#ifdef SFML_DEBUG

// In debug mode, perform a test on every EGL call
// The do-while loop is needed so that glCheck can be used as a single statement in if/else branches
#define eglCheck(expr) \
do \
{ \
expr; \
sf::priv::eglCheckError(__FILE__, __LINE__, #expr); \
} while (false)
// The lamdba allows us to call eglCheck as an expression and acts as a single statement perfect for if/else statements
#define eglCheck(...) \
[](auto&& eglCheckInternalFunction) \
{ \
if constexpr (!std::is_void_v<decltype(eglCheckInternalFunction())>) \
{ \
const auto eglCheckInternalReturnValue = eglCheckInternalFunction(); \
sf::priv::eglCheckError(__FILE__, static_cast<unsigned int>(__LINE__), #__VA_ARGS__); \
return eglCheckInternalReturnValue; \
} \
else \
{ \
eglCheckInternalFunction(); \
sf::priv::eglCheckError(__FILE__, static_cast<unsigned int>(__LINE__), #__VA_ARGS__); \
} \
}([&]() { return __VA_ARGS__; })

#else

// Else, we don't add any overhead
#define eglCheck(x) (x)
#define eglCheck(...) (__VA_ARGS__)

#endif

////////////////////////////////////////////////////////////
/// \brief Check the last EGL error
///
/// \param file Source file where the call is located
/// \param line Line number of the source file where the call is located
/// \param expression The evaluated expression as a string
///
/// \return `false` if an error occurred, `true` otherwise
///
////////////////////////////////////////////////////////////
bool eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);

} // namespace sf::priv

0 comments on commit 0d33dde

Please sign in to comment.