From 356e3317df7a802ae0a9de1ed9959e51ef06cbb8 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sun, 2 Apr 2023 19:37:45 -0500 Subject: [PATCH] hwr2: Do postimg in hardware Depends on updated shaders --- src/core/static_vec.hpp | 6 + src/d_main.c | 3 - src/hwr2/CMakeLists.txt | 2 + src/hwr2/pass_blit_postimg_screens.cpp | 253 +++++++++++++++++++++++++ src/hwr2/pass_blit_postimg_screens.hpp | 101 ++++++++++ src/i_video_common.cpp | 74 +++++++- src/rhi/gl3_core/gl3_core_rhi.cpp | 24 +++ src/rhi/rhi.cpp | 19 ++ src/rhi/rhi.hpp | 26 ++- src/sdl/rhi_gl3_core_platform.cpp | 2 + src/v_video.cpp | 190 ------------------- src/v_video.h | 2 - 12 files changed, 496 insertions(+), 206 deletions(-) create mode 100644 src/hwr2/pass_blit_postimg_screens.cpp create mode 100644 src/hwr2/pass_blit_postimg_screens.hpp diff --git a/src/core/static_vec.hpp b/src/core/static_vec.hpp index 823469649..7a7164789 100644 --- a/src/core/static_vec.hpp +++ b/src/core/static_vec.hpp @@ -130,6 +130,12 @@ public: } } + void clear() + { + arr_ = {{}}; + size_ = 0; + } + constexpr T* begin() noexcept { return &arr_[0]; } constexpr const T* begin() const noexcept { return cbegin(); } diff --git a/src/d_main.c b/src/d_main.c index e52ad6a61..875c97343 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -603,9 +603,6 @@ static void D_Display(void) for (i = 0; i <= r_splitscreen; i++) { R_ApplyViewMorph(i); - - if (postimgtype[i]) - V_DoPostProcessor(i, postimgtype[i], postimgparam[i]); } } diff --git a/src/hwr2/CMakeLists.txt b/src/hwr2/CMakeLists.txt index 0500c9ee4..cef776505 100644 --- a/src/hwr2/CMakeLists.txt +++ b/src/hwr2/CMakeLists.txt @@ -1,4 +1,6 @@ target_sources(SRB2SDL2 PRIVATE + pass_blit_postimg_screens.cpp + pass_blit_postimg_screens.hpp pass_blit_rect.cpp pass_blit_rect.hpp pass_imgui.cpp diff --git a/src/hwr2/pass_blit_postimg_screens.cpp b/src/hwr2/pass_blit_postimg_screens.cpp new file mode 100644 index 000000000..e0c6c09ed --- /dev/null +++ b/src/hwr2/pass_blit_postimg_screens.cpp @@ -0,0 +1,253 @@ +// 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 "pass_blit_postimg_screens.hpp" + +#include +#include +#include +#include +#include + +#include "../p_tick.h" +#include "../i_time.h" +#include "../screen.h" + +using namespace srb2; +using namespace srb2::hwr2; +using namespace srb2::rhi; + +namespace +{ +struct BlitVertex +{ + float x = 0.f; + float y = 0.f; + float z = 0.f; + float u = 0.f; + float v = 0.f; +}; +} // namespace + +static const PipelineDesc kPostimgPipelineDesc = +{ + PipelineProgram::kPostimg, + {{{sizeof(BlitVertex)}}, {{VertexAttributeName::kPosition, 0, 0}, {VertexAttributeName::kTexCoord0, 0, 12}}}, + {{{{UniformName::kTime, UniformName::kProjection, UniformName::kModelView, UniformName::kTexCoord0Transform, UniformName::kTexCoord0Min, UniformName::kTexCoord0Max, UniformName::kPostimgWater, UniformName::kPostimgHeat}}}}, + {{SamplerName::kSampler0}}, + std::nullopt, + {std::nullopt, {true, true, true, true}}, + PrimitiveType::kTriangles, + CullMode::kNone, + FaceWinding::kCounterClockwise, + {0.0, 0.0, 0.0, 1.0} +}; + +static const PipelineDesc kPostimgIndexedPipelineDesc = +{ + PipelineProgram::kPostimg, + {{{sizeof(BlitVertex)}}, {{VertexAttributeName::kPosition, 0, 0}, {VertexAttributeName::kTexCoord0, 0, 12}}}, + {{{{UniformName::kTime, UniformName::kProjection, UniformName::kModelView, UniformName::kTexCoord0Transform, UniformName::kTexCoord0Min, UniformName::kTexCoord0Max, UniformName::kPostimgWater, UniformName::kPostimgHeat}}}}, + {{SamplerName::kSampler0, SamplerName::kSampler1}}, + std::nullopt, + {std::nullopt, {true, true, true, true}}, + PrimitiveType::kTriangles, + CullMode::kNone, + FaceWinding::kCounterClockwise, + {0.0, 0.0, 0.0, 1.0} +}; + +static const BlitVertex kVerts[] = + {{-.5f, -.5f, 0.f, 0.f, 0.f}, {.5f, -.5f, 0.f, 1.f, 0.f}, {-.5f, .5f, 0.f, 0.f, 1.f}, {.5f, .5f, 0.f, 1.f, 1.f}}; + +static const uint16_t kIndices[] = {0, 1, 2, 1, 3, 2}; + +BlitPostimgScreens::BlitPostimgScreens(const std::shared_ptr& palette_mgr) + : palette_mgr_(palette_mgr) +{ +} + +BlitPostimgScreens::~BlitPostimgScreens() = default; + +void BlitPostimgScreens::prepass(Rhi& rhi) +{ + if (!renderpass_) + { + renderpass_ = rhi.create_render_pass( + { + false, + AttachmentLoadOp::kClear, + AttachmentStoreOp::kStore, + AttachmentLoadOp::kDontCare, + AttachmentStoreOp::kDontCare, + AttachmentLoadOp::kDontCare, + AttachmentStoreOp::kDontCare + } + ); + } + + if (!pipeline_) + { + pipeline_ = rhi.create_pipeline(kPostimgPipelineDesc); + } + + if (!indexed_pipeline_) + { + indexed_pipeline_ = rhi.create_pipeline(kPostimgIndexedPipelineDesc); + } + + if (!quad_vbo_) + { + quad_vbo_ = rhi.create_buffer({sizeof(kVerts), BufferType::kVertexBuffer, BufferUsage::kImmutable}); + upload_quad_buffer_ = true; + } + + if (!quad_ibo_) + { + quad_ibo_ = rhi.create_buffer({sizeof(kIndices), BufferType::kIndexBuffer, BufferUsage::kImmutable}); + upload_quad_buffer_ = true; + } + + screen_data_.clear(); +} + +static Rect get_screen_viewport(uint32_t screen, uint32_t screens, uint32_t w, uint32_t h) +{ + switch (screens) + { + case 1: + return {0, 0, w, h}; + case 2: + return {0, screen == 1 ? (static_cast(h) / 2) : 0, w, (h / 2)}; + default: + switch (screen) + { + case 2: + return {0, 0, w / 2, h / 2}; + case 3: + return {static_cast(w) / 2, 0, w / 2, h / 2}; + case 0: + return {0, static_cast(h) / 2, w / 2, h / 2}; + case 1: + return {static_cast(w) / 2, static_cast(h) / 2, w / 2, h / 2}; + } + } + return {0, 0, w, h}; +} + +void BlitPostimgScreens::transfer(Rhi& rhi, Handle ctx) +{ + // Upload needed buffers + if (upload_quad_buffer_) + { + rhi.update_buffer(ctx, quad_vbo_, 0, tcb::as_bytes(tcb::span(kVerts))); + rhi.update_buffer(ctx, quad_ibo_, 0, tcb::as_bytes(tcb::span(kIndices))); + upload_quad_buffer_ = false; + } + + for (uint32_t i = 0; i < screens_; i++) + { + BlitPostimgScreens::ScreenConfig& screen_config = screen_configs_[i]; + BlitPostimgScreens::ScreenData data {}; + + if (screen_config.indexed) + { + data.pipeline = indexed_pipeline_; + } + else + { + data.pipeline = pipeline_; + } + + VertexAttributeBufferBinding vertex_bindings[] = {{0, quad_vbo_}}; + TextureBinding sampler_bindings[] = + { + {SamplerName::kSampler0, screen_config.source}, + {SamplerName::kSampler1, palette_mgr_->palette()} + }; + + data.binding_set = rhi.create_binding_set( + ctx, + data.pipeline, + { + vertex_bindings, + tcb::span(sampler_bindings, screen_config.indexed ? 2 : 1) + } + ); + + glm::mat4 projection = glm::scale(glm::identity(), glm::vec3(2.f, -2.f, 1.f)); + glm::mat4 modelview = glm::identity(); + + glm::vec2 flip_mirror_uv_displace {0.0, 0.0}; + if (screen_config.post.mirror) + { + flip_mirror_uv_displace.x = 1 - (1 - screen_config.uv_size.x); + } + if (screen_config.post.flip) + { + flip_mirror_uv_displace.y = 1 - (1 - screen_config.uv_size.y); + } + + glm::mat3 texcoord_transform = + { + glm::vec3(screen_config.uv_size.x * (screen_config.post.mirror ? -1 : 1), 0.0, 0.0), + glm::vec3(0.0, screen_config.uv_size.y * (screen_config.post.flip ? -1 : 1), 0.0), + glm::vec3(screen_config.uv_offset + flip_mirror_uv_displace, 1.0) + }; + + glm::vec2 texcoord_min = screen_config.uv_offset; + glm::vec2 texcoord_max = screen_config.uv_offset + screen_config.uv_size; + + UniformVariant uniforms[] = + { + FixedToFloat(g_time.timefrac) + leveltime, + projection, + modelview, + texcoord_transform, + texcoord_min, + texcoord_max, + screen_config.post.water, + screen_config.post.heat + }; + + data.uniform_set = rhi.create_uniform_set(ctx, {uniforms}); + + screen_data_[i] = std::move(data); + } +} + +void BlitPostimgScreens::graphics(Rhi& rhi, Handle ctx) +{ + if (target_) + { + rhi.begin_render_pass(ctx, {renderpass_, target_, std::nullopt, glm::vec4(0.0, 0.0, 0.0, 1.0)}); + } + else + { + rhi.begin_default_render_pass(ctx, true); + } + + for (uint32_t i = 0; i < screens_; i++) + { + BlitPostimgScreens::ScreenData& data = screen_data_[i]; + + rhi.bind_pipeline(ctx, data.pipeline); + rhi.set_viewport(ctx, get_screen_viewport(i, screens_, target_ ? target_width_ : vid.width, target_ ? target_height_ : vid.height)); + rhi.bind_uniform_set(ctx, 0, data.uniform_set); + rhi.bind_binding_set(ctx, data.binding_set); + rhi.bind_index_buffer(ctx, quad_ibo_); + rhi.draw_indexed(ctx, 6, 0); + } + + rhi.end_render_pass(ctx); +} + +void BlitPostimgScreens::postpass(Rhi& rhi) +{ +} diff --git a/src/hwr2/pass_blit_postimg_screens.hpp b/src/hwr2/pass_blit_postimg_screens.hpp new file mode 100644 index 000000000..47893476a --- /dev/null +++ b/src/hwr2/pass_blit_postimg_screens.hpp @@ -0,0 +1,101 @@ +// 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_PASS_BLIT_POSTIMG_SCREENS__ +#define __SRB2_HWR2_PASS_BLIT_POSTIMG_SCREENS__ + +#include +#include + +#include + +#include "../rhi/rhi.hpp" +#include "../doomdef.h" +#include "pass.hpp" +#include "pass_resource_managers.hpp" + +namespace srb2::hwr2 +{ + +class BlitPostimgScreens : public Pass +{ +public: + struct PostImgConfig + { + bool water; + bool heat; + bool flip; + bool mirror; + }; + + struct ScreenConfig + { + rhi::Handle source; + bool indexed = false; + glm::vec2 uv_offset {}; + glm::vec2 uv_size {}; + PostImgConfig post; + }; + +private: + struct ScreenData + { + rhi::Handle pipeline; + rhi::Handle binding_set; + rhi::Handle uniform_set; + }; + + rhi::Handle pipeline_; + rhi::Handle indexed_pipeline_; + rhi::Handle renderpass_; + rhi::Handle quad_vbo_; + rhi::Handle quad_ibo_; + bool upload_quad_buffer_; + + uint32_t screens_; + std::array screen_configs_; + srb2::StaticVec screen_data_; + rhi::Handle target_; + uint32_t target_width_; + uint32_t target_height_; + + std::shared_ptr palette_mgr_; + +public: + BlitPostimgScreens(const std::shared_ptr& palette_mgr); + virtual ~BlitPostimgScreens(); + + virtual void prepass(rhi::Rhi& rhi) override; + virtual void transfer(rhi::Rhi& rhi, rhi::Handle ctx) override; + virtual void graphics(rhi::Rhi& rhi, rhi::Handle ctx) override; + virtual void postpass(rhi::Rhi& rhi) override; + + void set_num_screens(uint32_t screens) noexcept + { + SRB2_ASSERT(screens > 0 && screens <= MAXSPLITSCREENPLAYERS); + screens_ = screens; + } + + void set_screen(uint32_t screen_index, const ScreenConfig& config) noexcept + { + SRB2_ASSERT(screen_index < MAXSPLITSCREENPLAYERS); + screen_configs_[screen_index] = config; + } + + void set_target(rhi::Handle target, uint32_t width, uint32_t height) noexcept + { + target_ = target; + target_width_ = width; + target_height_ = height; + } +}; + +}; // namespace srb2::hwr2 + +#endif // __SRB2_HWR2_PASS_BLIT_POSTIMG_SCREENS__ diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp index a0802e904..80379ad41 100644 --- a/src/i_video_common.cpp +++ b/src/i_video_common.cpp @@ -17,6 +17,7 @@ #include "cxxutil.hpp" #include "f_finale.h" +#include "hwr2/pass_blit_postimg_screens.hpp" #include "hwr2/pass_blit_rect.hpp" #include "hwr2/pass_imgui.hpp" #include "hwr2/pass_manager.hpp" @@ -205,7 +206,7 @@ static InternalPassData build_pass_manager() auto basic_rendering = std::make_shared(); auto software_pass = std::make_shared(); - auto blit_sw_pass = std::make_shared(palette_manager, true); + auto blit_postimg_screens = std::make_shared(palette_manager); auto twodee = std::make_shared(); twodee->flat_manager_ = flat_texture_manager; twodee->data_ = make_twodee_pass_data(); @@ -222,20 +223,77 @@ static InternalPassData build_pass_manager() const bool sw_enabled = rendermode == render_soft && gamestate != GS_NULL; mgr.set_pass_enabled("software", sw_enabled); - mgr.set_pass_enabled("blit_sw_prepare", sw_enabled); - mgr.set_pass_enabled("blit_sw", sw_enabled && !g_wipeskiprender); + mgr.set_pass_enabled("blit_postimg_screens_prepare", sw_enabled); + mgr.set_pass_enabled("blit_postimg_screens", sw_enabled && !g_wipeskiprender); } ); basic_rendering->insert("software", software_pass); basic_rendering->insert( - "blit_sw_prepare", - [blit_sw_pass, software_pass, framebuffer_manager](PassManager&, Rhi&) + "blit_postimg_screens_prepare", + [blit_postimg_screens, software_pass, framebuffer_manager](PassManager&, Rhi&) { - blit_sw_pass->set_texture(software_pass->screen_texture(), vid.width, vid.height); - blit_sw_pass->set_output(framebuffer_manager->main_color(), vid.width, vid.height, false, false); + const bool sw_enabled = rendermode == render_soft && gamestate != GS_NULL; + const int screens = std::clamp(r_splitscreen + 1, 1, MAXSPLITSCREENPLAYERS); + + blit_postimg_screens->set_num_screens(screens); + for (int i = 0; i < screens; i++) + { + if (sw_enabled) + { + glm::vec2 uv_offset {0.f, 0.f}; + glm::vec2 uv_size {1.f, 1.f}; + + if (screens > 2) + { + uv_size = glm::vec2(.5f, .5f); + switch (i) + { + case 0: + uv_offset = glm::vec2(0.f, 0.f); + break; + case 1: + uv_offset = glm::vec2(.5f, 0.f); + break; + case 2: + uv_offset = glm::vec2(0.f, .5f); + break; + case 3: + uv_offset = glm::vec2(.5f, .5f); + break; + } + } + else if (screens > 1) + { + uv_size = glm::vec2(1.0, 0.5); + if (i == 1) + { + uv_offset = glm::vec2(0.f, .5f); + } + } + + // "You should probably never have more than 3 levels of indentation" -- Eidolon, the author of this + + blit_postimg_screens->set_screen( + i, + { + software_pass->screen_texture(), + true, + uv_offset, + uv_size, + { + postimgtype[i] == postimg_water, + postimgtype[i] == postimg_heat, + postimgtype[i] == postimg_flip, + postimgtype[i] == postimg_mirror + } + } + ); + } + } + blit_postimg_screens->set_target(framebuffer_manager->main_color(), vid.width, vid.height); } ); - basic_rendering->insert("blit_sw", blit_sw_pass); + basic_rendering->insert("blit_postimg_screens", blit_postimg_screens); basic_rendering->insert( "2d_prepare", diff --git a/src/rhi/gl3_core/gl3_core_rhi.cpp b/src/rhi/gl3_core/gl3_core_rhi.cpp index 8e10545f6..ce3df3b05 100644 --- a/src/rhi/gl3_core/gl3_core_rhi.cpp +++ b/src/rhi/gl3_core/gl3_core_rhi.cpp @@ -348,8 +348,16 @@ constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) return "u_projection"; case rhi::UniformName::kTexCoord0Transform: return "u_texcoord0_transform"; + case rhi::UniformName::kTexCoord0Min: + return "u_texcoord0_min"; + case rhi::UniformName::kTexCoord0Max: + return "u_texcoord0_max"; case rhi::UniformName::kTexCoord1Transform: return "u_texcoord1_transform"; + case rhi::UniformName::kTexCoord1Min: + return "u_texcoord1_min"; + case rhi::UniformName::kTexCoord1Max: + return "u_texcoord1_max"; case rhi::UniformName::kSampler0IsIndexedAlpha: return "u_sampler0_is_indexed_alpha"; case rhi::UniformName::kSampler1IsIndexedAlpha: @@ -370,6 +378,10 @@ constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) return "u_wipe_colorize_mode"; case rhi::UniformName::kWipeEncoreSwizzle: return "u_wipe_encore_swizzle"; + case rhi::UniformName::kPostimgWater: + return "u_postimg_water"; + case rhi::UniformName::kPostimgHeat: + return "u_postimg_heat"; default: return nullptr; } @@ -387,8 +399,16 @@ constexpr const char* map_uniform_enable_define(rhi::UniformName name) return "ENABLE_U_MODELVIEW"; case rhi::UniformName::kTexCoord0Transform: return "ENABLE_U_TEXCOORD0_TRANSFORM"; + case rhi::UniformName::kTexCoord0Min: + return "ENABLE_U_TEXCOORD0_MIN"; + case rhi::UniformName::kTexCoord0Max: + return "ENABLE_U_TEXCOORD0_MAX"; case rhi::UniformName::kTexCoord1Transform: return "ENABLE_U_TEXCOORD1_TRANSFORM"; + case rhi::UniformName::kTexCoord1Min: + return "ENABLE_U_TEXCOORD1_MIN"; + case rhi::UniformName::kTexCoord1Max: + return "ENABLE_U_TEXCOORD1_MAX"; case rhi::UniformName::kSampler0IsIndexedAlpha: return "ENABLE_U_SAMPLER0_IS_INDEXED_ALPHA"; case rhi::UniformName::kSampler1IsIndexedAlpha: @@ -409,6 +429,10 @@ constexpr const char* map_uniform_enable_define(rhi::UniformName name) return "ENABLE_U_WIPE_COLORIZE_MODE"; case rhi::UniformName::kWipeEncoreSwizzle: return "ENABLE_U_WIPE_ENCORE_SWIZZLE"; + case rhi::UniformName::kPostimgWater: + return "ENABLE_U_POSTIMG_WATER"; + case rhi::UniformName::kPostimgHeat: + return "ENABLE_U_POSTIMG_HEAT"; default: return nullptr; } diff --git a/src/rhi/rhi.cpp b/src/rhi/rhi.cpp index 36c3c7c8e..d11f4440b 100644 --- a/src/rhi/rhi.cpp +++ b/src/rhi/rhi.cpp @@ -50,6 +50,23 @@ const ProgramRequirements srb2::rhi::kProgramRequirementsPostprocessWipe = { {UniformName::kWipeEncoreSwizzle, true}}}}}, ProgramSamplerRequirements {{{SamplerName::kSampler0, true}, {SamplerName::kSampler1, true}, {SamplerName::kSampler2, true}}}}; +const ProgramRequirements srb2::rhi::kProgramRequirementsPostimg = { + ProgramVertexInputRequirements { + {ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, + ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, true}}}, + ProgramUniformRequirements { + {{ + {UniformName::kTime, true}, + {UniformName::kProjection, true}, + {UniformName::kModelView, true}, + {UniformName::kTexCoord0Transform, true}, + {UniformName::kTexCoord0Min, true}, + {UniformName::kTexCoord0Max, true}, + {UniformName::kPostimgWater, true}, + {UniformName::kPostimgHeat, true}}}}, + ProgramSamplerRequirements {{{SamplerName::kSampler0, true}, {SamplerName::kSampler1, false}}} +}; + const ProgramRequirements& rhi::program_requirements_for_program(PipelineProgram program) noexcept { switch (program) @@ -60,6 +77,8 @@ const ProgramRequirements& rhi::program_requirements_for_program(PipelineProgram return kProgramRequirementsUnshadedPaletted; case PipelineProgram::kPostprocessWipe: return kProgramRequirementsPostprocessWipe; + case PipelineProgram::kPostimg: + return kProgramRequirementsPostimg; default: std::terminate(); } diff --git a/src/rhi/rhi.hpp b/src/rhi/rhi.hpp index 3fb405119..f947fa201 100644 --- a/src/rhi/rhi.hpp +++ b/src/rhi/rhi.hpp @@ -171,7 +171,8 @@ enum class PipelineProgram { kUnshaded, kUnshadedPaletted, - kPostprocessWipe + kPostprocessWipe, + kPostimg }; enum class BufferType @@ -201,7 +202,11 @@ enum class UniformName kModelView, kProjection, kTexCoord0Transform, + kTexCoord0Min, + kTexCoord0Max, kTexCoord1Transform, + kTexCoord1Min, + kTexCoord1Max, kSampler0IsIndexedAlpha, kSampler1IsIndexedAlpha, kSampler2IsIndexedAlpha, @@ -211,7 +216,9 @@ enum class UniformName kSampler2Size, kSampler3Size, kWipeColorizeMode, - kWipeEncoreSwizzle + kWipeEncoreSwizzle, + kPostimgWater, + kPostimgHeat }; enum class SamplerName @@ -277,6 +284,7 @@ struct ProgramRequirements extern const ProgramRequirements kProgramRequirementsUnshaded; extern const ProgramRequirements kProgramRequirementsUnshadedPaletted; extern const ProgramRequirements kProgramRequirementsPostprocessWipe; +extern const ProgramRequirements kProgramRequirementsPostimg; const ProgramRequirements& program_requirements_for_program(PipelineProgram program) noexcept; @@ -311,8 +319,16 @@ inline constexpr const UniformFormat uniform_format(UniformName name) noexcept return UniformFormat::kMat4; case UniformName::kTexCoord0Transform: return UniformFormat::kMat3; + case UniformName::kTexCoord0Min: + return UniformFormat::kFloat2; + case UniformName::kTexCoord0Max: + return UniformFormat::kFloat2; case UniformName::kTexCoord1Transform: return UniformFormat::kMat3; + case UniformName::kTexCoord1Min: + return UniformFormat::kFloat2; + case UniformName::kTexCoord1Max: + return UniformFormat::kFloat2; case UniformName::kSampler0IsIndexedAlpha: return UniformFormat::kInt; case UniformName::kSampler1IsIndexedAlpha: @@ -333,6 +349,10 @@ inline constexpr const UniformFormat uniform_format(UniformName name) noexcept return UniformFormat::kInt; case UniformName::kWipeEncoreSwizzle: return UniformFormat::kInt; + case UniformName::kPostimgWater: + return UniformFormat::kInt; + case UniformName::kPostimgHeat: + return UniformFormat::kInt; default: return UniformFormat::kFloat; } @@ -365,7 +385,7 @@ struct UniformInputDesc struct SamplerInputDesc { - std::vector enabled_samplers; + srb2::StaticVec enabled_samplers; }; struct ColorMask diff --git a/src/sdl/rhi_gl3_core_platform.cpp b/src/sdl/rhi_gl3_core_platform.cpp index 79351d73e..155b5b7f2 100644 --- a/src/sdl/rhi_gl3_core_platform.cpp +++ b/src/sdl/rhi_gl3_core_platform.cpp @@ -42,6 +42,8 @@ static constexpr const char* pipeline_lump_slug(rhi::PipelineProgram program) return "unshadedpaletted"; case rhi::PipelineProgram::kPostprocessWipe: return "postprocesswipe"; + case rhi::PipelineProgram::kPostimg: + return "postimg"; default: return ""; } diff --git a/src/v_video.cpp b/src/v_video.cpp index 5d188d155..674f7a3b5 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -2898,196 +2898,6 @@ INT32 V_LevelNameHeight(const char *string) return w; } -boolean *heatshifter = NULL; -INT32 lastheight = 0; -INT32 heatindex[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0}; - -// -// V_DoPostProcessor -// -// Perform a particular image postprocessing function. -// -#include "p_local.h" -void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param) -{ -#if NUMSCREENS < 5 - // do not enable image post processing for ARM, SH and MIPS CPUs - (void)view; - (void)type; - (void)param; -#else - INT32 yoffset, xoffset; - -#ifdef HWRENDER - if (rendermode != render_soft) - return; -#endif - - if (view < 0 || view > 3 || view > r_splitscreen) - return; - - if ((view == 1 && r_splitscreen == 1) || view >= 2) - yoffset = viewheight; - else - yoffset = 0; - - if ((view == 1 || view == 3) && r_splitscreen > 1) - xoffset = viewwidth; - else - xoffset = 0; - - if (type == postimg_water) - { - UINT8 *tmpscr = screens[4]; - UINT8 *srcscr = screens[0]; - INT32 y; - angle_t disStart = (leveltime * 128) & FINEMASK; // in 0 to FINEANGLE - INT32 newpix; - INT32 sine; - //UINT8 *transme = R_GetTranslucencyTable(tr_trans50); - - for (y = yoffset; y < yoffset+viewheight; y++) - { - sine = (FINESINE(disStart)*5)>>FRACBITS; - newpix = abs(sine); - - if (sine < 0) - { - M_Memcpy(&tmpscr[(y*vid.width)+xoffset+newpix], &srcscr[(y*vid.width)+xoffset], viewwidth-newpix); - - // Cleanup edge - while (newpix) - { - tmpscr[(y*vid.width)+xoffset+newpix] = srcscr[(y*vid.width)+xoffset]; - newpix--; - } - } - else - { - M_Memcpy(&tmpscr[(y*vid.width)+xoffset+0], &srcscr[(y*vid.width)+xoffset+sine], viewwidth-newpix); - - // Cleanup edge - while (newpix) - { - tmpscr[(y*vid.width)+xoffset+viewwidth-newpix] = srcscr[(y*vid.width)+xoffset+(viewwidth-1)]; - newpix--; - } - } - -/* -Unoptimized version - for (x = 0; x < vid.width*vid.bpp; x++) - { - newpix = (x + sine); - - if (newpix < 0) - newpix = 0; - else if (newpix >= vid.width) - newpix = vid.width-1; - - tmpscr[y*vid.width + x] = srcscr[y*vid.width+newpix]; // *(transme + (srcscr[y*vid.width+x]<<8) + srcscr[y*vid.width+newpix]); - }*/ - disStart += 22;//the offset into the displacement map, increment each game loop - disStart &= FINEMASK; //clip it to FINEMASK - } - - VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset+xoffset, screens[0]+vid.width*vid.bpp*yoffset+xoffset, - viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width); - } - else if (type == postimg_motion) // Motion Blur! - { - UINT8 *tmpscr = screens[4]; - UINT8 *srcscr = screens[0]; - INT32 x, y; - - // TODO: Add a postimg_param so that we can pick the translucency level... - UINT8 *transme = R_GetTranslucencyTable(param); - - for (y = yoffset; y < yoffset+viewheight; y++) - { - for (x = xoffset; x < xoffset+viewwidth; x++) - { - tmpscr[y*vid.width + x] - = colormaps[*(transme + (srcscr [(y*vid.width)+x ] <<8) + (tmpscr[(y*vid.width)+x]))]; - } - } - VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset+xoffset, screens[0]+vid.width*vid.bpp*yoffset+xoffset, - viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width); - } - else if (type == postimg_flip) // Flip the screen upside-down - { - UINT8 *tmpscr = screens[4]; - UINT8 *srcscr = screens[0]; - INT32 y, y2; - - for (y = yoffset, y2 = yoffset+viewheight - 1; y < yoffset+viewheight; y++, y2--) - M_Memcpy(&tmpscr[(y2*vid.width)+xoffset], &srcscr[(y*vid.width)+xoffset], viewwidth); - - VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset+xoffset, screens[0]+vid.width*vid.bpp*yoffset+xoffset, - viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width); - } - else if (type == postimg_heat) // Heat wave - { - UINT8 *tmpscr = screens[4]; - UINT8 *srcscr = screens[0]; - INT32 y; - - // Make sure table is built - if (heatshifter == NULL || lastheight != viewheight) - { - if (heatshifter) - Z_Free(heatshifter); - - heatshifter = static_cast(Z_Calloc(viewheight * sizeof(boolean), PU_STATIC, NULL)); - - for (y = 0; y < viewheight; y++) - { - if (M_RandomChance(FRACUNIT/8)) // 12.5% - heatshifter[y] = true; - } - - heatindex[0] = heatindex[1] = heatindex[2] = heatindex[3] = 0; - lastheight = viewheight; - } - - for (y = yoffset; y < yoffset+viewheight; y++) - { - if (heatshifter[heatindex[view]++]) - { - // Shift this row of pixels to the right by 2 - tmpscr[(y*vid.width)+xoffset] = srcscr[(y*vid.width)+xoffset]; - M_Memcpy(&tmpscr[(y*vid.width)+xoffset], &srcscr[(y*vid.width)+xoffset+vid.dupx], viewwidth-vid.dupx); - } - else - M_Memcpy(&tmpscr[(y*vid.width)+xoffset], &srcscr[(y*vid.width)+xoffset], viewwidth); - - heatindex[view] %= viewheight; - } - - heatindex[view]++; - heatindex[view] %= vid.height; - - VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset+xoffset, screens[0]+vid.width*vid.bpp*yoffset+xoffset, - viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width); - } - else if (type == postimg_mirror) // Flip the screen on the x axis - { - UINT8 *tmpscr = screens[4]; - UINT8 *srcscr = screens[0]; - INT32 y, x, x2; - - for (y = yoffset; y < yoffset+viewheight; y++) - { - for (x = xoffset, x2 = xoffset+((viewwidth*vid.bpp)-1); x < xoffset+(viewwidth*vid.bpp); x++, x2--) - tmpscr[y*vid.width + x2] = srcscr[y*vid.width + x]; - } - - VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset+xoffset, screens[0]+vid.width*vid.bpp*yoffset+xoffset, - viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width); - } -#endif -} - // Generates a RGB565 color look-up table void InitColorLUT(colorlookup_t *lut, RGBA_t *palette, boolean makecolors) { diff --git a/src/v_video.h b/src/v_video.h index bda5920d9..fdd119c88 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -409,8 +409,6 @@ void V_DrawRightAlignedLSTitleHighString(INT32 x, INT32 y, INT32 option, const c void V_DrawCenteredLSTitleLowString(INT32 x, INT32 y, INT32 option, const char *string); void V_DrawRightAlignedLSTitleLowString(INT32 x, INT32 y, INT32 option, const char *string); -void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param); - void V_DrawPatchFill(patch_t *pat); void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT32 height, size_t srcrowbytes,