Skip to content

Commit

Permalink
[Render/Renderer] Added recoverFramebufferAttachmentParameter()
Browse files Browse the repository at this point in the history
- This can get a framebuffer's parameters, such as bit depth, color encoding, etc

- Recovering default framebuffer's color & depth formats to be gotten by the user if needed

- Added TextureInternalFormat::DEPTH_32

- Added FramebufferAttachment::DEFAULT_{FRONT|BACK}_{LEFT|RIGHT}
  • Loading branch information
Razakhel committed Oct 23, 2024
1 parent 189a819 commit 5784d74
Show file tree
Hide file tree
Showing 2 changed files with 213 additions and 15 deletions.
71 changes: 57 additions & 14 deletions include/RaZ/Render/Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,15 +422,16 @@ enum class TextureInternalFormat : unsigned int {
RGB32F = 34837 /* GL_RGB32F */, ///<
RGBA32F = 34836 /* GL_RGBA32F */, ///<

RGB10_A2 = 32857 /* GL_RGB10_A2 */, ///<
RGB10_A2UI = 36975 /* GL_RGB10_A2UI */, ///<
R11F_G11F_B10F = 35898 /* GL_R11F_G11F_B10F */, ///<

DEPTH16 = 33189 /* GL_DEPTH_COMPONENT16 */, ///<
DEPTH24 = 33190 /* GL_DEPTH_COMPONENT24 */, ///<
DEPTH24_STENCIL8 = 35056 /* GL_DEPTH24_STENCIL8 */, ///<
DEPTH32 = 33191 /* GL_DEPTH_COMPONENT32 */, ///<
DEPTH32F = 36012 /* GL_DEPTH_COMPONENT32F */, ///<
DEPTH32F_STENCIL8 = 36013 /* GL_DEPTH32F_STENCIL8 */, ///<

RGB10_A2 = 32857 /* GL_RGB10_A2 */, ///<
RGB10_A2UI = 36975 /* GL_RGB10_A2UI */, ///<
R11F_G11F_B10F = 35898 /* GL_R11F_G11F_B10F */ ///<
DEPTH32F_STENCIL8 = 36013 /* GL_DEPTH32F_STENCIL8 */ ///<
};

