hwr2: add g_wipeskiprender 1-frame workaround

This commit is contained in:
Eidolon 2023-02-20 21:27:21 -06:00
parent 158aaa6803
commit 1958394635
8 changed files with 58 additions and 55 deletions

View file

@ -690,6 +690,9 @@ static void D_Display(void)
ps_swaptime = I_GetPreciseTime(); ps_swaptime = I_GetPreciseTime();
I_FinishUpdate(); // page flip or blit buffer I_FinishUpdate(); // page flip or blit buffer
ps_swaptime = I_GetPreciseTime() - ps_swaptime; ps_swaptime = I_GetPreciseTime() - ps_swaptime;
// We should never do the HWR2 skip 3d drawing hack for more than 1 full draw.
g_wipeskiprender = false;
} }
} }

View file

@ -340,8 +340,8 @@ void F_WipeStartScreen(void)
return; return;
} }
#endif #endif
// wipe_scr_start = screens[3]; wipe_scr_start = screens[3];
// I_ReadScreen(wipe_scr_start); I_ReadScreen(wipe_scr_start);
I_FinishUpdateWipeStartScreen(); I_FinishUpdateWipeStartScreen();
#endif #endif
} }
@ -358,9 +358,9 @@ void F_WipeEndScreen(void)
return; return;
} }
#endif #endif
// wipe_scr_end = screens[4]; wipe_scr_end = screens[4];
// I_ReadScreen(wipe_scr_end); I_ReadScreen(wipe_scr_end);
// V_DrawBlock(0, 0, 0, vid.width, vid.height, wipe_scr_start); V_DrawBlock(0, 0, 0, vid.width, vid.height, wipe_scr_start);
I_FinishUpdateWipeEndScreen(); I_FinishUpdateWipeEndScreen();
#endif #endif
} }

View file

@ -30,7 +30,7 @@ class BlitRectPass final : public Pass
uint32_t output_width_ = 0; uint32_t output_width_ = 0;
uint32_t output_height_ = 0; uint32_t output_height_ = 0;
bool output_correct_aspect_ = false; bool output_correct_aspect_ = false;
bool output_clear_ = true; bool output_clear_ = false;
bool output_flip_ = false; bool output_flip_ = false;
rhi::Handle<rhi::RenderPass> render_pass_; rhi::Handle<rhi::RenderPass> render_pass_;
rhi::Handle<rhi::Buffer> quad_vbo_; rhi::Handle<rhi::Buffer> quad_vbo_;
@ -84,6 +84,8 @@ public:
output_correct_aspect_ = correct_aspect; output_correct_aspect_ = correct_aspect;
output_flip_ = flip; output_flip_ = flip;
} }
void clear_output(bool clear) noexcept { output_clear_ = clear; }
}; };
} // namespace srb2::hwr2 } // namespace srb2::hwr2

View file

