From 20002f83c445b9eba79f75c0a9d2a2fcf71e316d Mon Sep 17 00:00:00 2001 From: Eidolon Date: Fri, 19 May 2023 18:29:36 -0500 Subject: [PATCH] rhi: Make some stencil state dynamic The reference, compare mask and write mask for each face direction in the stencil test is now dynamic pipeline state and are implicitly set to default values when a pipeline is bound. This is implementable using Vulkan dynamic pipeline state bits and so there is no reason not to provide it. In the OpenGL implementation of RHI, this requires tracking some stencil state internally in the graphics context because the stencil state functions require multiple inputs that do not cleanly map to the Vulkan equivalents. --- src/rhi/gl3_core/gl3_core_rhi.cpp | 99 +++++++++++++++++++++++++++++-- src/rhi/gl3_core/gl3_core_rhi.hpp | 10 ++++ src/rhi/rhi.hpp | 6 +- 3 files changed, 106 insertions(+), 9 deletions(-) diff --git a/src/rhi/gl3_core/gl3_core_rhi.cpp b/src/rhi/gl3_core/gl3_core_rhi.cpp index 18985ac43..eab28f852 100644 --- a/src/rhi/gl3_core/gl3_core_rhi.cpp +++ b/src/rhi/gl3_core/gl3_core_rhi.cpp @@ -1414,26 +1414,32 @@ void GlCoreRhi::bind_pipeline(Handle ctx, Handle 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 +1738,87 @@ void GlCoreRhi::read_pixels(Handle 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 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 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 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) { SRB2_ASSERT(texture_slab_.is_valid(texture)); diff --git a/src/rhi/gl3_core/gl3_core_rhi.hpp b/src/rhi/gl3_core/gl3_core_rhi.hpp index 8814ac36f..31e85ad1d 100644 --- a/src/rhi/gl3_core/gl3_core_rhi.hpp +++ b/src/rhi/gl3_core/gl3_core_rhi.hpp @@ -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> disposal_; public: @@ -225,6 +232,9 @@ public: virtual void draw_indexed(Handle ctx, uint32_t index_count, uint32_t first_index) override; virtual void read_pixels(Handle ctx, const Rect& rect, PixelFormat format, tcb::span out) override; + virtual void set_stencil_reference(Handle ctx, CullMode face, uint8_t reference) override; + virtual void set_stencil_compare_mask(Handle ctx, CullMode face, uint8_t mask) override; + virtual void set_stencil_write_mask(Handle ctx, CullMode face, uint8_t mask) override; virtual void present() override; diff --git a/src/rhi/rhi.hpp b/src/rhi/rhi.hpp index 0187cf9fc..20f0bb7ae 100644 --- a/src/rhi/rhi.hpp +++ b/src/rhi/rhi.hpp @@ -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 ctx, uint32_t index_count, uint32_t first_index) = 0; virtual void read_pixels(Handle ctx, const Rect& rect, PixelFormat format, tcb::span out) = 0; + virtual void set_stencil_reference(Handle ctx, CullMode face, uint8_t reference) = 0; + virtual void set_stencil_compare_mask(Handle ctx, CullMode face, uint8_t mask) = 0; + virtual void set_stencil_write_mask(Handle ctx, CullMode face, uint8_t mask) = 0; virtual void present() = 0;