Merge branch 'more-rhi-stuff' into 'master'

More RHI improvements for HWR2

See merge request KartKrew/Kart!1246
This commit is contained in:
Eidolon 2023-05-20 15:45:34 +00:00
commit 2918f9b61c
13 changed files with 345 additions and 129 deletions

View file

@ -1,4 +1,5 @@
target_sources(SRB2SDL2 PRIVATE
blendmode.hpp
pass_blit_postimg_screens.cpp
pass_blit_postimg_screens.hpp
pass_blit_rect.cpp

28
src/hwr2/blendmode.hpp Normal file
View file

@ -0,0 +1,28 @@
// 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_BLENDMODE_HPP__
#define __SRB2_HWR2_BLENDMODE_HPP__
namespace srb2::hwr2
{
enum class BlendMode
{
kAlphaTransparent,
kModulate,
kAdditive,
kSubtractive,
kReverseSubtractive,
kInvertDest
};
} // namespace srb2::hwr2
#endif // __SRB2_HWR2_BLENDMODE_HPP__

View file

@ -12,6 +12,7 @@
#include <algorithm>
#include <cmath>
#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<TransferContext> ctx)
{
std::array<byteColor_t, kPaletteSize> 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<TransferContext> ctx)
{
tcb::span<const std::byte> 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<const std::byte> 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<Texture> lighttable_tex = find_extra_lighttable(lighttable);
SRB2_ASSERT(lighttable_tex != kNullHandle);
tcb::span<const std::byte> 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<TransferContext> ctx)
{
std::array<uint8_t, kPaletteSize> 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<TransferContext> ctx)
{
for (auto to_upload : colormaps_to_upload_)
{
SRB2_ASSERT(to_upload != nullptr);
SRB2_ASSERT(colormaps_.find(to_upload) != colormaps_.end());
rhi::Handle<rhi::Texture> map_texture = colormaps_.at(to_upload);
tcb::span<const std::byte> 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<rhi::Texture> MainPaletteManager::find_or_create_colormap(rhi::Rhi& rhi, srb2::NotNull<const uint8_t*> colormap)
{
if (colormaps_.find(colormap) != colormaps_.end())
{
return colormaps_[colormap];
}
Handle<Texture> 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<rhi::Texture> MainPaletteManager::find_colormap(srb2::NotNull<const uint8_t*> colormap) const
{
if (colormaps_.find(colormap) == colormaps_.end())
{
return kNullHandle;
}
return colormaps_.at(colormap);
}
rhi::Handle<rhi::Texture> MainPaletteManager::find_or_create_extra_lighttable(Rhi& rhi, srb2::NotNull<const uint8_t*> lighttable)
{
if (lighttables_.find(lighttable) != lighttables_.end())
{
return lighttables_[lighttable];
}
Handle<Texture> 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<rhi::Texture> MainPaletteManager::find_extra_lighttable(srb2::NotNull<const uint8_t*> lighttable) const
{
if (lighttables_.find(lighttable) == lighttables_.end())
{
return kNullHandle;
}
return lighttables_.at(lighttable);
}
void MainPaletteManager::transfer(Rhi& rhi, Handle<TransferContext> ctx)
{
std::array<byteColor_t, 256> 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<GraphicsContext> ctx)
@ -169,6 +290,13 @@ void MainPaletteManager::graphics(Rhi& rhi, Handle<GraphicsContext> 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;

View file

@ -74,6 +74,19 @@ public:
class MainPaletteManager final : public Pass
{
rhi::Handle<rhi::Texture> palette_;
rhi::Handle<rhi::Texture> lighttable_;
rhi::Handle<rhi::Texture> encore_lighttable_;
rhi::Handle<rhi::Texture> default_colormap_;
std::unordered_map<const uint8_t*, rhi::Handle<rhi::Texture>> colormaps_;
std::unordered_map<const uint8_t*, rhi::Handle<rhi::Texture>> lighttables_;
std::vector<const uint8_t*> colormaps_to_upload_;
std::vector<const uint8_t*> lighttables_to_upload_;
void upload_palette(rhi::Rhi& rhi, rhi::Handle<rhi::TransferContext> ctx);
void upload_lighttables(rhi::Rhi& rhi, rhi::Handle<rhi::TransferContext> ctx);
void upload_default_colormap(rhi::Rhi& rhi, rhi::Handle<rhi::TransferContext> ctx);
void upload_colormaps(rhi::Rhi& rhi, rhi::Handle<rhi::TransferContext> ctx);
public:
MainPaletteManager();
@ -85,6 +98,14 @@ public:
virtual void postpass(rhi::Rhi& rhi) override;
rhi::Handle<rhi::Texture> palette() const noexcept { return palette_; }
rhi::Handle<rhi::Texture> lighttable() const noexcept { return lighttable_; }
rhi::Handle<rhi::Texture> encore_lighttable() const noexcept { return encore_lighttable_; }
rhi::Handle<rhi::Texture> default_colormap() const noexcept { return default_colormap_; }
rhi::Handle<rhi::Texture> find_or_create_colormap(rhi::Rhi& rhi, srb2::NotNull<const uint8_t*> colormap);
rhi::Handle<rhi::Texture> find_colormap(srb2::NotNull<const uint8_t*> colormap) const;
rhi::Handle<rhi::Texture> find_or_create_extra_lighttable(rhi::Rhi& rhi, srb2::NotNull<const uint8_t*> lighttable);
rhi::Handle<rhi::Texture> find_extra_lighttable(srb2::NotNull<const uint8_t*> lighttable) const;
};
class CommonResourcesManager final : public Pass

View file

@ -14,6 +14,7 @@
#include <stb_rect_pack.h>
#include <glm/gtc/matrix_transform.hpp>
#include "blendmode.hpp"
#include "../r_patch.h"
#include "../v_video.h"
#include "../z_zone.h"
@ -25,9 +26,6 @@ using namespace srb2::rhi;
struct srb2::hwr2::TwodeePassData
{
Handle<Texture> default_tex;
Handle<Texture> default_colormap_tex;
std::unordered_map<const uint8_t*, Handle<Texture>> colormaps;
std::vector<const uint8_t*> colormaps_to_upload;
std::unordered_map<TwodeePipelineKey, Handle<Pipeline>> pipelines;
bool upload_default_tex = false;
};
@ -61,7 +59,7 @@ static PipelineDesc make_pipeline_desc(TwodeePipelineKey key)
BlendDesc blend_desc;
switch (key.blend)
{
case Draw2dBlend::kAlphaTransparent:
case BlendMode::kAlphaTransparent:
blend_desc.source_factor_color = BlendFactor::kSourceAlpha;
blend_desc.dest_factor_color = BlendFactor::kOneMinusSourceAlpha;
blend_desc.color_function = BlendFunction::kAdd;
@ -69,7 +67,7 @@ static PipelineDesc make_pipeline_desc(TwodeePipelineKey key)
blend_desc.dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha;
blend_desc.alpha_function = BlendFunction::kAdd;
break;
case Draw2dBlend::kModulate:
case BlendMode::kModulate:
blend_desc.source_factor_color = BlendFactor::kDest;
blend_desc.dest_factor_color = BlendFactor::kZero;
blend_desc.color_function = BlendFunction::kAdd;
@ -77,7 +75,7 @@ static PipelineDesc make_pipeline_desc(TwodeePipelineKey key)
blend_desc.dest_factor_alpha = BlendFactor::kZero;
blend_desc.alpha_function = BlendFunction::kAdd;
break;
case Draw2dBlend::kAdditive:
case BlendMode::kAdditive:
blend_desc.source_factor_color = BlendFactor::kSourceAlpha;
blend_desc.dest_factor_color = BlendFactor::kOne;
blend_desc.color_function = BlendFunction::kAdd;
@ -85,7 +83,7 @@ static PipelineDesc make_pipeline_desc(TwodeePipelineKey key)
blend_desc.dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha;
blend_desc.alpha_function = BlendFunction::kAdd;
break;
case Draw2dBlend::kSubtractive:
case BlendMode::kSubtractive:
blend_desc.source_factor_color = BlendFactor::kSourceAlpha;
blend_desc.dest_factor_color = BlendFactor::kOne;
blend_desc.color_function = BlendFunction::kSubtract;
@ -93,7 +91,7 @@ static PipelineDesc make_pipeline_desc(TwodeePipelineKey key)
blend_desc.dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha;
blend_desc.alpha_function = BlendFunction::kAdd;
break;
case Draw2dBlend::kReverseSubtractive:
case BlendMode::kReverseSubtractive:
blend_desc.source_factor_color = BlendFactor::kSourceAlpha;
blend_desc.dest_factor_color = BlendFactor::kOne;
blend_desc.color_function = BlendFunction::kReverseSubtract;
@ -101,7 +99,7 @@ static PipelineDesc make_pipeline_desc(TwodeePipelineKey key)
blend_desc.dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha;
blend_desc.alpha_function = BlendFunction::kAdd;
break;
case Draw2dBlend::kInvertDest:
case BlendMode::kInvertDest:
blend_desc.source_factor_color = BlendFactor::kOne;
blend_desc.dest_factor_color = BlendFactor::kOne;
blend_desc.color_function = BlendFunction::kSubtract;
@ -248,18 +246,18 @@ void TwodeePass::prepass(Rhi& rhi)
if (data_->pipelines.size() == 0)
{
TwodeePipelineKey alpha_transparent_tris = {Draw2dBlend::kAlphaTransparent, false};
TwodeePipelineKey modulate_tris = {Draw2dBlend::kModulate, false};
TwodeePipelineKey additive_tris = {Draw2dBlend::kAdditive, false};
TwodeePipelineKey subtractive_tris = {Draw2dBlend::kSubtractive, false};
TwodeePipelineKey revsubtractive_tris = {Draw2dBlend::kReverseSubtractive, false};
TwodeePipelineKey invertdest_tris = {Draw2dBlend::kInvertDest, false};
TwodeePipelineKey alpha_transparent_lines = {Draw2dBlend::kAlphaTransparent, true};
TwodeePipelineKey modulate_lines = {Draw2dBlend::kModulate, true};
TwodeePipelineKey additive_lines = {Draw2dBlend::kAdditive, true};
TwodeePipelineKey subtractive_lines = {Draw2dBlend::kSubtractive, true};
TwodeePipelineKey revsubtractive_lines = {Draw2dBlend::kReverseSubtractive, true};
TwodeePipelineKey invertdest_lines = {Draw2dBlend::kInvertDest, true};
TwodeePipelineKey alpha_transparent_tris = {BlendMode::kAlphaTransparent, false};
TwodeePipelineKey modulate_tris = {BlendMode::kModulate, false};
TwodeePipelineKey additive_tris = {BlendMode::kAdditive, false};
TwodeePipelineKey subtractive_tris = {BlendMode::kSubtractive, false};
TwodeePipelineKey revsubtractive_tris = {BlendMode::kReverseSubtractive, false};
TwodeePipelineKey invertdest_tris = {BlendMode::kInvertDest, false};
TwodeePipelineKey alpha_transparent_lines = {BlendMode::kAlphaTransparent, true};
TwodeePipelineKey modulate_lines = {BlendMode::kModulate, true};
TwodeePipelineKey additive_lines = {BlendMode::kAdditive, true};
TwodeePipelineKey subtractive_lines = {BlendMode::kSubtractive, true};
TwodeePipelineKey revsubtractive_lines = {BlendMode::kReverseSubtractive, true};
TwodeePipelineKey invertdest_lines = {BlendMode::kInvertDest, true};
data_->pipelines.insert({alpha_transparent_tris, rhi.create_pipeline(make_pipeline_desc(alpha_transparent_tris))});
data_->pipelines.insert({modulate_tris, rhi.create_pipeline(make_pipeline_desc(modulate_tris))});
data_->pipelines.insert({additive_tris, rhi.create_pipeline(make_pipeline_desc(additive_tris))});
@ -285,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(
@ -313,7 +300,6 @@ void TwodeePass::prepass(Rhi& rhi)
// Stage 1 - command list patch detection
std::unordered_set<const patch_t*> found_patches;
std::unordered_set<const uint8_t*> found_colormaps;
for (const auto& list : *ctx_)
{
for (const auto& cmd : list.cmds)
@ -327,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) {}};
@ -341,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<Texture> 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_)
{
@ -535,34 +510,9 @@ void TwodeePass::transfer(Rhi& rhi, Handle<TransferContext> ctx)
std::array<uint8_t, 4> 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<uint8_t, 256> 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<Texture> palette_tex = palette_manager_->palette();
// Update the buffers for each list
@ -606,11 +556,11 @@ void TwodeePass::transfer(Rhi& rhi, Handle<TransferContext> ctx)
}
const uint8_t* colormap = mcmd.colormap;
Handle<Texture> colormap_h = data_->default_colormap_tex;
Handle<Texture> 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 =

View file

@ -34,7 +34,7 @@ struct TwodeePassData;
/// @brief Hash map key for caching pipelines
struct TwodeePipelineKey
{
Draw2dBlend blend;
BlendMode blend;
bool lines;
bool operator==(const TwodeePipelineKey& r) const noexcept { return !(blend != r.blend || lines != r.lines); }

View file

@ -89,7 +89,7 @@ void Draw2dVerticesBuilder::done()
list.cmds.push_back(tris_);
}
Draw2dBlend srb2::hwr2::get_blend_mode(const Draw2dCmd& cmd) noexcept
BlendMode srb2::hwr2::get_blend_mode(const Draw2dCmd& cmd) noexcept
{
auto visitor = srb2::Overload {
[&](const Draw2dPatchQuad& cmd) { return cmd.blend; },

View file

@ -19,6 +19,7 @@
#include <tcb/span.hpp>
#include "blendmode.hpp"
#include "../cxxutil.hpp"
#include "../doomtype.h"
@ -38,16 +39,6 @@ struct TwodeeVertex
float a;
};
enum class Draw2dBlend
{
kAlphaTransparent,
kModulate,
kAdditive,
kSubtractive,
kReverseSubtractive,
kInvertDest
};
struct Draw2dPatchQuad
{
std::size_t begin_index = 0;
@ -56,7 +47,7 @@ struct Draw2dPatchQuad
// A null patch ptr means no patch is drawn
const patch_t* patch = nullptr;
const uint8_t* colormap = nullptr;
Draw2dBlend blend;
BlendMode blend;
float r = 0.f;
float g = 0.f;
float b = 0.f;
@ -81,14 +72,14 @@ struct Draw2dVertices
std::size_t begin_index = 0;
std::size_t begin_element = 0;
std::size_t elements = 0;
Draw2dBlend blend = Draw2dBlend::kAlphaTransparent;
BlendMode blend = BlendMode::kAlphaTransparent;
lumpnum_t flat_lump = UINT32_MAX; // LUMPERROR but not loading w_wad.h from this header
bool lines = false;
};
using Draw2dCmd = std::variant<Draw2dPatchQuad, Draw2dVertices>;
Draw2dBlend get_blend_mode(const Draw2dCmd& cmd) noexcept;
BlendMode get_blend_mode(const Draw2dCmd& cmd) noexcept;
bool is_draw_lines(const Draw2dCmd& cmd) noexcept;
std::size_t elements(const Draw2dCmd& cmd) noexcept;
@ -194,7 +185,7 @@ public:
return *this;
}
Draw2dQuadBuilder& blend(Draw2dBlend blend)
Draw2dQuadBuilder& blend(BlendMode blend)
{
quad_.blend = blend;
return *this;
@ -245,7 +236,7 @@ public:
return *this;
}
Draw2dVerticesBuilder& blend(Draw2dBlend blend)
Draw2dVerticesBuilder& blend(BlendMode blend)
{
tris_.blend = blend;
return *this;

View file

@ -886,7 +886,6 @@ void GlCoreRhi::destroy_renderbuffer(rhi::Handle<rhi::Renderbuffer> handle)
rhi::Handle<rhi::Pipeline> GlCoreRhi::create_pipeline(const PipelineDesc& desc)
{
SRB2_ASSERT(graphics_context_active_ == false);
SRB2_ASSERT(platform_ != nullptr);
// TODO assert compatibility of pipeline description with program using ProgramRequirements
@ -1414,26 +1413,32 @@ void GlCoreRhi::bind_pipeline(Handle<GraphicsContext> ctx, Handle<Pipeline> pipe
if (desc.depth_stencil_state->stencil_test)
{
gl_->Enable(GL_STENCIL_TEST);
stencil_front_reference_ = 0;
stencil_back_reference_ = 0;
stencil_front_compare_mask_ = 0xFF;
stencil_back_compare_mask_ = 0xFF;
stencil_front_write_mask_ = 0xFF;
stencil_back_write_mask_ = 0xFF;
GL_ASSERT;
gl_->StencilFuncSeparate(
GL_FRONT,
map_compare_func(desc.depth_stencil_state->front.stencil_compare),
desc.depth_stencil_state->front.reference,
desc.depth_stencil_state->front.compare_mask
stencil_front_reference_,
stencil_front_compare_mask_
);
GL_ASSERT;
gl_->StencilFuncSeparate(
GL_BACK,
map_compare_func(desc.depth_stencil_state->back.stencil_compare),
desc.depth_stencil_state->back.reference,
desc.depth_stencil_state->back.compare_mask
stencil_back_reference_,
stencil_back_compare_mask_
);
GL_ASSERT;
gl_->StencilMaskSeparate(GL_FRONT, desc.depth_stencil_state->front.write_mask);
gl_->StencilMaskSeparate(GL_FRONT, stencil_front_write_mask_);
GL_ASSERT;
gl_->StencilMaskSeparate(GL_BACK, desc.depth_stencil_state->back.write_mask);
gl_->StencilMaskSeparate(GL_BACK, stencil_back_write_mask_);
GL_ASSERT;
}
else
@ -1732,6 +1737,87 @@ void GlCoreRhi::read_pixels(Handle<GraphicsContext> ctx, const Rect& rect, Pixel
gl_->ReadPixels(rect.x, rect.y, rect.w, rect.h, layout, type, out.data());
}
void GlCoreRhi::set_stencil_reference(Handle<GraphicsContext> ctx, CullMode face, uint8_t reference)
{
SRB2_ASSERT(face != CullMode::kNone);
SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation());
SRB2_ASSERT(current_render_pass_.has_value());
SRB2_ASSERT(current_pipeline_.has_value());
auto& pl = pipeline_slab_[*current_pipeline_];
if (face == CullMode::kFront)
{
stencil_front_reference_ = reference;
gl_->StencilFuncSeparate(
GL_FRONT,
map_compare_func(pl.desc.depth_stencil_state->front.stencil_compare),
stencil_front_reference_,
stencil_front_compare_mask_
);
}
else if (face == CullMode::kBack)
{
stencil_back_reference_ = reference;
gl_->StencilFuncSeparate(
GL_BACK,
map_compare_func(pl.desc.depth_stencil_state->back.stencil_compare),
stencil_back_reference_,
stencil_back_compare_mask_
);
}
}
void GlCoreRhi::set_stencil_compare_mask(Handle<GraphicsContext> ctx, CullMode face, uint8_t compare_mask)
{
SRB2_ASSERT(face != CullMode::kNone);
SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation());
SRB2_ASSERT(current_render_pass_.has_value());
SRB2_ASSERT(current_pipeline_.has_value());
auto& pl = pipeline_slab_[*current_pipeline_];
if (face == CullMode::kFront)
{
stencil_front_compare_mask_ = compare_mask;
gl_->StencilFuncSeparate(
GL_FRONT,
map_compare_func(pl.desc.depth_stencil_state->front.stencil_compare),
stencil_front_reference_,
stencil_front_compare_mask_
);
}
else if (face == CullMode::kBack)
{
stencil_back_compare_mask_ = compare_mask;
gl_->StencilFuncSeparate(
GL_BACK,
map_compare_func(pl.desc.depth_stencil_state->back.stencil_compare),
stencil_back_reference_,
stencil_back_compare_mask_
);
}
}
void GlCoreRhi::set_stencil_write_mask(Handle<GraphicsContext> ctx, CullMode face, uint8_t write_mask)
{
SRB2_ASSERT(face != CullMode::kNone);
SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation());
SRB2_ASSERT(current_render_pass_.has_value());
SRB2_ASSERT(current_pipeline_.has_value());
if (face == CullMode::kFront)
{
stencil_front_write_mask_ = write_mask;
gl_->StencilMaskSeparate(GL_FRONT, stencil_front_write_mask_);
}
else if (face == CullMode::kBack)
{
stencil_back_write_mask_ = write_mask;
gl_->StencilMaskSeparate(GL_BACK, stencil_back_write_mask_);
}
}
TextureDetails GlCoreRhi::get_texture_details(Handle<Texture> texture)
{
SRB2_ASSERT(texture_slab_.is_valid(texture));

View file

@ -46,11 +46,11 @@ struct std::hash<srb2::rhi::GlCoreFramebufferKey>
{
std::size_t operator()(const srb2::rhi::GlCoreFramebufferKey& key) const
{
std::size_t color_hash = std::hash<const srb2::rhi::Handle<srb2::rhi::Texture>>()(key.color);
std::size_t color_hash = std::hash<srb2::rhi::Handle<srb2::rhi::Texture>>()(key.color);
std::size_t depth_stencil_hash = 0;
if (key.depth_stencil)
{
depth_stencil_hash = std::hash<const srb2::rhi::Handle<srb2::rhi::Renderbuffer>>()(*key.depth_stencil);
depth_stencil_hash = std::hash<srb2::rhi::Handle<srb2::rhi::Renderbuffer>>()(*key.depth_stencil);
}
return color_hash ^ (depth_stencil_hash << 1);
}
@ -164,6 +164,13 @@ class GlCoreRhi final : public Rhi
uint32_t index_buffer_offset_ = 0;
uint32_t transfer_context_generation_ = 0;
uint8_t stencil_front_reference_ = 0;
uint8_t stencil_front_compare_mask_ = 0xFF;
uint8_t stencil_front_write_mask_ = 0xFF;
uint8_t stencil_back_reference_ = 0;
uint8_t stencil_back_compare_mask_ = 0xFF;
uint8_t stencil_back_write_mask_ = 0xFF;
std::vector<std::function<void()>> disposal_;
public:
@ -225,6 +232,9 @@ public:
virtual void draw_indexed(Handle<GraphicsContext> ctx, uint32_t index_count, uint32_t first_index) override;
virtual void
read_pixels(Handle<GraphicsContext> ctx, const Rect& rect, PixelFormat format, tcb::span<std::byte> out) override;
virtual void set_stencil_reference(Handle<GraphicsContext> ctx, CullMode face, uint8_t reference) override;
virtual void set_stencil_compare_mask(Handle<GraphicsContext> ctx, CullMode face, uint8_t mask) override;
virtual void set_stencil_write_mask(Handle<GraphicsContext> ctx, CullMode face, uint8_t mask) override;
virtual void present() override;

View file

@ -314,7 +314,7 @@ namespace std
{
template <typename T>
struct hash<const srb2::rhi::Handle<T>>
struct hash<srb2::rhi::Handle<T>>
{
std::size_t operator()(const srb2::rhi::Handle<T>& e) const
{

View file

@ -424,9 +424,6 @@ struct PipelineStencilOpStateDesc
StencilOp pass;
StencilOp depth_fail;
CompareFunc stencil_compare;
uint32_t compare_mask;
uint32_t write_mask;
uint32_t reference;
};
struct PipelineDepthStencilStateDesc
@ -648,6 +645,9 @@ struct Rhi
virtual void draw_indexed(Handle<GraphicsContext> ctx, uint32_t index_count, uint32_t first_index) = 0;
virtual void
read_pixels(Handle<GraphicsContext> ctx, const Rect& rect, PixelFormat format, tcb::span<std::byte> out) = 0;
virtual void set_stencil_reference(Handle<GraphicsContext> ctx, CullMode face, uint8_t reference) = 0;
virtual void set_stencil_compare_mask(Handle<GraphicsContext> ctx, CullMode face, uint8_t mask) = 0;
virtual void set_stencil_write_mask(Handle<GraphicsContext> ctx, CullMode face, uint8_t mask) = 0;
virtual void present() = 0;

View file

@ -31,6 +31,7 @@
#include "m_misc.h"
#include "m_random.h"
#include "doomstat.h"
#include "hwr2/blendmode.hpp"
#ifdef HWRENDER
#include "hardware/hw_glob.h"
@ -914,27 +915,27 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
{
falpha = (10 - alphalevel) / 10.f;
}
hwr2::Draw2dBlend blend = hwr2::Draw2dBlend::kAlphaTransparent;
hwr2::BlendMode blend = hwr2::BlendMode::kAlphaTransparent;
switch (blendmode)
{
case AST_MODULATE:
blend = hwr2::Draw2dBlend::kModulate;
blend = hwr2::BlendMode::kModulate;
break;
case AST_ADD:
blend = hwr2::Draw2dBlend::kAdditive;
blend = hwr2::BlendMode::kAdditive;
break;
// Note: SRB2 has these blend modes flipped compared to GL and Vulkan.
// SRB2's Subtract is Dst - Src. OpenGL is Src - Dst. And vice versa for reverse.
// Twodee will use the GL definitions.
case AST_SUBTRACT:
blend = hwr2::Draw2dBlend::kReverseSubtractive;
blend = hwr2::BlendMode::kReverseSubtractive;
break;
case AST_REVERSESUBTRACT:
blend = hwr2::Draw2dBlend::kSubtractive;
blend = hwr2::BlendMode::kSubtractive;
break;
default:
blend = hwr2::Draw2dBlend::kAlphaTransparent;
blend = hwr2::BlendMode::kAlphaTransparent;
break;
}
@ -1187,7 +1188,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
float a = 0.5f; // alphalevel is unused in GL??
g_2d.begin_quad()
.rect(x, y, w, h)
.blend(hwr2::Draw2dBlend::kAlphaTransparent)
.blend(hwr2::BlendMode::kAlphaTransparent)
.color(r, g, b, a)
.done();
}
@ -1332,7 +1333,7 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U
float g;
float b;
float a;
hwr2::Draw2dBlend blendmode;
hwr2::BlendMode blendmode;
if (color & 0xFF00)
{
@ -1345,7 +1346,7 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U
b = std::clamp((fstrength - (2.f / 3.f)) * 3.f, 0.f, 1.f);
a = 1;
blendmode = hwr2::Draw2dBlend::kReverseSubtractive;
blendmode = hwr2::BlendMode::kReverseSubtractive;
}
else
{
@ -1356,7 +1357,7 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U
g = bc.green / 255.f;
b = bc.blue / 255.f;
a = softwaretranstohwr[std::clamp(static_cast<int>(strength), 0, 10)] / 255.f;
blendmode = hwr2::Draw2dBlend::kAlphaTransparent;
blendmode = hwr2::BlendMode::kAlphaTransparent;
}
g_2d.begin_quad()
@ -1529,7 +1530,7 @@ void V_DrawFadeScreen(UINT16 color, UINT8 strength)
float g;
float b;
float a;
hwr2::Draw2dBlend blendmode;
hwr2::BlendMode blendmode;
if (color & 0xFF00)
{
@ -1542,7 +1543,7 @@ void V_DrawFadeScreen(UINT16 color, UINT8 strength)
b = std::clamp((fstrength - (2.f / 3.f)) * 3.f, 0.f, 1.f);
a = 1;
blendmode = hwr2::Draw2dBlend::kReverseSubtractive;
blendmode = hwr2::BlendMode::kReverseSubtractive;
}
else
{
@ -1553,7 +1554,7 @@ void V_DrawFadeScreen(UINT16 color, UINT8 strength)
g = bc.green / 255.f;
b = bc.blue / 255.f;
a = softwaretranstohwr[std::clamp(static_cast<int>(strength), 0, 10)] / 255.f;
blendmode = hwr2::Draw2dBlend::kAlphaTransparent;
blendmode = hwr2::BlendMode::kAlphaTransparent;
}
g_2d.begin_quad()
@ -1629,7 +1630,7 @@ void V_DrawFadeConsBack(INT32 plines)
float a = 0.5f;
g_2d.begin_quad()
.rect(0, 0, vid.width, plines)
.blend(hwr2::Draw2dBlend::kAlphaTransparent)
.blend(hwr2::BlendMode::kAlphaTransparent)
.color(r, g, b, a)
.done();
}
@ -1649,7 +1650,7 @@ void V_EncoreInvertScreen(void)
#endif
g_2d.begin_quad()
.blend(hwr2::Draw2dBlend::kInvertDest)
.blend(hwr2::BlendMode::kInvertDest)
.color(1, 1, 1, 1)
.rect(0, 0, vid.width, vid.height)
.done();