Skip to content

Commit

Permalink
Replaced texture array by a pool of textures
Browse files Browse the repository at this point in the history
  • Loading branch information
rtoumazet committed Mar 27, 2024
1 parent fc7a3fc commit 74bd226
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 84 deletions.
81 changes: 45 additions & 36 deletions saturnin/src/video/opengl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ constexpr auto check_gl_error = 1;
constexpr enum class RenderType { RenderType_drawElements, RenderType_drawTest };
constexpr auto render_type = RenderType::RenderType_drawElements;

constexpr auto uses_fbo = true;
constexpr auto uses_fbo = false;

const std::unordered_map<ScrollScreen, VdpLayer> screen_to_layer = {
{ScrollScreen::nbg3, VdpLayer::nbg3},
Expand Down Expand Up @@ -150,7 +150,7 @@ void Opengl::shutdown() const {
void Opengl::preRender() {
switchRenderedBuffer();

attachTextureLayerToFbo(fbo_texture_array_id_, getFboTextureLayer(currentRenderedBuffer()));
attachTextureToFbo(getFboTextureId(currentRenderedBuffer()));

// Viewport is the entire Saturn framebuffer
glViewport(0, 0, saturn_framebuffer_width, saturn_framebuffer_height);
Expand Down Expand Up @@ -453,30 +453,32 @@ void Opengl::renderToAvailableTexture(const FboKey& key, const PartsList& parts_
}

void Opengl::clearFboTextures() {
Log::debug(Logger::opengl, "clearFboTextures() call");
for (u8 index = 0; auto& status : fbo_texture_pool_status_) {
if (status == FboTextureStatus::to_clear) {
Log::debug(Logger::opengl, "- Clearing texture at index {}", index);
attachTextureLayerToFbo(fbo_texture_array_id_, index);

gl::glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

Log::debug(Logger::opengl, "- Changing FBO texture status at index {} to 'unused'", index);
status = FboTextureStatus::unused;
}
}
Log::debug(Logger::opengl, "clearFbos() return");
// Log::debug(Logger::opengl, "clearFboTextures() call");
// for (u8 index = 0; auto& status : fbo_texture_pool_status_) {
// if (status == FboTextureStatus::to_clear) {
// // :WIP:
// // Log::debug(Logger::opengl, "- Clearing texture at index {}", index);
// // attachTextureLayerToFbo(fbo_texture_array_id_, index);
// // attachTextureToFbo(getFboTextureId(FboTextureType::vdp2_debug_layer));

// // gl::glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// // glClear(GL_COLOR_BUFFER_BIT);

// // Log::debug(Logger::opengl, "- Changing FBO texture status at index {} to 'unused'", index);
// // status = FboTextureStatus::unused;
// }
//}
// Log::debug(Logger::opengl, "clearFbos() return");
}

void Opengl::clearFboKeys() {
Log::debug(Logger::opengl, "clearFboKeys() call");
const auto count = std::erase_if(fbo_key_to_fbo_pool_index_, [this](const auto& item) {
auto const& [key, index] = item;
return fbo_pool_status_[index] != FboStatus::reuse;
});
Log::debug(Logger::opengl, "- {} FBO key(s) erased", count);
Log::debug(Logger::opengl, "clearFboKeys() return");
// Log::debug(Logger::opengl, "clearFboKeys() call");
// const auto count = std::erase_if(fbo_key_to_fbo_pool_index_, [this](const auto& item) {
// auto const& [key, index] = item;
// return fbo_pool_status_[index] != FboStatus::reuse;
// });
// Log::debug(Logger::opengl, "- {} FBO key(s) erased", count);
// Log::debug(Logger::opengl, "clearFboKeys() return");
}

void Opengl::bindFbo(const u32 fbo_id) {
Expand Down Expand Up @@ -907,7 +909,7 @@ auto Opengl::getRenderedBufferTextureId() const -> u32 { return getFboTextureId(

void Opengl::renderVdp1DebugOverlay() {
//----------- Pre render -----------//
attachTextureLayerToFbo(fbo_texture_array_id_, fbo_texture_type_to_layer_.at(FboTextureType::vdp1_debug_overlay));
attachTextureToFbo(getFboTextureId(FboTextureType::vdp1_debug_overlay));

// Viewport is the entire Saturn framebuffer
glViewport(0, 0, saturn_framebuffer_width, saturn_framebuffer_height);
Expand Down Expand Up @@ -971,7 +973,7 @@ void Opengl::renderVdp1DebugOverlay() {

void Opengl::renderVdp2DebugLayer(core::EmulatorContext& state) {
//----------- Pre render -----------//
attachTextureLayerToFbo(fbo_texture_array_id_, fbo_texture_type_to_layer_.at(FboTextureType::vdp2_debug_layer));
attachTextureToFbo(getFboTextureId(FboTextureType::vdp2_debug_layer));

// Viewport is the entire Saturn framebuffer
glViewport(0, 0, saturn_framebuffer_width, saturn_framebuffer_height);
Expand Down Expand Up @@ -1650,25 +1652,25 @@ void Opengl::initializeFbo() {
fbo_texture_pool_status_[i] = FboTextureStatus::unused;
}

// Generating a the main FBO used by the renderer.
fbo_ = generateFbo();

// Some textures are setup as a specific types in the FBO texture pool.
// Front and back buffers are switched every frame : one will be used as the last complete rendering by the GUI while
// the other will be rendered to.
// Textures not yet linked to a type will be used as a 'priority' type on demand when rendering.
fbo_texture_type_to_id_.try_emplace(FboTextureType::front_buffer, getAvailableFboTextureIndex());
fbo_texture_type_to_id_.try_emplace(FboTextureType::back_buffer, getAvailableFboTextureIndex());
fbo_texture_type_to_id_.try_emplace(FboTextureType::vdp1_debug_overlay, getAvailableFboTextureIndex());
fbo_texture_type_to_id_.try_emplace(FboTextureType::vdp2_debug_layer, getAvailableFboTextureIndex());
fbo_texture_type_to_id_.try_emplace(FboTextureType::front_buffer, fbo_texture_pool_[*getAvailableFboTextureIndex()]);
fbo_texture_type_to_id_.try_emplace(FboTextureType::back_buffer, fbo_texture_pool_[*getAvailableFboTextureIndex()]);
fbo_texture_type_to_id_.try_emplace(FboTextureType::vdp1_debug_overlay, fbo_texture_pool_[*getAvailableFboTextureIndex()]);
fbo_texture_type_to_id_.try_emplace(FboTextureType::vdp2_debug_layer, fbo_texture_pool_[*getAvailableFboTextureIndex()]);

currentRenderedBuffer(FboTextureType::front_buffer);

// Generating the main FBO used by the renderer.
fbo_ = generateFbo();

glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
}

auto Opengl::generateFbo() -> u32 {
auto fbo = u32{};
// auto texture = u32{};
if (is_legacy_opengl_) {
glGenFramebuffersEXT(1, &fbo);
} else {
Expand All @@ -1679,9 +1681,8 @@ auto Opengl::generateFbo() -> u32 {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

// Attaching the color texture to the fbo
const auto layer = 0;
attachTextureLayerToFbo(fbo_texture_array_id_, layer);
// Attaching the color texture currently used as framebuffer to the FBO.
attachTextureToFbo(getFboTextureId(currentRenderedBuffer()));

if (is_legacy_opengl_) {
const auto status = glCheckFramebufferStatusEXT(GLenum::GL_FRAMEBUFFER_EXT);
Expand Down Expand Up @@ -1743,6 +1744,14 @@ void Opengl::attachTextureLayerToFbo(const u32 texture_id, const u8 layer) {
}
}

void Opengl::attachTextureToFbo(const u32 texture_id) {
if (is_legacy_opengl_) {
glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_id, 0);
} else {
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_id, 0);
}
}

auto Opengl::calculateViewportPosAndSize() const -> std::tuple<u32, u32, u32, u32> {
const auto host_res = hostScreenResolution();
const auto host_ratio = static_cast<float>(host_res.width) / static_cast<float>(host_res.height);
Expand Down
15 changes: 14 additions & 1 deletion saturnin/src/video/opengl.h
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ class Opengl {

auto initializeTextureArray(const u32 width, const u32 height, const u32 depth) const -> u32;

auto getFboTextureLayer(const FboTextureType type) const -> u32 { return fbo_texture_type_to_layer_.at(type); };
auto getFboTextureId(const FboTextureType type) const -> u32 { return fbo_texture_type_to_id_.at(type); };

void switchRenderedBuffer();

Expand All @@ -711,6 +711,19 @@ class Opengl {

void attachTextureLayerToFbo(const u32 texture_id, const u8 layer);

////////////////////////////////////////////////////////////////////////////////////////////////////
/// \fn void Opengl::attachTextureToFbo(const u32 texture_id);
///
/// \brief Attachs a texture to the curently bound FBO.
///
/// \author Runik
/// \date 27/03/2024
///
/// \param texture_id Identifier for the texture.
////////////////////////////////////////////////////////////////////////////////////////////////////

void attachTextureToFbo(const u32 texture_id);

auto calculateViewportPosAndSize() const -> std::tuple<u32, u32, u32, u32>;

////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion saturnin/src/video/texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ SharedMutex Texture::storage_mutex_;
AddressToPlaneData Texture::address_to_plane_data_;

Texture::Texture(const VdpType vp,
const Layer layer,
const VdpLayer layer,
const u32 address,
const u8 color_count,
const u16 palette_number,
Expand Down
20 changes: 10 additions & 10 deletions saturnin/src/video/texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Texture {
/// Constructors / Destructors
Texture() = delete;
Texture(const VdpType vp,
const Layer layer,
const VdpLayer layer,
const u32 address,
const u8 color_count,
const u16 palette_number,
Expand Down Expand Up @@ -307,15 +307,15 @@ class Texture {
static SharedMutex storage_mutex_; ///< Used for multithreading access to the texture pool.
static AddressToPlaneData address_to_plane_data_; ///< Information describing the address to plane

VdpType vdp_type_{VdpType::not_set}; ///< What kind of VDP type is linked to this texture.
Layer layer_; ///< Layer linked to this texture.
u16 width_{}; ///< The texture width.
u16 height_{}; ///< The texture height.
bool is_discarded_{false}; ///< True if the texture is discarded.
bool is_recently_used_{true}; ///< True if the texture was used during the current frame.
// bool delete_on_gpu_{false}; ///< True to delete the texture on the GPU.
size_t key_{}; ///< The key of the part.
u32 api_handle_{}; ///< Handle to the graphics API.
VdpType vdp_type_{VdpType::not_set}; ///< What kind of VDP type is linked to this texture.
VdpLayer layer_; ///< Layer linked to this texture.
u16 width_{}; ///< The texture width.
u16 height_{}; ///< The texture height.
bool is_discarded_{false}; ///< True if the texture is discarded.
bool is_recently_used_{true}; ///< True if the texture was used during the current frame.
// bool delete_on_gpu_{false}; ///< True to delete the texture on the GPU.
size_t key_{}; ///< The key of the part.
u32 api_handle_{}; ///< Handle to the graphics API.

std::vector<u8> raw_data_{}; ///< Raw texture data.
};
Expand Down
72 changes: 36 additions & 36 deletions saturnin/src/video/vdp2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2450,44 +2450,44 @@ void Vdp2::populateRenderData() {
// bg_[util::toUnderlying(ScrollScreen::nbg2)] = {};
}

// clearRenderData(ScrollScreen::nbg3);
// if (canScrollScreenBeDisplayed(ScrollScreen::nbg3)) {
// if (isScreenDisplayed(ScrollScreen::nbg3)) {
// updateScrollScreenStatus(ScrollScreen::nbg3);
// if (getScreen(ScrollScreen::nbg3).priority_number != 0) { readScrollScreenData(ScrollScreen::nbg3); }
// }
// }

// WIP
if (canScrollScreenBeDisplayed(ScrollScreen::nbg3) && isScreenDisplayed(ScrollScreen::nbg3)) {
updateScrollScreenStatus(ScrollScreen::nbg3);
const auto isDirty = isCacheDirty(ScrollScreen::nbg3);
const auto priorityIsAboveZero = getScreen(ScrollScreen::nbg3).priority_number != 0;
if (isDirty && priorityIsAboveZero) {
discardCache(ScrollScreen::nbg3);
clearRenderData(ScrollScreen::nbg3);
readScrollScreenData(ScrollScreen::nbg3);
// Data must be reloaded. Passing the status as 'to_clear' suffice on this side.
modules_.opengl()->setFboStatus(getScreen(ScrollScreen::nbg3).priority_number,
ScrollScreen::nbg3,
FboStatus::to_clear);
}

if (!priorityIsAboveZero) {
// Clear previously used data.
modules_.opengl()->setFboStatus(ScrollScreen::nbg3, FboStatus::to_clear);
}

if (!isDirty && priorityIsAboveZero) {
// Reuse previous data.
modules_.opengl()->setFboStatus(getScreen(ScrollScreen::nbg3).priority_number,
ScrollScreen::nbg3,
FboStatus::reuse);
clearRenderData(ScrollScreen::nbg3);
if (canScrollScreenBeDisplayed(ScrollScreen::nbg3)) {
if (isScreenDisplayed(ScrollScreen::nbg3)) {
updateScrollScreenStatus(ScrollScreen::nbg3);
if (getScreen(ScrollScreen::nbg3).priority_number != 0) { readScrollScreenData(ScrollScreen::nbg3); }
}
} else {
// Clear previously used data.
modules_.opengl()->setFboStatus(ScrollScreen::nbg3, FboStatus::to_clear);
}

// WIP
//if (canScrollScreenBeDisplayed(ScrollScreen::nbg3) && isScreenDisplayed(ScrollScreen::nbg3)) {
// updateScrollScreenStatus(ScrollScreen::nbg3);
// const auto isDirty = isCacheDirty(ScrollScreen::nbg3);
// const auto priorityIsAboveZero = getScreen(ScrollScreen::nbg3).priority_number != 0;
// if (isDirty && priorityIsAboveZero) {
// discardCache(ScrollScreen::nbg3);
// clearRenderData(ScrollScreen::nbg3);
// readScrollScreenData(ScrollScreen::nbg3);
// // Data must be reloaded. Passing the status as 'to_clear' suffice on this side.
// modules_.opengl()->setFboStatus(getScreen(ScrollScreen::nbg3).priority_number,
// ScrollScreen::nbg3,
// FboStatus::to_clear);
// }

// if (!priorityIsAboveZero) {
// // Clear previously used data.
// modules_.opengl()->setFboStatus(ScrollScreen::nbg3, FboStatus::to_clear);
// }

// if (!isDirty && priorityIsAboveZero) {
// // Reuse previous data.
// modules_.opengl()->setFboStatus(getScreen(ScrollScreen::nbg3).priority_number,
// ScrollScreen::nbg3,
// FboStatus::reuse);
// }
//} else {
// // Clear previously used data.
// modules_.opengl()->setFboStatus(ScrollScreen::nbg3, FboStatus::to_clear);
//}
}
}

Expand Down

0 comments on commit 74bd226

Please sign in to comment.