enum class PixelDataType : unsigned int {
Expand Down Expand Up @@ -729,7 +730,38 @@ enum class FramebufferAttachment : unsigned int {
COLOR4 = 36068 /* GL_COLOR_ATTACHMENT4 */, ///< Color attachment 4.
COLOR5 = 36069 /* GL_COLOR_ATTACHMENT5 */, ///< Color attachment 5.
COLOR6 = 36070 /* GL_COLOR_ATTACHMENT6 */, ///< Color attachment 6.
COLOR7 = 36071 /* GL_COLOR_ATTACHMENT7 */ ///< Color attachment 7.
COLOR7 = 36071 /* GL_COLOR_ATTACHMENT7 */, ///< Color attachment 7.

// Default framebuffer attachments
#if !defined(USE_WEBGL)
#if !defined(USE_OPENGL_ES)
DEFAULT_FRONT_LEFT = 1024 /* GL_FRONT_LEFT */, ///<
DEFAULT_FRONT_RIGHT = 1025 /* GL_FRONT_RIGHT */, ///<
DEFAULT_BACK_LEFT = 1026 /* GL_BACK_LEFT */, ///<
DEFAULT_BACK_RIGHT = 1027 /* GL_BACK_RIGHT */, ///<
#else
DEFAULT_BACK = 1029 /* GL_BACK */, ///<
#endif
DEFAULT_DEPTH = 6145 /* GL_DEPTH */, ///<
DEFAULT_STENCIL = 6146 /* GL_STENCIL */ ///<
#endif
};

enum class FramebufferAttachmentParam : unsigned int {
RED_SIZE = 33298 /* GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE */, ///<
GREEN_SIZE = 33299 /* GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE */, ///<
BLUE_SIZE = 33300 /* GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE */, ///<
ALPHA_SIZE = 33301 /* GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE */, ///<
DEPTH_SIZE = 33302 /* GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE */, ///<
STENCIL_SIZE = 33303 /* GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE */, ///<
COMPONENT_TYPE = 33297 /* GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE */, ///<
COLOR_ENCODING = 33296 /* GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING */, ///<
OBJECT_TYPE = 36048 /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE */, ///<
OBJECT_NAME = 36049 /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME */, ///<
TEXTURE_LEVEL = 36050 /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL */, ///<
TEXTURE_CUBE_MAP_FACE = 36051 /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE */, ///<
TEXTURE_LAYER = 36052 /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */, ///<
LAYERED = 36263 /* GL_FRAMEBUFFER_ATTACHMENT_LAYERED */ ///<
};

enum class ReadBuffer : unsigned int {
Expand All @@ -740,10 +772,11 @@ enum class ReadBuffer : unsigned int {
FRONT = 1028 /* GL_FRONT */, ///<
LEFT = 1030 /* GL_LEFT */, ///<
RIGHT = 1031 /* GL_RIGHT */, ///<
FRONT_LEFT = 1024 /* GL_FRONT_LEFT */, ///<
FRONT_RIGHT = 1025 /* GL_FRONT_RIGHT */, ///<
BACK_LEFT = 1026 /* GL_BACK_LEFT */, ///<
BACK_RIGHT = 1027 /* GL_BACK_RIGHT */, ///<

FRONT_LEFT = static_cast<unsigned int>(FramebufferAttachment::DEFAULT_FRONT_LEFT), ///<
FRONT_RIGHT = static_cast<unsigned int>(FramebufferAttachment::DEFAULT_FRONT_RIGHT), ///<
BACK_LEFT = static_cast<unsigned int>(FramebufferAttachment::DEFAULT_BACK_LEFT), ///<
BACK_RIGHT = static_cast<unsigned int>(FramebufferAttachment::DEFAULT_BACK_RIGHT), ///<
#endif

COLOR_ATTACHMENT0 = static_cast<unsigned int>(FramebufferAttachment::COLOR0), ///< Color attachment 0.
Expand All @@ -760,10 +793,10 @@ enum class DrawBuffer : unsigned int {
NONE = static_cast<unsigned int>(ReadBuffer::NONE), ///<

#if !defined(USE_OPENGL_ES)
FRONT_LEFT = static_cast<unsigned int>(ReadBuffer::FRONT_LEFT), ///<
FRONT_RIGHT = static_cast<unsigned int>(ReadBuffer::FRONT_RIGHT), ///<
BACK_LEFT = static_cast<unsigned int>(ReadBuffer::BACK_LEFT), ///<
BACK_RIGHT = static_cast<unsigned int>(ReadBuffer::BACK_RIGHT), ///<
FRONT_LEFT = static_cast<unsigned int>(FramebufferAttachment::DEFAULT_FRONT_LEFT), ///<
FRONT_RIGHT = static_cast<unsigned int>(FramebufferAttachment::DEFAULT_FRONT_RIGHT), ///<
BACK_LEFT = static_cast<unsigned int>(FramebufferAttachment::DEFAULT_BACK_LEFT), ///<
BACK_RIGHT = static_cast<unsigned int>(FramebufferAttachment::DEFAULT_BACK_RIGHT), ///<
#else
BACK = static_cast<unsigned int>(ReadBuffer::BACK), ///<
#endif
Expand Down Expand Up @@ -913,6 +946,8 @@ class Renderer {
/// \return True if the given version is higher than or equal to the current one, false otherwise.
static bool checkVersion(int major, int minor) noexcept { return (s_majorVersion > major || (s_majorVersion == major && s_minorVersion >= minor)); }
static bool isExtensionSupported(const std::string& extension) { return (s_extensions.find(extension) != s_extensions.cend()); }
static TextureInternalFormat getDefaultFramebufferColorFormat() { return s_defaultFramebufferColor; }
static TextureInternalFormat getDefaultFramebufferDepthFormat() { return s_defaultFramebufferDepth; }
static void enable(Capability capability);
static void disable(Capability capability);
static bool isEnabled(Capability capability);
Expand Down Expand Up @@ -1338,6 +1373,10 @@ class Renderer {
unsigned int textureIndex, unsigned int mipmapLevel, unsigned int layer,
FramebufferType type = FramebufferType::FRAMEBUFFER);
#endif
static void recoverFramebufferAttachmentParameter(FramebufferAttachment attachment,
FramebufferAttachmentParam param,
int* values,
FramebufferType type = FramebufferType::FRAMEBUFFER);
static void setReadBuffer(ReadBuffer buffer);
static void setDrawBuffers(unsigned int count, const DrawBuffer* buffers);
template <std::size_t N> static void setDrawBuffers(DrawBuffer (&buffers)[N]) { setDrawBuffers(N, buffers); }
Expand Down Expand Up @@ -1432,6 +1471,8 @@ class Renderer {
~Renderer() = delete;

private:
static void recoverDefaultFramebufferColorFormat();
static void recoverDefaultFramebufferDepthFormat();
/// Prints OpenGL errors only in Debug mode and if SKIP_RENDERER_ERRORS hasn't been defined.
static void printConditionalErrors() {
#if !defined(NDEBUG) && !defined(SKIP_RENDERER_ERRORS)
Expand All @@ -1444,6 +1485,8 @@ class Renderer {
static inline int s_majorVersion {};
static inline int s_minorVersion {};
static inline std::unordered_set<std::string> s_extensions {};
static inline TextureInternalFormat s_defaultFramebufferColor {};
static inline TextureInternalFormat s_defaultFramebufferDepth {};
};

} // namespace Raz
Expand Down
157 changes: 156 additions & 1 deletion src/RaZ/Render/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ void Renderer::initialize() {

// Recovering supported extensions
{
int extCount{};
int extCount {};
getParameter(StateParameter::EXTENSION_COUNT, &extCount);

s_extensions.reserve(static_cast<std::size_t>(extCount));
Expand All @@ -125,6 +125,9 @@ void Renderer::initialize() {
}
#endif

recoverDefaultFramebufferColorFormat();
recoverDefaultFramebufferDepthFormat();

#if !defined(RAZ_PLATFORM_MAC) && !defined(USE_OPENGL_ES) // Setting the debug message callback provokes a crash on macOS & isn't available on OpenGL ES
if (checkVersion(4, 3)) {
enable(Capability::DEBUG_OUTPUT);
Expand Down Expand Up @@ -1451,6 +1454,17 @@ void Renderer::setFramebufferTexture3D(FramebufferAttachment attachment,
}
#endif

void Renderer::recoverFramebufferAttachmentParameter(FramebufferAttachment attachment,
FramebufferAttachmentParam param,
int* values,
FramebufferType type) {
assert("Error: The Renderer must be initialized before calling its functions." && isInitialized());

glGetFramebufferAttachmentParameteriv(static_cast<unsigned int>(type), static_cast<unsigned int>(attachment), static_cast<unsigned int>(param), values);

printConditionalErrors();
}

void Renderer::setReadBuffer(ReadBuffer buffer) {
assert("Error: The Renderer must be initialized before calling its functions." && isInitialized());

Expand Down Expand Up @@ -1716,4 +1730,145 @@ void Renderer::printErrors() {
}
}

void Renderer::recoverDefaultFramebufferColorFormat() {
struct ColorInfo {
int redBitCount {};
int greenBitCount {};
int blueBitCount {};
int alphaBitCount {};
int compType {};
int encoding {};
};

struct ColorFormat {
ColorInfo colorInfo {};
TextureInternalFormat format {};
std::string_view formatStr;
};

constexpr std::array<ColorFormat, 26> formats = {{
{ ColorInfo{ 8, 8, 8, 0, GL_UNSIGNED_NORMALIZED, GL_LINEAR }, TextureInternalFormat::RGB8, "RGB8" },
{ ColorInfo{ 8, 8, 8, 8, GL_UNSIGNED_NORMALIZED, GL_LINEAR }, TextureInternalFormat::RGBA8, "RGBA8" },
{ ColorInfo{ 8, 8, 8, 0, GL_UNSIGNED_NORMALIZED, GL_SRGB }, TextureInternalFormat::SRGB8, "SRGB8" },
{ ColorInfo{ 8, 8, 8, 8, GL_UNSIGNED_NORMALIZED, GL_SRGB }, TextureInternalFormat::SRGBA8, "SRGBA8" },
{ ColorInfo{ 8, 8, 8, 0, GL_INT, GL_LINEAR }, TextureInternalFormat::RGB8I, "RGB8I" },
{ ColorInfo{ 8, 8, 8, 8, GL_INT, GL_LINEAR }, TextureInternalFormat::RGBA8I, "RGBA8I" },
{ ColorInfo{ 8, 8, 8, 0, GL_UNSIGNED_INT, GL_LINEAR }, TextureInternalFormat::RGB8UI, "RGB8UI" },
{ ColorInfo{ 8, 8, 8, 8, GL_UNSIGNED_INT, GL_LINEAR }, TextureInternalFormat::RGBA8UI, "RGBA8UI" },
{ ColorInfo{ 8, 8, 8, 0, GL_SIGNED_NORMALIZED, GL_LINEAR }, TextureInternalFormat::RGB8_SNORM, "RGB8_SNORM" },
{ ColorInfo{ 8, 8, 8, 8, GL_SIGNED_NORMALIZED, GL_LINEAR }, TextureInternalFormat::RGBA8_SNORM, "RGBA8_SNORM" },
{ ColorInfo{ 16, 16, 16, 16, GL_UNSIGNED_NORMALIZED, GL_LINEAR }, TextureInternalFormat::RGBA16, "RGBA16" },
{ ColorInfo{ 16, 16, 16, 0, GL_INT, GL_LINEAR }, TextureInternalFormat::RGB16I, "RGB16I" },
{ ColorInfo{ 16, 16, 16, 16, GL_INT, GL_LINEAR }, TextureInternalFormat::RGBA16I, "RGBA16I" },
{ ColorInfo{ 16, 16, 16, 0, GL_UNSIGNED_INT, GL_LINEAR }, TextureInternalFormat::RGB16UI, "RGB16UI" },
{ ColorInfo{ 16, 16, 16, 16, GL_UNSIGNED_INT, GL_LINEAR }, TextureInternalFormat::RGBA16UI, "RGBA16UI" },
{ ColorInfo{ 16, 16, 16, 0, GL_FLOAT, GL_LINEAR }, TextureInternalFormat::RGB16F, "RGB16F" },
{ ColorInfo{ 16, 16, 16, 16, GL_FLOAT, GL_LINEAR }, TextureInternalFormat::RGBA16F, "RGBA16F" },
{ ColorInfo{ 32, 32, 32, 0, GL_INT, GL_LINEAR }, TextureInternalFormat::RGB32I, "RGB32I" },
{ ColorInfo{ 32, 32, 32, 32, GL_INT, GL_LINEAR }, TextureInternalFormat::RGBA32I, "RGBA32I" },
{ ColorInfo{ 32, 32, 32, 0, GL_UNSIGNED_INT, GL_LINEAR }, TextureInternalFormat::RGB32UI, "RGB32UI" },
{ ColorInfo{ 32, 32, 32, 32, GL_UNSIGNED_INT, GL_LINEAR }, TextureInternalFormat::RGBA32UI, "RGBA32UI" },
{ ColorInfo{ 32, 32, 32, 0, GL_FLOAT, GL_LINEAR }, TextureInternalFormat::RGB32F, "RGB32F" },
{ ColorInfo{ 32, 32, 32, 32, GL_FLOAT, GL_LINEAR }, TextureInternalFormat::RGBA32F, "RGBA32F" },
{ ColorInfo{ 10, 10, 10, 2, GL_UNSIGNED_NORMALIZED, GL_LINEAR }, TextureInternalFormat::RGB10_A2, "RGB10_A2" },
{ ColorInfo{ 10, 10, 10, 2, GL_UNSIGNED_INT, GL_LINEAR }, TextureInternalFormat::RGB10_A2UI, "RGB10_A2UI" },
{ ColorInfo{ 11, 11, 10, 0, GL_FLOAT, GL_LINEAR }, TextureInternalFormat::R11F_G11F_B10F, "R11F_G11F_B10F" }
}};

#if defined(USE_WEBGL)
// WebGL requires getting a color attachment for the default framebuffer
// See: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getFramebufferAttachmentParameter#attachment
constexpr FramebufferAttachment attachment = FramebufferAttachment::COLOR0;
#elif defined(USE_OPENGL_ES)
constexpr FramebufferAttachment attachment = FramebufferAttachment::DEFAULT_BACK;
#else
constexpr FramebufferAttachment attachment = FramebufferAttachment::DEFAULT_BACK_LEFT;
#endif
ColorInfo colorInfo;
Renderer::recoverFramebufferAttachmentParameter(attachment, FramebufferAttachmentParam::RED_SIZE, &colorInfo.redBitCount);
Renderer::recoverFramebufferAttachmentParameter(attachment, FramebufferAttachmentParam::GREEN_SIZE, &colorInfo.greenBitCount);
Renderer::recoverFramebufferAttachmentParameter(attachment, FramebufferAttachmentParam::BLUE_SIZE, &colorInfo.blueBitCount);
Renderer::recoverFramebufferAttachmentParameter(attachment, FramebufferAttachmentParam::ALPHA_SIZE, &colorInfo.alphaBitCount);
Renderer::recoverFramebufferAttachmentParameter(attachment, FramebufferAttachmentParam::COMPONENT_TYPE, &colorInfo.compType);
Renderer::recoverFramebufferAttachmentParameter(attachment, FramebufferAttachmentParam::COLOR_ENCODING, &colorInfo.encoding);

const auto colorFormatIter = std::find_if(formats.cbegin(), formats.cend(), [&colorInfo] (const ColorFormat& format) {
return (colorInfo.redBitCount == format.colorInfo.redBitCount
&& colorInfo.greenBitCount == format.colorInfo.greenBitCount
&& colorInfo.blueBitCount == format.colorInfo.blueBitCount
&& colorInfo.alphaBitCount == format.colorInfo.alphaBitCount
&& colorInfo.compType == format.colorInfo.compType
&& colorInfo.encoding == format.colorInfo.encoding);
});

if (colorFormatIter == formats.cend()) {
Logger::error("[Renderer] Unknown default framebuffer color bits combination (red " + std::to_string(colorInfo.redBitCount) + ", green "
+ std::to_string(colorInfo.greenBitCount) + ", blue " + std::to_string(colorInfo.blueBitCount) + ", alpha "
+ std::to_string(colorInfo.alphaBitCount) + ", component type " + std::to_string(colorInfo.compType) + ", encoding "
+ std::to_string(colorInfo.encoding) + ')');
return;
}

s_defaultFramebufferColor = colorFormatIter->format;

Logger::debug("[Renderer] Found default framebuffer color format " + std::string(colorFormatIter->formatStr) + " (value "
+ std::to_string(static_cast<unsigned int>(s_defaultFramebufferColor)) + "; red " + std::to_string(colorInfo.redBitCount)
+ ", green " + std::to_string(colorInfo.greenBitCount) + ", blue " + std::to_string(colorInfo.blueBitCount) + ", alpha "
+ std::to_string(colorInfo.alphaBitCount) + ", component type " + std::to_string(colorInfo.compType) + ", encoding "
+ std::to_string(colorInfo.encoding) + ')');
}

void Renderer::recoverDefaultFramebufferDepthFormat() {
struct DepthInfo {
int depthBitCount {};
int stencilBitCount {};
int compType {};
};

struct DepthFormat {
DepthInfo depthInfo {};
TextureInternalFormat format {};
std::string_view formatStr;
};

constexpr std::array<DepthFormat, 6> formats = {{
{ DepthInfo{ 16, 0, GL_UNSIGNED_NORMALIZED }, TextureInternalFormat::DEPTH16, "DEPTH16" },
{ DepthInfo{ 24, 0, GL_UNSIGNED_NORMALIZED }, TextureInternalFormat::DEPTH24, "DEPTH24" },
{ DepthInfo{ 24, 8, GL_UNSIGNED_NORMALIZED }, TextureInternalFormat::DEPTH24_STENCIL8, "DEPTH24_STENCIL8" },
{ DepthInfo{ 32, 0, GL_UNSIGNED_NORMALIZED }, TextureInternalFormat::DEPTH32, "DEPTH32" },
{ DepthInfo{ 32, 0, GL_FLOAT }, TextureInternalFormat::DEPTH32F, "DEPTH32F" },
{ DepthInfo{ 32, 8, GL_FLOAT }, TextureInternalFormat::DEPTH32F_STENCIL8, "DEPTH32F_STENCIL8" }
}};

#if defined(USE_WEBGL)
// WebGL requires getting explicitly the depth attachment for the default framebuffer
// See: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getFramebufferAttachmentParameter#attachment
constexpr FramebufferAttachment attachment = FramebufferAttachment::DEPTH;
#else
constexpr FramebufferAttachment attachment = FramebufferAttachment::DEFAULT_DEPTH;
#endif
DepthInfo depthInfo {};
Renderer::recoverFramebufferAttachmentParameter(attachment, FramebufferAttachmentParam::DEPTH_SIZE, &depthInfo.depthBitCount);
Renderer::recoverFramebufferAttachmentParameter(attachment, FramebufferAttachmentParam::STENCIL_SIZE, &depthInfo.stencilBitCount);
Renderer::recoverFramebufferAttachmentParameter(attachment, FramebufferAttachmentParam::COMPONENT_TYPE, &depthInfo.compType);

const auto depthFormatIter = std::find_if(formats.cbegin(), formats.cend(), [&depthInfo] (const DepthFormat& format) {
return (depthInfo.depthBitCount == format.depthInfo.depthBitCount
&& depthInfo.stencilBitCount == format.depthInfo.stencilBitCount
&& depthInfo.compType == format.depthInfo.compType);
});

if (depthFormatIter == formats.cend()) {
Logger::error("[Renderer] Unknown default framebuffer depth bits combination (depth " + std::to_string(depthInfo.depthBitCount)
+ ", stencil " + std::to_string(depthInfo.stencilBitCount) + ", component type: " + std::to_string(depthInfo.compType) + ')');
return;
}

s_defaultFramebufferDepth = depthFormatIter->format;

Logger::debug("[Renderer] Found default framebuffer depth format " + std::string(depthFormatIter->formatStr) + " (value "
+ std::to_string(static_cast<unsigned int>(s_defaultFramebufferDepth)) + "; depth " + std::to_string(depthInfo.depthBitCount)
+ ", stencil " + std::to_string(depthInfo.stencilBitCount) + ", component type " + std::to_string(depthInfo.compType) + ')');
}

} // namespace Raz

0 comments on commit 5784d74

Please sign in to comment.