#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_DYNAMICSTATE_H_ #define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_DYNAMICSTATE_H_ #include "common/assert.h" #include "graphics/host_gpu/renderer/renderTarget.h" #include "graphics/host_gpu/vulkanCommon.h" #include #include #include #include #include namespace Libs::Graphics { struct GraphicContext; struct StencilOps { vk::StencilOp fail_op {}; vk::StencilOp pass_op {}; vk::StencilOp depth_fail_op {}; vk::CompareOp compare_op {}; bool operator==(const StencilOps& other) const { return fail_op == other.fail_op && pass_op == other.pass_op && depth_fail_op == other.depth_fail_op && compare_op == other.compare_op; } }; struct DynamicState { struct { bool viewports : 1; bool scissors : 1; bool depth_test_enabled : 1; bool depth_write_enabled : 1; bool depth_compare_op : 1; bool depth_bounds_test_enabled : 1; bool depth_bounds : 1; bool depth_bias_enabled : 1; bool depth_bias : 1; bool stencil_test_enabled : 1; bool stencil_front_ops : 1; bool stencil_front_reference : 1; bool stencil_front_write_mask : 1; bool stencil_front_compare_mask : 1; bool stencil_back_ops : 1; bool stencil_back_reference : 1; bool stencil_back_write_mask : 1; bool stencil_back_compare_mask : 1; bool blend_constants : 1; bool color_write_enables : 1; bool line_width : 1; bool feedback_loop_aspects : 1; } dirty_state {}; std::array viewports {}; std::array scissors {}; uint32_t num_viewports {}; uint32_t num_scissors {}; bool depth_test_enabled {}; bool depth_write_enabled {}; vk::CompareOp depth_compare_op {}; bool depth_bounds_test_enabled {}; float depth_bounds_min {}; float depth_bounds_max {}; bool depth_bias_enabled {}; float depth_bias_constant {}; float depth_bias_clamp {}; float depth_bias_slope {}; bool stencil_test_enabled {}; StencilOps stencil_front_ops {}; uint32_t stencil_front_reference {}; uint32_t stencil_front_write_mask {}; uint32_t stencil_front_compare_mask {}; StencilOps stencil_back_ops {}; uint32_t stencil_back_reference {}; uint32_t stencil_back_write_mask {}; uint32_t stencil_back_compare_mask {}; std::array blend_constants {}; std::array color_write_enables {}; uint32_t num_color_write_enables {}; float line_width {}; vk::ImageAspectFlags feedback_loop_aspects {}; /// Commits the dynamic state to the provided command buffer. void Commit(const GraphicContext& graphics, vk::CommandBuffer cmdbuf); /// Invalidates all dynamic state to be flushed into the next command buffer. void Invalidate() { std::memset(&dirty_state, 0xFF, sizeof(dirty_state)); } void SetViewports(std::span viewports_) { EXIT_IF(viewports_.size() > viewports.size()); if (!std::ranges::equal(std::span(viewports).first(num_viewports), viewports_)) { std::ranges::copy(viewports_, viewports.begin()); num_viewports = static_cast(viewports_.size()); dirty_state.viewports = true; } } void SetScissors(std::span scissors_) { EXIT_IF(scissors_.size() > scissors.size()); if (!std::ranges::equal(std::span(scissors).first(num_scissors), scissors_)) { std::ranges::copy(scissors_, scissors.begin()); num_scissors = static_cast(scissors_.size()); dirty_state.scissors = true; } } void SetDepthTestEnabled(const bool enabled) { if (depth_test_enabled != enabled) { depth_test_enabled = enabled; dirty_state.depth_test_enabled = true; } } void SetDepthWriteEnabled(const bool enabled) { if (depth_write_enabled != enabled) { depth_write_enabled = enabled; dirty_state.depth_write_enabled = true; } } void SetDepthCompareOp(const vk::CompareOp compare_op) { if (depth_compare_op != compare_op) { depth_compare_op = compare_op; dirty_state.depth_compare_op = true; } } void SetDepthBoundsTestEnabled(const bool enabled) { if (depth_bounds_test_enabled != enabled) { depth_bounds_test_enabled = enabled; dirty_state.depth_bounds_test_enabled = true; } } void SetDepthBounds(const float min, const float max) { if (depth_bounds_min != min || depth_bounds_max != max) { depth_bounds_min = min; depth_bounds_max = max; dirty_state.depth_bounds = true; } } void SetDepthBiasEnabled(const bool enabled) { if (depth_bias_enabled != enabled) { depth_bias_enabled = enabled; dirty_state.depth_bias_enabled = true; } } void SetDepthBias(const float constant, const float clamp, const float slope) { if (depth_bias_constant != constant || depth_bias_clamp != clamp || depth_bias_slope != slope) { depth_bias_constant = constant; depth_bias_clamp = clamp; depth_bias_slope = slope; dirty_state.depth_bias = true; } } void SetStencilTestEnabled(const bool enabled) { if (stencil_test_enabled != enabled) { stencil_test_enabled = enabled; dirty_state.stencil_test_enabled = true; } } void SetStencilOps(const StencilOps& front_ops, const StencilOps& back_ops) { if (stencil_front_ops != front_ops) { stencil_front_ops = front_ops; dirty_state.stencil_front_ops = true; } if (stencil_back_ops != back_ops) { stencil_back_ops = back_ops; dirty_state.stencil_back_ops = true; } } void SetStencilReferences(const uint32_t front_reference, const uint32_t back_reference) { if (stencil_front_reference != front_reference) { stencil_front_reference = front_reference; dirty_state.stencil_front_reference = true; } if (stencil_back_reference != back_reference) { stencil_back_reference = back_reference; dirty_state.stencil_back_reference = true; } } void SetStencilWriteMasks(const uint32_t front_write_mask, const uint32_t back_write_mask) { if (stencil_front_write_mask != front_write_mask) { stencil_front_write_mask = front_write_mask; dirty_state.stencil_front_write_mask = true; } if (stencil_back_write_mask != back_write_mask) { stencil_back_write_mask = back_write_mask; dirty_state.stencil_back_write_mask = true; } } void SetStencilCompareMasks(const uint32_t front_compare_mask, const uint32_t back_compare_mask) { if (stencil_front_compare_mask != front_compare_mask) { stencil_front_compare_mask = front_compare_mask; dirty_state.stencil_front_compare_mask = true; } if (stencil_back_compare_mask != back_compare_mask) { stencil_back_compare_mask = back_compare_mask; dirty_state.stencil_back_compare_mask = true; } } void SetBlendConstants(const std::array blend_constants_) { if (blend_constants != blend_constants_) { blend_constants = blend_constants_; dirty_state.blend_constants = true; } } void SetColorWriteEnables(std::span enables) { EXIT_IF(enables.size() > color_write_enables.size()); if (!std::ranges::equal(std::span(color_write_enables).first(num_color_write_enables), enables)) { std::ranges::copy(enables, color_write_enables.begin()); num_color_write_enables = static_cast(enables.size()); dirty_state.color_write_enables = true; } } void SetLineWidth(const float width) { if (line_width != width) { line_width = width; dirty_state.line_width = true; } } void SetAttachmentFeedbackLoopAspects(const vk::ImageAspectFlags aspects) { if (feedback_loop_aspects != aspects) { feedback_loop_aspects = aspects; dirty_state.feedback_loop_aspects = true; } } }; } // namespace Libs::Graphics #endif // EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_DYNAMICSTATE_H_