Move readback format mapping to renderer gl

This commit is contained in:
2026-06-02 06:27:29 +02:00
parent 9ce49ef19c
commit 75dfc85978
6 changed files with 117 additions and 13 deletions

View File

@@ -123,6 +123,32 @@ OpenGlPixelFormat texture_format_for_channel_count(std::uint32_t channel_count)
}
}
OpenGlReadbackFormat rgba8_readback_format() noexcept
{
return OpenGlReadbackFormat {
.pixel_format = gl_rgba,
.component_type = gl_unsigned_byte,
.bytes_per_pixel = 4U,
};
}
OpenGlReadbackFormat rgba32f_readback_format() noexcept
{
return OpenGlReadbackFormat {
.pixel_format = gl_rgba,
.component_type = gl_float,
.bytes_per_pixel = 16U,
};
}
std::uint64_t readback_byte_count(
OpenGlReadbackFormat format,
std::uint32_t width,
std::uint32_t height) noexcept
{
return static_cast<std::uint64_t>(width) * height * format.bytes_per_pixel;
}
const char* framebuffer_status_name(std::uint32_t status) noexcept
{
switch (status) {

View File

@@ -32,12 +32,24 @@ struct OpenGlTextureParameter {
std::uint32_t value = 0;
};
struct OpenGlReadbackFormat {
std::uint32_t pixel_format = 0;
std::uint32_t component_type = 0;
std::uint32_t bytes_per_pixel = 0;
};
[[nodiscard]] OpenGlCapabilities detect_opengl_capabilities(
std::span<const std::string_view> extensions,
OpenGlRuntime runtime) noexcept;
[[nodiscard]] std::uint32_t texture_upload_type_for_internal_format(std::uint32_t internal_format) noexcept;
[[nodiscard]] OpenGlPixelFormat texture_format_for_channel_count(std::uint32_t channel_count) noexcept;
[[nodiscard]] OpenGlReadbackFormat rgba8_readback_format() noexcept;
[[nodiscard]] OpenGlReadbackFormat rgba32f_readback_format() noexcept;
[[nodiscard]] std::uint64_t readback_byte_count(
OpenGlReadbackFormat format,
std::uint32_t width,
std::uint32_t height) noexcept;
[[nodiscard]] const char* framebuffer_status_name(std::uint32_t status) noexcept;
[[nodiscard]] std::uint32_t framebuffer_color_buffer_mask() noexcept;
[[nodiscard]] std::uint32_t framebuffer_blit_filter(bool linear) noexcept;

View File

@@ -358,10 +358,18 @@ uint8_t* RTT::readTextureData(uint8_t* buffer) const noexcept
buffer = createBuffer();
App::I->render_task([&]
{
const auto readback = pp::renderer::gl::rgba8_readback_format();
GLint old;
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID);
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glReadPixels(
0,
0,
w,
h,
static_cast<GLenum>(readback.pixel_format),
static_cast<GLenum>(readback.component_type),
buffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, old);
});
return buffer;
@@ -375,10 +383,18 @@ float* RTT::readTextureDataFloat(float* buffer) const noexcept
buffer = createBufferFloat();
App::I->render_task([&]
{
const auto readback = pp::renderer::gl::rgba32f_readback_format();
GLint old;
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID);
glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, buffer);
glReadPixels(
0,
0,
w,
h,
static_cast<GLenum>(readback.pixel_format),
static_cast<GLenum>(readback.component_type),
buffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, old);
});
return buffer;
@@ -386,12 +402,21 @@ float* RTT::readTextureDataFloat(float* buffer) const noexcept
uint8_t* RTT::createBuffer() const noexcept
{
return new uint8_t[w * h * 4];
const auto readback = pp::renderer::gl::rgba8_readback_format();
return new uint8_t[pp::renderer::gl::readback_byte_count(
readback,
static_cast<std::uint32_t>(w),
static_cast<std::uint32_t>(h))];
}
float * RTT::createBufferFloat() const noexcept
{
return new float[w * h * 4];
const auto readback = pp::renderer::gl::rgba32f_readback_format();
return new float[pp::renderer::gl::readback_byte_count(
readback,
static_cast<std::uint32_t>(w),
static_cast<std::uint32_t>(h))
/ sizeof(float)];
}
void RTT::bindTexture()
@@ -467,11 +492,26 @@ bool PBO::create(RTT& rtt) noexcept
App::I->render_task([this, &rtt] {
width = rtt.getWidth();
height = rtt.getHeight();
const auto readback = pp::renderer::gl::rgba8_readback_format();
rtt.bindFramebuffer();
glGenBuffers(1, &buffer_id);
glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer_id);
glBufferData(GL_PIXEL_PACK_BUFFER, width * height * 4, 0, GL_STREAM_READ);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBufferData(
GL_PIXEL_PACK_BUFFER,
static_cast<GLsizeiptr>(pp::renderer::gl::readback_byte_count(
readback,
static_cast<std::uint32_t>(width),
static_cast<std::uint32_t>(height))),
0,
GL_STREAM_READ);
glReadPixels(
0,
0,
width,
height,
static_cast<GLenum>(readback.pixel_format),
static_cast<GLenum>(readback.component_type),
0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
rtt.unbindFramebuffer();
});
@@ -513,9 +553,14 @@ void PBO::unbind() noexcept
glm::uint8_t* PBO::map() noexcept
{
App::I->render_task([this] {
const auto readback = pp::renderer::gl::rgba8_readback_format();
glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer_id);
mapped_ptr = (GLubyte*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0,
width * height * 4, GL_MAP_READ_BIT);
static_cast<GLsizeiptr>(pp::renderer::gl::readback_byte_count(
readback,
static_cast<std::uint32_t>(width),
static_cast<std::uint32_t>(height))),
GL_MAP_READ_BIT);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
});
return mapped_ptr;