From 0072170b2e48f27e1b153712ec3bf6f47af8d74b Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sun, 17 Mar 2024 17:50:29 -0700 Subject: [PATCH] Add SalCRT Sharp --- src/cvars.cpp | 2 +- src/hwr2/blit_rect.cpp | 43 +++++++++++++++++++++++++++++++++++- src/hwr2/blit_rect.hpp | 1 + src/hwr2/hardware_state.hpp | 1 + src/i_video_common.cpp | 8 +++++++ src/rhi/rhi.cpp | 12 ++++++++++ src/rhi/rhi.hpp | 4 +++- src/sdl/rhi_gl2_platform.cpp | 2 ++ 8 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index df290f65f..f8f143a7f 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -431,7 +431,7 @@ consvar_t cv_scr_depth = Player("scr_depth", "16 bits").values({{8, "8 bits"}, { //added : 03-02-98: default screen mode, as loaded/saved in config consvar_t cv_scr_width = Player("scr_width", "640").values(CV_Unsigned); consvar_t cv_scr_height = Player("scr_height", "400").values(CV_Unsigned); -consvar_t cv_scr_effect = Player("scr_effect", "Sharp Bilinear").values({{0, "Nearest"}, {1, "Sharp Bilinear"}, {2, "SalCRT"}}).save(); +consvar_t cv_scr_effect = Player("scr_effect", "Sharp Bilinear").values({{0, "Nearest"}, {1, "Sharp Bilinear"}, {2, "SalCRT"}, {3, "SalCRT Sharp"}}).save(); consvar_t cv_scr_scale = Player("scr_scale", "1.0").floating_point(); consvar_t cv_scr_x = Player("scr_x", "0.0").floating_point(); diff --git a/src/hwr2/blit_rect.cpp b/src/hwr2/blit_rect.cpp index 41290604c..ec9d09ce4 100644 --- a/src/hwr2/blit_rect.cpp +++ b/src/hwr2/blit_rect.cpp @@ -79,6 +79,20 @@ static const PipelineDesc kCrtPipelineDescription = { FaceWinding::kCounterClockwise, {0.f, 0.f, 0.f, 1.f}}; +/// @brief Pipeline used for CRT special blit (sharp) +static const PipelineDesc kCrtSharpPipelineDescription = { + PipelineProgram::kCrtSharp, + {{{sizeof(BlitVertex)}}, {{VertexAttributeName::kPosition, 0, 0}, {VertexAttributeName::kTexCoord0, 0, 12}}}, + {{{UniformName::kProjection}, {{UniformName::kModelView, UniformName::kTexCoord0Transform, UniformName::kSampler0Size}}}}, + {{// RGB/A texture + SamplerName::kSampler0, SamplerName::kSampler1}}, + std::nullopt, + {std::nullopt, {true, true, true, true}}, + PrimitiveType::kTriangles, + CullMode::kNone, + FaceWinding::kCounterClockwise, + {0.f, 0.f, 0.f, 1.f}}; + BlitRectPass::BlitRectPass() : BlitRectPass(BlitRectPass::BlitMode::kNearest) {} BlitRectPass::BlitRectPass(BlitRectPass::BlitMode blit_mode) : blit_mode_(blit_mode) {} BlitRectPass::~BlitRectPass() = default; @@ -105,6 +119,9 @@ void BlitRectPass::prepass(Rhi& rhi) case BlitRectPass::BlitMode::kCrt: pipeline_ = rhi.create_pipeline(kCrtPipelineDescription); break; + case BlitRectPass::BlitMode::kCrtSharp: + pipeline_ = rhi.create_pipeline(kCrtSharpPipelineDescription); + break; default: std::terminate(); } @@ -123,7 +140,7 @@ void BlitRectPass::prepass(Rhi& rhi) quad_ibo_needs_upload_ = true; } - if (blit_mode_ == BlitRectPass::BlitMode::kCrt && !dot_pattern_) + if ((blit_mode_ == BlitRectPass::BlitMode::kCrt || blit_mode_ == BlitRectPass::BlitMode::kCrtSharp) && !dot_pattern_) { dot_pattern_ = rhi.create_texture({ rhi::TextureFormat::kRGBA, @@ -260,6 +277,30 @@ void BlitRectPass::transfer(Rhi& rhi, Handle ctx) binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs}); break; } + case BlitRectPass::BlitMode::kCrtSharp: + { + std::array g2_uniforms = { + // ModelView + glm::scale( + glm::identity(), + glm::vec3(taller ? 2.f : 2.f * aspect, taller ? 2.f * (1.f / aspect) : 2.f, 1.f) + ), + // Texcoord0 Transform + glm::mat3( + glm::vec3(1.f, 0.f, 0.f), + glm::vec3(0.f, output_flip_ ? -1.f : 1.f, 0.f), + glm::vec3(0.f, output_flip_ ? 1.f : 0.f, 1.f) + ), + // Sampler 0 Size + glm::vec2(texture_details.width, texture_details.height) + }; + uniform_sets_[1] = rhi.create_uniform_set(ctx, {g2_uniforms}); + + std::array vbs = {{{0, quad_vbo_}}}; + std::array tbs = {{{rhi::SamplerName::kSampler0, texture_}, {rhi::SamplerName::kSampler1, dot_pattern_}}}; + binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs}); + break; + } case BlitRectPass::BlitMode::kSharpBilinear: { std::array g2_uniforms = { diff --git a/src/hwr2/blit_rect.hpp b/src/hwr2/blit_rect.hpp index ba256e6ee..3afd74a2c 100644 --- a/src/hwr2/blit_rect.hpp +++ b/src/hwr2/blit_rect.hpp @@ -27,6 +27,7 @@ public: kNearest, kSharpBilinear, kCrt, + kCrtSharp }; private: diff --git a/src/hwr2/hardware_state.hpp b/src/hwr2/hardware_state.hpp index fa8871f0e..134507862 100644 --- a/src/hwr2/hardware_state.hpp +++ b/src/hwr2/hardware_state.hpp @@ -40,6 +40,7 @@ struct HardwareState std::unique_ptr blit_rect; std::unique_ptr sharp_bilinear_blit_rect; std::unique_ptr crt_blit_rect; + std::unique_ptr crtsharp_blit_rect; std::unique_ptr screen_capture; std::unique_ptr backbuffer; WipeFrames wipe_frames; diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp index f357fb178..15cc1b8c4 100644 --- a/src/i_video_common.cpp +++ b/src/i_video_common.cpp @@ -85,6 +85,7 @@ static void reset_hardware_state(Rhi* rhi) g_hw_state.blit_rect = std::make_unique(BlitRectPass::BlitMode::kNearest); g_hw_state.sharp_bilinear_blit_rect = std::make_unique(BlitRectPass::BlitMode::kSharpBilinear); g_hw_state.crt_blit_rect = std::make_unique(BlitRectPass::BlitMode::kCrt); + g_hw_state.crtsharp_blit_rect = std::make_unique(BlitRectPass::BlitMode::kCrtSharp); g_hw_state.screen_capture = std::make_unique(); g_hw_state.backbuffer = std::make_unique(); g_hw_state.wipe_frames = {}; @@ -298,16 +299,19 @@ void I_FinishUpdate(void) g_hw_state.blit_rect->set_output(x, y, w, h, true, true); g_hw_state.sharp_bilinear_blit_rect->set_output(x, y, w, h, true, true); g_hw_state.crt_blit_rect->set_output(x, y, w, h, true, true); + g_hw_state.crtsharp_blit_rect->set_output(x, y, w, h, true, true); } else { g_hw_state.blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); g_hw_state.sharp_bilinear_blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); g_hw_state.crt_blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); + g_hw_state.crtsharp_blit_rect->set_output(0, 0, 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.sharp_bilinear_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); g_hw_state.crt_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); + g_hw_state.crtsharp_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); switch (cv_scr_effect.value) { @@ -319,6 +323,10 @@ void I_FinishUpdate(void) rhi->update_texture_settings(ctx, g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kLinear, TextureFilterMode::kLinear); g_hw_state.crt_blit_rect->draw(*rhi, ctx); break; + case 3: + rhi->update_texture_settings(ctx, g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kLinear, TextureFilterMode::kLinear); + g_hw_state.crtsharp_blit_rect->draw(*rhi, ctx); + break; default: rhi->update_texture_settings(ctx, g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kNearest, TextureFilterMode::kNearest); g_hw_state.blit_rect->draw(*rhi, ctx); diff --git a/src/rhi/rhi.cpp b/src/rhi/rhi.cpp index 6813122bb..94c60089d 100644 --- a/src/rhi/rhi.cpp +++ b/src/rhi/rhi.cpp @@ -87,6 +87,16 @@ const ProgramRequirements srb2::rhi::kProgramRequirementsCrt = { {{{UniformName::kModelView, true}, {UniformName::kTexCoord0Transform, true}, {UniformName::kSampler0Size, true}}}}}, ProgramSamplerRequirements {{{SamplerName::kSampler0, true}, {SamplerName::kSampler1, true}}}}; +const ProgramRequirements srb2::rhi::kProgramRequirementsCrtSharp = { + ProgramVertexInputRequirements { + {ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, + ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, + ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false}}}, + ProgramUniformRequirements { + {{{{UniformName::kProjection, true}}}, + {{{UniformName::kModelView, true}, {UniformName::kTexCoord0Transform, true}, {UniformName::kSampler0Size, true}}}}}, + ProgramSamplerRequirements {{{SamplerName::kSampler0, true}, {SamplerName::kSampler1, true}}}}; + const ProgramRequirements& rhi::program_requirements_for_program(PipelineProgram program) noexcept { switch (program) @@ -103,6 +113,8 @@ const ProgramRequirements& rhi::program_requirements_for_program(PipelineProgram return kProgramRequirementsSharpBilinear; case PipelineProgram::kCrt: return kProgramRequirementsCrt; + case PipelineProgram::kCrtSharp: + return kProgramRequirementsCrtSharp; default: std::terminate(); } diff --git a/src/rhi/rhi.hpp b/src/rhi/rhi.hpp index 2b42a6cca..544e9ce74 100644 --- a/src/rhi/rhi.hpp +++ b/src/rhi/rhi.hpp @@ -174,7 +174,8 @@ enum class PipelineProgram kPostprocessWipe, kPostimg, kSharpBilinear, - kCrt + kCrt, + kCrtSharp }; enum class BufferType @@ -289,6 +290,7 @@ extern const ProgramRequirements kProgramRequirementsPostprocessWipe; extern const ProgramRequirements kProgramRequirementsPostimg; extern const ProgramRequirements kProgramRequirementsSharpBilinear; extern const ProgramRequirements kProgramRequirementsCrt; +extern const ProgramRequirements kProgramRequirementsCrtSharp; const ProgramRequirements& program_requirements_for_program(PipelineProgram program) noexcept; diff --git a/src/sdl/rhi_gl2_platform.cpp b/src/sdl/rhi_gl2_platform.cpp index 10b3905e5..399ffa5cb 100644 --- a/src/sdl/rhi_gl2_platform.cpp +++ b/src/sdl/rhi_gl2_platform.cpp @@ -49,6 +49,8 @@ static constexpr const char* pipeline_lump_slug(rhi::PipelineProgram program) return "sharpbilinear"; case rhi::PipelineProgram::kCrt: return "crt"; + case rhi::PipelineProgram::kCrtSharp: + return "crtsharp"; default: return ""; }