From aa48237928ffcb947088cff6d83fb26701d165b3 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Fri, 19 May 2023 18:45:12 -0500 Subject: [PATCH] hwr2: Track colormaps and lighttables tex globally This will allow hardware to reuse the same colormap textures objects as twodee. --- src/hwr2/pass_resource_managers.cpp | 150 ++++++++++++++++++++++++++-- src/hwr2/pass_resource_managers.hpp | 21 ++++ src/hwr2/pass_twodee.cpp | 59 +---------- 3 files changed, 164 insertions(+), 66 deletions(-) diff --git a/src/hwr2/pass_resource_managers.cpp b/src/hwr2/pass_resource_managers.cpp index 58ea993eb..a6f2a52cc 100644 --- a/src/hwr2/pass_resource_managers.cpp +++ b/src/hwr2/pass_resource_managers.cpp @@ -12,6 +12,7 @@ #include #include +#include "../r_state.h" #include "../v_video.h" #include "../z_zone.h" @@ -139,28 +140,148 @@ void FramebufferManager::postpass(Rhi& rhi) { } -MainPaletteManager::MainPaletteManager() : Pass() -{ -} - +MainPaletteManager::MainPaletteManager() = default; MainPaletteManager::~MainPaletteManager() = default; +constexpr std::size_t kPaletteSize = 256; +constexpr std::size_t kLighttableRows = LIGHTLEVELS; + void MainPaletteManager::prepass(Rhi& rhi) { if (!palette_) { - palette_ = rhi.create_texture({TextureFormat::kRGBA, 256, 1, TextureWrapMode::kClamp, TextureWrapMode::kClamp}); + palette_ = rhi.create_texture({TextureFormat::kRGBA, kPaletteSize, 1, TextureWrapMode::kClamp, TextureWrapMode::kClamp}); } + + if (!lighttable_) + { + lighttable_ = rhi.create_texture({TextureFormat::kLuminance, kPaletteSize, kLighttableRows, TextureWrapMode::kClamp, TextureWrapMode::kClamp}); + } + + if (!encore_lighttable_) + { + encore_lighttable_ = rhi.create_texture({TextureFormat::kLuminance, kPaletteSize, kLighttableRows, TextureWrapMode::kClamp, TextureWrapMode::kClamp}); + } + + if (!default_colormap_) + { + default_colormap_ = rhi.create_texture({TextureFormat::kLuminance, kPaletteSize, 1, TextureWrapMode::kClamp, TextureWrapMode::kClamp}); + } +} + +void MainPaletteManager::upload_palette(Rhi& rhi, Handle ctx) +{ + std::array palette_32; + for (std::size_t i = 0; i < kPaletteSize; i++) + { + palette_32[i] = V_GetColor(i).s; + } + rhi.update_texture(ctx, palette_, {0, 0, kPaletteSize, 1}, PixelFormat::kRGBA8, tcb::as_bytes(tcb::span(palette_32))); +} + +void MainPaletteManager::upload_lighttables(Rhi& rhi, Handle ctx) +{ + tcb::span colormap_bytes = tcb::as_bytes(tcb::span(colormaps, kPaletteSize * kLighttableRows)); + rhi.update_texture(ctx, lighttable_, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, colormap_bytes); + + if (encoremap != nullptr) + { + tcb::span encoremap_bytes = tcb::as_bytes(tcb::span(encoremap, kPaletteSize * kLighttableRows)); + rhi.update_texture(ctx, lighttable_, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, encoremap_bytes); + } + + if (!lighttables_to_upload_.empty()) + { + for (auto lighttable : lighttables_to_upload_) + { + Handle lighttable_tex = find_extra_lighttable(lighttable); + SRB2_ASSERT(lighttable_tex != kNullHandle); + tcb::span lighttable_bytes = tcb::as_bytes(tcb::span(lighttable, kPaletteSize * kLighttableRows)); + rhi.update_texture(ctx, lighttable_tex, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, lighttable_bytes); + } + lighttables_to_upload_.clear(); + } +} + +void MainPaletteManager::upload_default_colormap(Rhi& rhi, Handle ctx) +{ + std::array data; + for (std::size_t i = 0; i < kPaletteSize; i++) + { + data[i] = i; + } + rhi.update_texture(ctx, default_colormap_, {0, 0, kPaletteSize, 1}, PixelFormat::kR8, tcb::as_bytes(tcb::span(data))); +} + +void MainPaletteManager::upload_colormaps(Rhi& rhi, Handle ctx) +{ + for (auto to_upload : colormaps_to_upload_) + { + SRB2_ASSERT(to_upload != nullptr); + SRB2_ASSERT(colormaps_.find(to_upload) != colormaps_.end()); + + rhi::Handle map_texture = colormaps_.at(to_upload); + + tcb::span map_bytes = tcb::as_bytes(tcb::span(to_upload, kPaletteSize)); + rhi.update_texture(ctx, map_texture, {0, 0, kPaletteSize, 1}, PixelFormat::kR8, map_bytes); + } + colormaps_to_upload_.clear(); +} + +rhi::Handle MainPaletteManager::find_or_create_colormap(rhi::Rhi& rhi, srb2::NotNull colormap) +{ + if (colormaps_.find(colormap) != colormaps_.end()) + { + return colormaps_[colormap]; + } + + Handle texture = rhi.create_texture({TextureFormat::kLuminance, kPaletteSize, 1, TextureWrapMode::kClamp, TextureWrapMode::kClamp}); + + colormaps_.insert_or_assign(colormap, texture); + colormaps_to_upload_.push_back(colormap); + return texture; +} + +rhi::Handle MainPaletteManager::find_colormap(srb2::NotNull colormap) const +{ + if (colormaps_.find(colormap) == colormaps_.end()) + { + return kNullHandle; + } + + return colormaps_.at(colormap); +} + +rhi::Handle MainPaletteManager::find_or_create_extra_lighttable(Rhi& rhi, srb2::NotNull lighttable) +{ + if (lighttables_.find(lighttable) != lighttables_.end()) + { + return lighttables_[lighttable]; + } + + Handle texture = rhi.create_texture({TextureFormat::kLuminance, kPaletteSize, kLighttableRows, TextureWrapMode::kClamp, TextureWrapMode::kClamp}); + + lighttables_.insert_or_assign(lighttable, texture); + lighttables_to_upload_.push_back(lighttable); + return texture; +} + +rhi::Handle MainPaletteManager::find_extra_lighttable(srb2::NotNull lighttable) const +{ + if (lighttables_.find(lighttable) == lighttables_.end()) + { + return kNullHandle; + } + + return lighttables_.at(lighttable); } void MainPaletteManager::transfer(Rhi& rhi, Handle ctx) { - std::array palette_32; - for (std::size_t i = 0; i < 256; i++) - { - palette_32[i] = V_GetColor(i).s; - } - rhi.update_texture(ctx, palette_, {0, 0, 256, 1}, PixelFormat::kRGBA8, tcb::as_bytes(tcb::span(palette_32))); + upload_palette(rhi, ctx); + upload_lighttables(rhi, ctx); + upload_default_colormap(rhi, ctx); + upload_colormaps(rhi, ctx); } void MainPaletteManager::graphics(Rhi& rhi, Handle ctx) @@ -169,6 +290,13 @@ void MainPaletteManager::graphics(Rhi& rhi, Handle ctx) void MainPaletteManager::postpass(Rhi& rhi) { + // Delete all colormap textures so they'll be recreated next frame + // Unfortunately the 256x1 translation colormaps are sometimes freed at runtime + for (auto& cm : colormaps_) + { + rhi.destroy_texture(cm.second); + } + colormaps_.clear(); } CommonResourcesManager::CommonResourcesManager() = default; diff --git a/src/hwr2/pass_resource_managers.hpp b/src/hwr2/pass_resource_managers.hpp index 30c158572..11e7fad95 100644 --- a/src/hwr2/pass_resource_managers.hpp +++ b/src/hwr2/pass_resource_managers.hpp @@ -74,6 +74,19 @@ public: class MainPaletteManager final : public Pass { rhi::Handle palette_; + rhi::Handle lighttable_; + rhi::Handle encore_lighttable_; + rhi::Handle default_colormap_; + + std::unordered_map> colormaps_; + std::unordered_map> lighttables_; + std::vector colormaps_to_upload_; + std::vector lighttables_to_upload_; + + void upload_palette(rhi::Rhi& rhi, rhi::Handle ctx); + void upload_lighttables(rhi::Rhi& rhi, rhi::Handle ctx); + void upload_default_colormap(rhi::Rhi& rhi, rhi::Handle ctx); + void upload_colormaps(rhi::Rhi& rhi, rhi::Handle ctx); public: MainPaletteManager(); @@ -85,6 +98,14 @@ public: virtual void postpass(rhi::Rhi& rhi) override; rhi::Handle palette() const noexcept { return palette_; } + rhi::Handle lighttable() const noexcept { return lighttable_; } + rhi::Handle encore_lighttable() const noexcept { return encore_lighttable_; } + rhi::Handle default_colormap() const noexcept { return default_colormap_; } + + rhi::Handle find_or_create_colormap(rhi::Rhi& rhi, srb2::NotNull colormap); + rhi::Handle find_colormap(srb2::NotNull colormap) const; + rhi::Handle find_or_create_extra_lighttable(rhi::Rhi& rhi, srb2::NotNull lighttable); + rhi::Handle find_extra_lighttable(srb2::NotNull lighttable) const; }; class CommonResourcesManager final : public Pass diff --git a/src/hwr2/pass_twodee.cpp b/src/hwr2/pass_twodee.cpp index acac41bd0..ed30706df 100644 --- a/src/hwr2/pass_twodee.cpp +++ b/src/hwr2/pass_twodee.cpp @@ -26,9 +26,6 @@ using namespace srb2::rhi; struct srb2::hwr2::TwodeePassData { Handle default_tex; - Handle default_colormap_tex; - std::unordered_map> colormaps; - std::vector colormaps_to_upload; std::unordered_map> pipelines; bool upload_default_tex = false; }; @@ -286,17 +283,6 @@ void TwodeePass::prepass(Rhi& rhi) }); data_->upload_default_tex = true; } - if (!data_->default_colormap_tex) - { - data_->default_colormap_tex = rhi.create_texture({ - TextureFormat::kLuminance, - 256, - 1, - TextureWrapMode::kClamp, - TextureWrapMode::kClamp - }); - data_->upload_default_tex = true; - } if (!render_pass_) { render_pass_ = rhi.create_render_pass( @@ -314,7 +300,6 @@ void TwodeePass::prepass(Rhi& rhi) // Stage 1 - command list patch detection std::unordered_set found_patches; - std::unordered_set found_colormaps; for (const auto& list : *ctx_) { for (const auto& cmd : list.cmds) @@ -328,7 +313,7 @@ void TwodeePass::prepass(Rhi& rhi) } if (cmd.colormap != nullptr) { - found_colormaps.insert(cmd.colormap); + palette_manager_->find_or_create_colormap(rhi, cmd.colormap); } }, [&](const Draw2dVertices& cmd) {}}; @@ -342,17 +327,6 @@ void TwodeePass::prepass(Rhi& rhi) } patch_atlas_cache_->pack(rhi); - for (auto colormap : found_colormaps) - { - if (data_->colormaps.find(colormap) == data_->colormaps.end()) - { - Handle colormap_tex = rhi.create_texture({TextureFormat::kLuminance, 256, 1}); - data_->colormaps.insert({colormap, colormap_tex}); - } - - data_->colormaps_to_upload.push_back(colormap); - } - size_t list_index = 0; for (auto& list : *ctx_) { @@ -536,34 +510,9 @@ void TwodeePass::transfer(Rhi& rhi, Handle ctx) std::array data = {0, 255, 0, 255}; rhi.update_texture(ctx, data_->default_tex, {0, 0, 2, 1}, PixelFormat::kRG8, tcb::as_bytes(tcb::span(data))); - std::array colormap_data; - for (size_t i = 0; i < 256; i++) - { - colormap_data[i] = i; - } - rhi.update_texture( - ctx, - data_->default_colormap_tex, - {0, 0, 256, 1}, - PixelFormat::kR8, - tcb::as_bytes(tcb::span(colormap_data)) - ); - data_->upload_default_tex = false; } - for (auto colormap : data_->colormaps_to_upload) - { - rhi.update_texture( - ctx, - data_->colormaps[colormap], - {0, 0, 256, 1}, - rhi::PixelFormat::kR8, - tcb::as_bytes(tcb::span(colormap, 256)) - ); - } - data_->colormaps_to_upload.clear(); - Handle palette_tex = palette_manager_->palette(); // Update the buffers for each list @@ -607,11 +556,11 @@ void TwodeePass::transfer(Rhi& rhi, Handle ctx) } const uint8_t* colormap = mcmd.colormap; - Handle colormap_h = data_->default_colormap_tex; + Handle colormap_h = palette_manager_->default_colormap(); if (colormap) { - SRB2_ASSERT(data_->colormaps.find(colormap) != data_->colormaps.end()); - colormap_h = data_->colormaps[colormap]; + colormap_h = palette_manager_->find_colormap(colormap); + SRB2_ASSERT(colormap_h != kNullHandle); } tx[2] = {SamplerName::kSampler2, colormap_h}; mcmd.binding_set =