@ -33,15 +33,10 @@ void FramebufferManager::prepass(Rhi& rhi)
// Destroy the framebuffer textures if they exist and the video size changed // Destroy the framebuffer textures if they exist and the video size changed
if (width_ != current_width || height_ != current_height) if (width_ != current_width || height_ != current_height)
{ {
if (main_colors_[0] != kNullHandle) if (main_color_ != kNullHandle)
{ {
rhi.destroy_texture(main_colors_[0]); rhi.destroy_texture(main_color_);
main_colors_[0] = kNullHandle; main_color_ = kNullHandle;
}
if (main_colors_[1] != kNullHandle)
{
rhi.destroy_texture(main_colors_[1]);
main_colors_[1] = kNullHandle;
} }
if (main_depth_ != kNullHandle) if (main_depth_ != kNullHandle)
{ {
@ -74,13 +69,9 @@ void FramebufferManager::prepass(Rhi& rhi)
height_ = current_height; height_ = current_height;
// Recreate the framebuffer textures // Recreate the framebuffer textures
if (main_colors_[0] == kNullHandle) if (main_color_ == kNullHandle)
{ {
main_colors_[0] = rhi.create_texture({TextureFormat::kRGBA, current_width, current_height}); main_color_ = rhi.create_texture({TextureFormat::kRGBA, current_width, current_height});
}
if (main_colors_[1] == kNullHandle)
{
main_colors_[1] = rhi.create_texture({TextureFormat::kRGBA, current_width, current_height});
} }
if (main_depth_ == kNullHandle) if (main_depth_ == kNullHandle)
{ {

View file

@ -22,12 +22,11 @@ namespace srb2::hwr2
class FramebufferManager final : public Pass class FramebufferManager final : public Pass
{ {
std::array<rhi::Handle<rhi::Texture>, 2> main_colors_; rhi::Handle<rhi::Texture> main_color_;
rhi::Handle<rhi::Renderbuffer> main_depth_; rhi::Handle<rhi::Renderbuffer> main_depth_;
std::array<rhi::Handle<rhi::Texture>, 2> post_colors_; std::array<rhi::Handle<rhi::Texture>, 2> post_colors_;
rhi::Handle<rhi::Texture> wipe_start_color_; rhi::Handle<rhi::Texture> wipe_start_color_;
rhi::Handle<rhi::Texture> wipe_end_color_; rhi::Handle<rhi::Texture> wipe_end_color_;
std::size_t main_index_ = 0;
std::size_t post_index_ = 0; std::size_t post_index_ = 0;
std::size_t width_ = 0; std::size_t width_ = 0;
std::size_t height_ = 0; std::size_t height_ = 0;
@ -42,9 +41,6 @@ public:
virtual void graphics(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx) override; virtual void graphics(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx) override;
virtual void postpass(rhi::Rhi& rhi) override; virtual void postpass(rhi::Rhi& rhi) override;
/// @brief Swap the current and previous main colors.
void swap_main() noexcept { main_index_ = main_index_ == 0 ? 1 : 0; }
/// @brief Swap the current and previous postprocess FB textures. Use between pass prepass phases to alternate. /// @brief Swap the current and previous postprocess FB textures. Use between pass prepass phases to alternate.
void swap_post() noexcept void swap_post() noexcept
{ {
@ -54,9 +50,8 @@ public:
void reset_post() noexcept { first_postprocess_ = true; } void reset_post() noexcept { first_postprocess_ = true; }
rhi::Handle<rhi::Texture> current_main_color() const noexcept { return main_colors_[main_index_]; } rhi::Handle<rhi::Texture> main_color() const noexcept { return main_color_; }
rhi::Handle<rhi::Renderbuffer> main_depth() const noexcept { return main_depth_; } rhi::Handle<rhi::Renderbuffer> main_depth() const noexcept { return main_depth_; }
rhi::Handle<rhi::Texture> previous_main_color() const noexcept { return main_colors_[1 - main_index_]; }
rhi::Handle<rhi::Texture> current_post_color() const noexcept { return post_colors_[post_index_]; } rhi::Handle<rhi::Texture> current_post_color() const noexcept { return post_colors_[post_index_]; }
@ -64,7 +59,7 @@ public:
{ {
if (first_postprocess_) if (first_postprocess_)
{ {
return current_main_color(); return main_color();
} }
return post_colors_[1 - post_index_]; return post_colors_[1 - post_index_];
}; };

View file

@ -150,11 +150,11 @@ static InternalPassData build_pass_manager()
"3d_prepare", "3d_prepare",
[framebuffer_manager](PassManager& mgr, Rhi&) [framebuffer_manager](PassManager& mgr, Rhi&)
{ {
const bool sw_enabled = rendermode == render_soft; const bool sw_enabled = rendermode == render_soft && gamestate != GS_NULL;
mgr.set_pass_enabled("software", sw_enabled); mgr.set_pass_enabled("software", sw_enabled);
mgr.set_pass_enabled("blit_sw_prepare", sw_enabled); mgr.set_pass_enabled("blit_sw_prepare", sw_enabled);
mgr.set_pass_enabled("blit_sw", sw_enabled); mgr.set_pass_enabled("blit_sw", sw_enabled && !g_wipeskiprender);
} }
); );
basic_rendering->insert("software", software_pass); basic_rendering->insert("software", software_pass);
@ -163,7 +163,7 @@ static InternalPassData build_pass_manager()
[blit_sw_pass, software_pass, framebuffer_manager](PassManager&, Rhi&) [blit_sw_pass, software_pass, framebuffer_manager](PassManager&, Rhi&)
{ {
blit_sw_pass->set_texture(software_pass->screen_texture(), vid.width, vid.height); blit_sw_pass->set_texture(software_pass->screen_texture(), vid.width, vid.height);
blit_sw_pass->set_output(framebuffer_manager->current_main_color(), vid.width, vid.height, false, false); blit_sw_pass->set_output(framebuffer_manager->main_color(), vid.width, vid.height, false, false);
} }
); );
basic_rendering->insert("blit_sw", blit_sw_pass); basic_rendering->insert("blit_sw", blit_sw_pass);
@ -172,7 +172,7 @@ static InternalPassData build_pass_manager()
"2d_prepare", "2d_prepare",
[twodee, framebuffer_manager, palette_manager](PassManager& mgr, Rhi&) [twodee, framebuffer_manager, palette_manager](PassManager& mgr, Rhi&)
{ {
twodee->output_ = framebuffer_manager->current_main_color(); twodee->output_ = framebuffer_manager->main_color();
twodee->palette_manager_ = palette_manager; twodee->palette_manager_ = palette_manager;
twodee->output_width_ = vid.width; twodee->output_width_ = vid.width;
twodee->output_height_ = vid.height; twodee->output_height_ = vid.height;
@ -180,35 +180,17 @@ static InternalPassData build_pass_manager()
); );
basic_rendering->insert("2d", twodee); basic_rendering->insert("2d", twodee);
// basic_rendering->insert(
// "pp_final_prepare",
// [](PassManager& mgr, Rhi&)
// {
// mgr.set_pass_enabled("pp_final_wipe_prepare", WipeInAction);
// mgr.set_pass_enabled("pp_final_wipe", WipeInAction);
// mgr.set_pass_enabled("pp_final_wipe_flip", WipeInAction);
// }
// );
basic_rendering->insert( basic_rendering->insert(
"pp_final_simple_blit_prepare", "pp_final_simple_blit_prepare",
[pp_simple_blit_pass, framebuffer_manager](PassManager&, Rhi&) [pp_simple_blit_pass, framebuffer_manager](PassManager&, Rhi&)
{ {
framebuffer_manager->swap_post(); framebuffer_manager->swap_post();
pp_simple_blit_pass->set_texture(framebuffer_manager->current_main_color(), vid.width, vid.height); pp_simple_blit_pass->set_texture(framebuffer_manager->main_color(), vid.width, vid.height);
pp_simple_blit_pass pp_simple_blit_pass
->set_output(framebuffer_manager->current_post_color(), vid.width, vid.height, false, true); ->set_output(framebuffer_manager->current_post_color(), vid.width, vid.height, false, true);
} }
); );
basic_rendering->insert("pp_final_simple_blit", pp_simple_blit_pass); basic_rendering->insert("pp_final_simple_blit", pp_simple_blit_pass);
// basic_rendering->insert(
// "pp_final_simple_blit_flip",
// [framebuffer_manager](PassManager&, Rhi&) { framebuffer_manager->swap_post(); }
// );
// basic_rendering->insert(
// "pp_final_wipe_flip",
// [framebuffer_manager](PassManager&, Rhi&) { framebuffer_manager->swap_post(); }
// );
basic_rendering->insert( basic_rendering->insert(
"screenshot_prepare", "screenshot_prepare",
@ -270,18 +252,33 @@ static InternalPassData build_pass_manager()
// Wipe End Screen Capture rendering // Wipe End Screen Capture rendering
auto wipe_capture_end_rendering = std::make_shared<PassManager>(); auto wipe_capture_end_rendering = std::make_shared<PassManager>();
auto wipe_end_blit = std::make_shared<BlitRectPass>(); auto wipe_end_blit = std::make_shared<BlitRectPass>();
auto wipe_end_blit_start_to_main = std::make_shared<BlitRectPass>();
wipe_capture_end_rendering->insert("resource_manager", resource_manager); wipe_capture_end_rendering->insert("resource_manager", resource_manager);
wipe_capture_end_rendering->insert("basic_rendering", basic_rendering); wipe_capture_end_rendering->insert("basic_rendering", basic_rendering);
wipe_capture_end_rendering->insert( wipe_capture_end_rendering->insert(
"wipe_capture_prepare", "wipe_capture_prepare",
[framebuffer_manager, wipe_end_blit](PassManager&, Rhi&) [framebuffer_manager, wipe_end_blit, wipe_end_blit_start_to_main](PassManager&, Rhi&)
{ {
wipe_end_blit->set_texture(framebuffer_manager->current_post_color(), vid.width, vid.height); wipe_end_blit->set_texture(framebuffer_manager->current_post_color(), vid.width, vid.height);
wipe_end_blit->set_output(framebuffer_manager->wipe_end_color(), vid.width, vid.height, false, true); wipe_end_blit->set_output(framebuffer_manager->wipe_end_color(), vid.width, vid.height, false, true);
wipe_end_blit_start_to_main->set_texture(
framebuffer_manager->wipe_start_color(),
vid.width,
vid.height
);
wipe_end_blit_start_to_main->set_output(
framebuffer_manager->main_color(),
vid.width,
vid.height,
false,
true
);
} }
); );
wipe_capture_end_rendering->insert("wipe_capture", wipe_end_blit); wipe_capture_end_rendering->insert("wipe_capture", wipe_end_blit);
wipe_capture_end_rendering->insert("wipe_end_blit_start_to_main", wipe_end_blit_start_to_main);
// Wipe rendering only runs the wipe shader on the start and end screens, and adds composite-present. // Wipe rendering only runs the wipe shader on the start and end screens, and adds composite-present.
auto wipe_rendering = std::make_shared<PassManager>(); auto wipe_rendering = std::make_shared<PassManager>();
@ -294,7 +291,7 @@ static InternalPassData build_pass_manager()
[pp_wipe_pass, framebuffer_manager, common_resources_manager](PassManager&, Rhi&) [pp_wipe_pass, framebuffer_manager, common_resources_manager](PassManager&, Rhi&)
{ {
framebuffer_manager->swap_post(); framebuffer_manager->swap_post();
Handle<Texture> start = framebuffer_manager->wipe_start_color(); Handle<Texture> start = framebuffer_manager->main_color();
Handle<Texture> end = framebuffer_manager->wipe_end_color(); Handle<Texture> end = framebuffer_manager->wipe_end_color();
if (g_wipereverse) if (g_wipereverse)
{ {

View file

@ -334,7 +334,7 @@ FUNCNORETURN static ATTRNORETURN void CorruptMapError(const char *msg)
{ {
sprintf(mapname, "ID %d", gamemap-1); sprintf(mapname, "ID %d", gamemap-1);
} }
CON_LogMessage("Map "); CON_LogMessage("Map ");
CON_LogMessage(mapname); CON_LogMessage(mapname);
CON_LogMessage(" is corrupt: "); CON_LogMessage(" is corrupt: ");
@ -7499,9 +7499,14 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// This is needed. Don't touch. // This is needed. Don't touch.
maptol = mapheaderinfo[gamemap-1]->typeoflevel; maptol = mapheaderinfo[gamemap-1]->typeoflevel;
// HWR2 skip 3d render draw hack to avoid losing the current wipe screen
g_wipeskiprender = true;
CON_Drawer(); // let the user know what we are going to do CON_Drawer(); // let the user know what we are going to do
I_FinishUpdate(); // page flip or blit buffer I_FinishUpdate(); // page flip or blit buffer
g_wipeskiprender = false;
// Reset the palette // Reset the palette
if (rendermode != render_none) if (rendermode != render_none)
V_SetPaletteLump("PLAYPAL"); V_SetPaletteLump("PLAYPAL");

View file

@ -336,9 +336,14 @@ void Y_IntermissionDrawer(void)
{ {
INT32 i, whiteplayer = MAXPLAYERS, x = 4, hilicol = highlightflags; INT32 i, whiteplayer = MAXPLAYERS, x = 4, hilicol = highlightflags;
// If we early return, skip drawing the 3D scene (software buffer) so it doesn't clobber the frame for the wipe
g_wipeskiprender = true;
if (intertype == int_none || rendermode == render_none) if (intertype == int_none || rendermode == render_none)
return; return;
g_wipeskiprender = false;
// the merge was kind of a mess, how does this work -- toast 171021 // the merge was kind of a mess, how does this work -- toast 171021
{ {
M_DrawMenuBackground(); M_DrawMenuBackground();
@ -810,7 +815,7 @@ void Y_StartIntermission(void)
if (!timer) if (!timer)
{ {
// Prevent a weird bug // Prevent a weird bug
timer = 1; timer = 1;
} }
else if (nump < 2 && !netgame) else if (nump < 2 && !netgame)
{ {
@ -945,6 +950,9 @@ void Y_VoteDrawer(void)
UINT8 selected[4]; UINT8 selected[4];
fixed_t rubyheight = 0; fixed_t rubyheight = 0;
// If we early return, skip drawing the 3D scene (software buffer) so it doesn't clobber the frame for the wipe
g_wipeskiprender = true;
if (rendermode == render_none) if (rendermode == render_none)
return; return;
@ -954,6 +962,8 @@ void Y_VoteDrawer(void)
if (!voteclient.loaded) if (!voteclient.loaded)
return; return;
g_wipeskiprender = false;
{ {
static angle_t rubyfloattime = 0; static angle_t rubyfloattime = 0;
rubyheight = FINESINE(rubyfloattime>>ANGLETOFINESHIFT); rubyheight = FINESINE(rubyfloattime>>ANGLETOFINESHIFT);