From 78ccaf361bea17548808b78dd4abd42b011c6690 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Thu, 31 Aug 2023 20:11:48 -0500 Subject: [PATCH] hwr2: upscale chosen resolution to desktop res --- src/f_wipe.cpp | 18 ++++--- src/hwr2/CMakeLists.txt | 2 + src/hwr2/hardware_state.hpp | 2 + src/hwr2/upscale_backbuffer.cpp | 87 +++++++++++++++++++++++++++++++++ src/hwr2/upscale_backbuffer.hpp | 39 +++++++++++++++ src/i_video_common.cpp | 13 ++++- src/sdl/i_video.cpp | 4 +- src/v_video.cpp | 3 -- 8 files changed, 155 insertions(+), 13 deletions(-) create mode 100644 src/hwr2/upscale_backbuffer.cpp create mode 100644 src/hwr2/upscale_backbuffer.hpp diff --git a/src/f_wipe.cpp b/src/f_wipe.cpp index 2831ee19f..39a7b2aa4 100644 --- a/src/f_wipe.cpp +++ b/src/f_wipe.cpp @@ -226,8 +226,6 @@ INT32 lastwipetic = 0; #define GENLEN 31 -static UINT8 *wipe_scr_start; //screen 3 -static UINT8 *wipe_scr_end; //screen 4 static UINT8 *wipe_scr; //screen 0 (main drawing) static UINT8 pallen; static fixed_t paldiv; @@ -385,8 +383,11 @@ void F_WipeStartScreen(void) hw_state->twodee_renderer->flush(*rhi, ctx, g_2d); - rhi::Rect copy_region = {0, 0, static_cast(vid.width), static_cast(vid.height)}; - rhi->copy_framebuffer_to_texture(ctx, hw_state->wipe_frames.start, copy_region, copy_region); + rhi::Rect dst_region = {0, 0, static_cast(vid.width), static_cast(vid.height)}; + rhi::TextureDetails backbuf_deets = rhi->get_texture_details(hw_state->backbuffer->color()); + dst_region.w = std::min(dst_region.w, backbuf_deets.width); + dst_region.h = std::min(dst_region.h, backbuf_deets.height); + rhi->copy_framebuffer_to_texture(ctx, hw_state->wipe_frames.start, dst_region, dst_region); I_FinishUpdate(); #endif @@ -425,10 +426,13 @@ void F_WipeEndScreen(void) hw_state->twodee_renderer->flush(*rhi, ctx, g_2d); - rhi::Rect copy_region = {0, 0, static_cast(vid.width), static_cast(vid.height)}; - rhi->copy_framebuffer_to_texture(ctx, hw_state->wipe_frames.end, copy_region, copy_region); + rhi::Rect dst_region = {0, 0, static_cast(vid.width), static_cast(vid.height)}; + rhi::TextureDetails backbuf_deets = rhi->get_texture_details(hw_state->backbuffer->color()); + dst_region.w = std::min(dst_region.w, backbuf_deets.width); + dst_region.h = std::min(dst_region.h, backbuf_deets.height); + rhi->copy_framebuffer_to_texture(ctx, hw_state->wipe_frames.end, dst_region, dst_region); - hw_state->blit_rect->set_output(copy_region.w, copy_region.h, false, true); + hw_state->blit_rect->set_output(dst_region.w, dst_region.h, false, true); rhi::TextureDetails start_deets = rhi->get_texture_details(hw_state->wipe_frames.start); hw_state->blit_rect->set_texture(hw_state->wipe_frames.start, start_deets.width, start_deets.height); hw_state->blit_rect->draw(*rhi, ctx); diff --git a/src/hwr2/CMakeLists.txt b/src/hwr2/CMakeLists.txt index eb7febdaf..fa068990f 100644 --- a/src/hwr2/CMakeLists.txt +++ b/src/hwr2/CMakeLists.txt @@ -27,4 +27,6 @@ target_sources(SRB2SDL2 PRIVATE twodee.hpp twodee_renderer.cpp twodee_renderer.hpp + upscale_backbuffer.cpp + upscale_backbuffer.hpp ) diff --git a/src/hwr2/hardware_state.hpp b/src/hwr2/hardware_state.hpp index bc42dcf08..86849f60c 100644 --- a/src/hwr2/hardware_state.hpp +++ b/src/hwr2/hardware_state.hpp @@ -17,6 +17,7 @@ #include "screen_capture.hpp" #include "software_screen_renderer.hpp" #include "twodee_renderer.hpp" +#include "upscale_backbuffer.hpp" namespace srb2::hwr2 { @@ -38,6 +39,7 @@ struct HardwareState std::unique_ptr wipe; std::unique_ptr blit_rect; std::unique_ptr screen_capture; + std::unique_ptr backbuffer; WipeFrames wipe_frames; }; diff --git a/src/hwr2/upscale_backbuffer.cpp b/src/hwr2/upscale_backbuffer.cpp new file mode 100644 index 000000000..0d3666e5c --- /dev/null +++ b/src/hwr2/upscale_backbuffer.cpp @@ -0,0 +1,87 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by Ronald "Eidolon" Kinard +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#include "upscale_backbuffer.hpp" + +#include "../i_video.h" + +using namespace srb2; +using namespace srb2::rhi; +using namespace srb2::hwr2; + +UpscaleBackbuffer::UpscaleBackbuffer() = default; +UpscaleBackbuffer::UpscaleBackbuffer(UpscaleBackbuffer&&) = default; +UpscaleBackbuffer::~UpscaleBackbuffer() = default; +UpscaleBackbuffer& UpscaleBackbuffer::operator=(UpscaleBackbuffer&&) = default; + +static bool size_equal(Rhi& rhi, Handle tex, uint32_t width, uint32_t height) +{ + TextureDetails deets = rhi.get_texture_details(tex); + return deets.width == width && deets.height == height; +} + +void UpscaleBackbuffer::begin_pass(Rhi& rhi, Handle ctx) +{ + uint32_t vid_width = static_cast(vid.width); + uint32_t vid_height = static_cast(vid.height); + + bool remake = false; + if (!color_ || !size_equal(rhi, color_, vid_width, vid_height)) + { + remake = true; + } + + if (remake) + { + if (color_) + { + rhi.destroy_texture(color_); + color_ = kNullHandle; + } + if (depth_) + { + rhi.destroy_renderbuffer(depth_); + depth_ = kNullHandle; + } + + TextureDesc color_tex {}; + color_tex.format = TextureFormat::kRGBA; + color_tex.width = vid_width; + color_tex.height = vid_height; + color_tex.u_wrap = TextureWrapMode::kClamp; + color_tex.v_wrap = TextureWrapMode::kClamp; + color_ = rhi.create_texture(color_tex); + + RenderbufferDesc depth_tex {}; + depth_tex.width = vid_width; + depth_tex.height = vid_height; + + depth_ = rhi.create_renderbuffer(depth_tex); + } + + if (!renderpass_) + { + RenderPassDesc desc {}; + desc.use_depth_stencil = true; + desc.color_load_op = AttachmentLoadOp::kLoad; + desc.color_store_op = AttachmentStoreOp::kStore; + desc.depth_load_op = AttachmentLoadOp::kLoad; + desc.depth_store_op = AttachmentStoreOp::kStore; + desc.stencil_load_op = AttachmentLoadOp::kLoad; + desc.stencil_store_op = AttachmentStoreOp::kStore; + renderpass_ = rhi.create_render_pass(desc); + } + + RenderPassBeginInfo begin_info {}; + begin_info.render_pass = renderpass_; + begin_info.clear_color = {0, 0, 0, 1}; + begin_info.color_attachment = color_; + begin_info.depth_stencil_attachment = depth_; + rhi.begin_render_pass(ctx, begin_info); +} diff --git a/src/hwr2/upscale_backbuffer.hpp b/src/hwr2/upscale_backbuffer.hpp new file mode 100644 index 000000000..d7b34a276 --- /dev/null +++ b/src/hwr2/upscale_backbuffer.hpp @@ -0,0 +1,39 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by Ronald "Eidolon" Kinard +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef __SRB2_HWR2_UPSCALE_BACKBUFFER_HPP__ +#define __SRB2_HWR2_UPSCALE_BACKBUFFER_HPP__ + +#include "../rhi/rhi.hpp" + +namespace srb2::hwr2 +{ + +class UpscaleBackbuffer +{ + rhi::Handle color_; + rhi::Handle depth_; + rhi::Handle renderpass_; + +public: + UpscaleBackbuffer(); + UpscaleBackbuffer(const UpscaleBackbuffer&) = delete; + UpscaleBackbuffer(UpscaleBackbuffer&&); + ~UpscaleBackbuffer(); + + UpscaleBackbuffer& operator=(const UpscaleBackbuffer&) = delete; + UpscaleBackbuffer& operator=(UpscaleBackbuffer&&); + + void begin_pass(rhi::Rhi& rhi, rhi::Handle ctx); + rhi::Handle color() const noexcept { return color_; } +}; + +} // namespace srb2::hwr2 + +#endif // __SRB2_HWR2_UPSCALE_BACKBUFFER_HPP__ diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp index 4a493843c..54ee9c876 100644 --- a/src/i_video_common.cpp +++ b/src/i_video_common.cpp @@ -79,6 +79,7 @@ static void reset_hardware_state(Rhi* rhi) g_hw_state.wipe = std::make_unique(); g_hw_state.blit_rect = std::make_unique(); g_hw_state.screen_capture = std::make_unique(); + g_hw_state.backbuffer = std::make_unique(); g_hw_state.wipe_frames = {}; g_last_known_rhi = rhi; @@ -278,8 +279,9 @@ void I_StartDisplayUpdate(void) } rhi::Handle ctx = rhi->begin_graphics(); + HardwareState* hw_state = &g_hw_state; - rhi->begin_default_render_pass(ctx, false); + hw_state->backbuffer->begin_pass(*rhi, ctx); g_main_graphics_context = ctx; @@ -318,6 +320,15 @@ void I_FinishUpdate(void) // better hope the drawing code left the context in a render pass, I guess g_hw_state.twodee_renderer->flush(*rhi, ctx, g_2d); rhi->end_render_pass(ctx); + + rhi->begin_default_render_pass(ctx, true); + + // Upscale draw the backbuffer (with postprocessing maybe?) + g_hw_state.blit_rect->set_output(vid.realwidth, vid.realheight, true, true); + g_hw_state.blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); + g_hw_state.blit_rect->draw(*rhi, ctx); + rhi->end_render_pass(ctx); + rhi->end_graphics(ctx); g_main_graphics_context = kNullHandle; diff --git a/src/sdl/i_video.cpp b/src/sdl/i_video.cpp index 0839a312f..cd5ba1848 100644 --- a/src/sdl/i_video.cpp +++ b/src/sdl/i_video.cpp @@ -190,7 +190,7 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool if (fullscreen) { wasfullscreen = SDL_TRUE; - SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); + SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); } else // windowed mode { @@ -217,7 +217,7 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool SDL_SetWindowSize(window, width, height); if (fullscreen) { - SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); + SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); } } diff --git a/src/v_video.cpp b/src/v_video.cpp index f69d505b5..e5bc68a3f 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -3207,9 +3207,6 @@ void VID_DisplaySoftwareScreen() // Misnomer; this just uploads the screen to the software indexed screen texture hw_state->software_screen_renderer->draw(*rhi, ctx); - rhi->end_render_pass(ctx); - rhi->begin_default_render_pass(ctx, false); - const int screens = std::clamp(r_splitscreen + 1, 1, MAXSPLITSCREENPLAYERS); hw_state->blit_postimg_screens->set_num_screens(screens); hw_state->blit_postimg_screens->set_target(static_cast(vid.width), static_cast(vid.height));