Преглед изворни кода

fixed_pipeline_state: Pack blending state

Reduce FixedPipelineState's size to 364 bytes.
ReinUsesLisp пре 6 година
родитељ
комит
b571c92dfd

+ 158 - 55
src/video_core/renderer_vulkan/fixed_pipeline_state.cpp

@@ -95,71 +95,58 @@ void FixedPipelineState::Rasterizer::Fill(const Maxwell& regs) noexcept {
     std::memcpy(&point_size, &regs.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast
 }
 
-namespace {
-
-constexpr FixedPipelineState::BlendingAttachment GetBlendingAttachmentState(
-    const Maxwell& regs, std::size_t render_target) {
-    const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : render_target];
-    const std::array components = {mask.R != 0, mask.G != 0, mask.B != 0, mask.A != 0};
-
-    const FixedPipelineState::BlendingAttachment default_blending(
-        false, Maxwell::Blend::Equation::Add, Maxwell::Blend::Factor::One,
-        Maxwell::Blend::Factor::Zero, Maxwell::Blend::Equation::Add, Maxwell::Blend::Factor::One,
-        Maxwell::Blend::Factor::Zero, components);
-    if (render_target >= regs.rt_control.count) {
-        return default_blending;
+void FixedPipelineState::ColorBlending::Fill(const Maxwell& regs) noexcept {
+    for (std::size_t index = 0; index < std::size(attachments); ++index) {
+        attachments[index].Fill(regs, index);
     }
+}
+
+void FixedPipelineState::BlendingAttachment::Fill(const Maxwell& regs, std::size_t index) {
+    const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index];
+
+    raw = 0;
+    mask_r.Assign(mask.R);
+    mask_g.Assign(mask.G);
+    mask_b.Assign(mask.B);
+    mask_a.Assign(mask.A);
+
+    // TODO: C++20 Use templated lambda to deduplicate code
 
     if (!regs.independent_blend_enable) {
         const auto& src = regs.blend;
-        if (!src.enable[render_target]) {
-            return default_blending;
+        if (!src.enable[index]) {
+            return;
         }
-        return FixedPipelineState::BlendingAttachment(
-            true, src.equation_rgb, src.factor_source_rgb, src.factor_dest_rgb, src.equation_a,
-            src.factor_source_a, src.factor_dest_a, components);
+        equation_rgb.Assign(PackBlendEquation(src.equation_rgb));
+        equation_a.Assign(PackBlendEquation(src.equation_a));
+        factor_source_rgb.Assign(PackBlendFactor(src.factor_source_rgb));
+        factor_dest_rgb.Assign(PackBlendFactor(src.factor_dest_rgb));
+        factor_source_a.Assign(PackBlendFactor(src.factor_source_a));
+        factor_dest_a.Assign(PackBlendFactor(src.factor_dest_a));
+        enable.Assign(1);
+        return;
     }
 
-    if (!regs.blend.enable[render_target]) {
-        return default_blending;
+    if (!regs.blend.enable[index]) {
+        return;
     }
-    const auto& src = regs.independent_blend[render_target];
-    return FixedPipelineState::BlendingAttachment(
-        true, src.equation_rgb, src.factor_source_rgb, src.factor_dest_rgb, src.equation_a,
-        src.factor_source_a, src.factor_dest_a, components);
-}
-
-constexpr FixedPipelineState::ColorBlending GetColorBlendingState(const Maxwell& regs) {
-    return FixedPipelineState::ColorBlending(
-        {regs.blend_color.r, regs.blend_color.g, regs.blend_color.b, regs.blend_color.a},
-        regs.rt_control.count,
-        {GetBlendingAttachmentState(regs, 0), GetBlendingAttachmentState(regs, 1),
-         GetBlendingAttachmentState(regs, 2), GetBlendingAttachmentState(regs, 3),
-         GetBlendingAttachmentState(regs, 4), GetBlendingAttachmentState(regs, 5),
-         GetBlendingAttachmentState(regs, 6), GetBlendingAttachmentState(regs, 7)});
+    const auto& src = regs.independent_blend[index];
+    equation_rgb.Assign(PackBlendEquation(src.equation_rgb));
+    equation_a.Assign(PackBlendEquation(src.equation_a));
+    factor_source_rgb.Assign(PackBlendFactor(src.factor_source_rgb));
+    factor_dest_rgb.Assign(PackBlendFactor(src.factor_dest_rgb));
+    factor_source_a.Assign(PackBlendFactor(src.factor_source_a));
+    factor_dest_a.Assign(PackBlendFactor(src.factor_dest_a));
+    enable.Assign(1);
 }
 
-} // Anonymous namespace
-
 std::size_t FixedPipelineState::BlendingAttachment::Hash() const noexcept {
-    return static_cast<std::size_t>(enable) ^ (static_cast<std::size_t>(rgb_equation) << 5) ^
-           (static_cast<std::size_t>(src_rgb_func) << 10) ^
-           (static_cast<std::size_t>(dst_rgb_func) << 15) ^
-           (static_cast<std::size_t>(a_equation) << 20) ^
-           (static_cast<std::size_t>(src_a_func) << 25) ^
-           (static_cast<std::size_t>(dst_a_func) << 30) ^
-           (static_cast<std::size_t>(components[0]) << 35) ^
-           (static_cast<std::size_t>(components[1]) << 36) ^
-           (static_cast<std::size_t>(components[2]) << 37) ^
-           (static_cast<std::size_t>(components[3]) << 38);
+    return raw;
 }
 
 bool FixedPipelineState::BlendingAttachment::operator==(const BlendingAttachment& rhs) const
     noexcept {
-    return std::tie(enable, rgb_equation, src_rgb_func, dst_rgb_func, a_equation, src_a_func,
-                    dst_a_func, components) ==
-           std::tie(rhs.enable, rhs.rgb_equation, rhs.src_rgb_func, rhs.dst_rgb_func,
-                    rhs.a_equation, rhs.src_a_func, rhs.dst_a_func, rhs.components);
+    return raw == rhs.raw;
 }
 
 std::size_t FixedPipelineState::VertexInput::Hash() const noexcept {
@@ -190,16 +177,15 @@ bool FixedPipelineState::DepthStencil::operator==(const DepthStencil& rhs) const
 }
 
 std::size_t FixedPipelineState::ColorBlending::Hash() const noexcept {
-    std::size_t hash = attachments_count << 13;
-    for (std::size_t rt = 0; rt < static_cast<std::size_t>(attachments_count); ++rt) {
+    std::size_t hash = 0;
+    for (std::size_t rt = 0; rt < std::size(attachments); ++rt) {
         boost::hash_combine(hash, attachments[rt].Hash());
     }
     return hash;
 }
 
 bool FixedPipelineState::ColorBlending::operator==(const ColorBlending& rhs) const noexcept {
-    return std::equal(attachments.begin(), attachments.begin() + attachments_count,
-                      rhs.attachments.begin(), rhs.attachments.begin() + rhs.attachments_count);
+    return attachments == rhs.attachments;
 }
 
 std::size_t FixedPipelineState::Hash() const noexcept {
@@ -220,7 +206,7 @@ FixedPipelineState GetFixedPipelineState(const Maxwell& regs) {
     FixedPipelineState fixed_state;
     fixed_state.rasterizer.Fill(regs);
     fixed_state.depth_stencil.Fill(regs);
-    fixed_state.color_blending = GetColorBlendingState(regs);
+    fixed_state.color_blending.Fill(regs);
     return fixed_state;
 }
 
@@ -312,4 +298,121 @@ Maxwell::LogicOperation FixedPipelineState::UnpackLogicOp(u32 packed) noexcept {
     return static_cast<Maxwell::LogicOperation>(packed + 0x1500);
 }
 
+u32 FixedPipelineState::PackBlendEquation(Maxwell::Blend::Equation equation) noexcept {
+    switch (equation) {
+    case Maxwell::Blend::Equation::Add:
+    case Maxwell::Blend::Equation::AddGL:
+        return 0;
+    case Maxwell::Blend::Equation::Subtract:
+    case Maxwell::Blend::Equation::SubtractGL:
+        return 1;
+    case Maxwell::Blend::Equation::ReverseSubtract:
+    case Maxwell::Blend::Equation::ReverseSubtractGL:
+        return 2;
+    case Maxwell::Blend::Equation::Min:
+    case Maxwell::Blend::Equation::MinGL:
+        return 3;
+    case Maxwell::Blend::Equation::Max:
+    case Maxwell::Blend::Equation::MaxGL:
+        return 4;
+    }
+    return 0;
+}
+
+Maxwell::Blend::Equation FixedPipelineState::UnpackBlendEquation(u32 packed) noexcept {
+    static constexpr std::array LUT = {
+        Maxwell::Blend::Equation::Add, Maxwell::Blend::Equation::Subtract,
+        Maxwell::Blend::Equation::ReverseSubtract, Maxwell::Blend::Equation::Min,
+        Maxwell::Blend::Equation::Max};
+    return LUT[packed];
+}
+
+u32 FixedPipelineState::PackBlendFactor(Maxwell::Blend::Factor factor) noexcept {
+    switch (factor) {
+    case Maxwell::Blend::Factor::Zero:
+    case Maxwell::Blend::Factor::ZeroGL:
+        return 0;
+    case Maxwell::Blend::Factor::One:
+    case Maxwell::Blend::Factor::OneGL:
+        return 1;
+    case Maxwell::Blend::Factor::SourceColor:
+    case Maxwell::Blend::Factor::SourceColorGL:
+        return 2;
+    case Maxwell::Blend::Factor::OneMinusSourceColor:
+    case Maxwell::Blend::Factor::OneMinusSourceColorGL:
+        return 3;
+    case Maxwell::Blend::Factor::SourceAlpha:
+    case Maxwell::Blend::Factor::SourceAlphaGL:
+        return 4;
+    case Maxwell::Blend::Factor::OneMinusSourceAlpha:
+    case Maxwell::Blend::Factor::OneMinusSourceAlphaGL:
+        return 5;
+    case Maxwell::Blend::Factor::DestAlpha:
+    case Maxwell::Blend::Factor::DestAlphaGL:
+        return 6;
+    case Maxwell::Blend::Factor::OneMinusDestAlpha:
+    case Maxwell::Blend::Factor::OneMinusDestAlphaGL:
+        return 7;
+    case Maxwell::Blend::Factor::DestColor:
+    case Maxwell::Blend::Factor::DestColorGL:
+        return 8;
+    case Maxwell::Blend::Factor::OneMinusDestColor:
+    case Maxwell::Blend::Factor::OneMinusDestColorGL:
+        return 9;
+    case Maxwell::Blend::Factor::SourceAlphaSaturate:
+    case Maxwell::Blend::Factor::SourceAlphaSaturateGL:
+        return 10;
+    case Maxwell::Blend::Factor::Source1Color:
+    case Maxwell::Blend::Factor::Source1ColorGL:
+        return 11;
+    case Maxwell::Blend::Factor::OneMinusSource1Color:
+    case Maxwell::Blend::Factor::OneMinusSource1ColorGL:
+        return 12;
+    case Maxwell::Blend::Factor::Source1Alpha:
+    case Maxwell::Blend::Factor::Source1AlphaGL:
+        return 13;
+    case Maxwell::Blend::Factor::OneMinusSource1Alpha:
+    case Maxwell::Blend::Factor::OneMinusSource1AlphaGL:
+        return 14;
+    case Maxwell::Blend::Factor::ConstantColor:
+    case Maxwell::Blend::Factor::ConstantColorGL:
+        return 15;
+    case Maxwell::Blend::Factor::OneMinusConstantColor:
+    case Maxwell::Blend::Factor::OneMinusConstantColorGL:
+        return 16;
+    case Maxwell::Blend::Factor::ConstantAlpha:
+    case Maxwell::Blend::Factor::ConstantAlphaGL:
+        return 17;
+    case Maxwell::Blend::Factor::OneMinusConstantAlpha:
+    case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
+        return 18;
+    }
+    return 0;
+}
+
+Maxwell::Blend::Factor FixedPipelineState::UnpackBlendFactor(u32 packed) noexcept {
+    static constexpr std::array LUT = {
+        Maxwell::Blend::Factor::Zero,
+        Maxwell::Blend::Factor::One,
+        Maxwell::Blend::Factor::SourceColor,
+        Maxwell::Blend::Factor::OneMinusSourceColor,
+        Maxwell::Blend::Factor::SourceAlpha,
+        Maxwell::Blend::Factor::OneMinusSourceAlpha,
+        Maxwell::Blend::Factor::DestAlpha,
+        Maxwell::Blend::Factor::OneMinusDestAlpha,
+        Maxwell::Blend::Factor::DestColor,
+        Maxwell::Blend::Factor::OneMinusDestColor,
+        Maxwell::Blend::Factor::SourceAlphaSaturate,
+        Maxwell::Blend::Factor::Source1Color,
+        Maxwell::Blend::Factor::OneMinusSource1Color,
+        Maxwell::Blend::Factor::Source1Alpha,
+        Maxwell::Blend::Factor::OneMinusSource1Alpha,
+        Maxwell::Blend::Factor::ConstantColor,
+        Maxwell::Blend::Factor::OneMinusConstantColor,
+        Maxwell::Blend::Factor::ConstantAlpha,
+        Maxwell::Blend::Factor::OneMinusConstantAlpha,
+    };
+    return LUT[packed];
+}
+
 } // namespace Vulkan

+ 54 - 27
src/video_core/renderer_vulkan/fixed_pipeline_state.h

@@ -42,27 +42,29 @@ struct FixedPipelineState {
     static u32 PackLogicOp(Maxwell::LogicOperation op) noexcept;
     static Maxwell::LogicOperation UnpackLogicOp(u32 packed) noexcept;
 
+    static u32 PackBlendEquation(Maxwell::Blend::Equation equation) noexcept;
+    static Maxwell::Blend::Equation UnpackBlendEquation(u32 packed) noexcept;
+
+    static u32 PackBlendFactor(Maxwell::Blend::Factor factor) noexcept;
+    static Maxwell::Blend::Factor UnpackBlendFactor(u32 packed) noexcept;
+
     struct BlendingAttachment {
-        constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation,
-                                     Maxwell::Blend::Factor src_rgb_func,
-                                     Maxwell::Blend::Factor dst_rgb_func,
-                                     Maxwell::Blend::Equation a_equation,
-                                     Maxwell::Blend::Factor src_a_func,
-                                     Maxwell::Blend::Factor dst_a_func,
-                                     std::array<bool, 4> components)
-            : enable{enable}, rgb_equation{rgb_equation}, src_rgb_func{src_rgb_func},
-              dst_rgb_func{dst_rgb_func}, a_equation{a_equation}, src_a_func{src_a_func},
-              dst_a_func{dst_a_func}, components{components} {}
-        BlendingAttachment() = default;
-
-        bool enable;
-        Maxwell::Blend::Equation rgb_equation;
-        Maxwell::Blend::Factor src_rgb_func;
-        Maxwell::Blend::Factor dst_rgb_func;
-        Maxwell::Blend::Equation a_equation;
-        Maxwell::Blend::Factor src_a_func;
-        Maxwell::Blend::Factor dst_a_func;
-        std::array<bool, 4> components;
+        union {
+            u32 raw;
+            BitField<0, 1, u32> mask_r;
+            BitField<1, 1, u32> mask_g;
+            BitField<2, 1, u32> mask_b;
+            BitField<3, 1, u32> mask_a;
+            BitField<4, 3, u32> equation_rgb;
+            BitField<7, 3, u32> equation_a;
+            BitField<10, 5, u32> factor_source_rgb;
+            BitField<15, 5, u32> factor_dest_rgb;
+            BitField<20, 5, u32> factor_source_a;
+            BitField<25, 5, u32> factor_dest_a;
+            BitField<30, 1, u32> enable;
+        };
+
+        void Fill(const Maxwell& regs, std::size_t index);
 
         std::size_t Hash() const noexcept;
 
@@ -71,7 +73,36 @@ struct FixedPipelineState {
         bool operator!=(const BlendingAttachment& rhs) const noexcept {
             return !operator==(rhs);
         }
+
+        constexpr std::array<bool, 4> Mask() const noexcept {
+            return {mask_r != 0, mask_g != 0, mask_b != 0, mask_a != 0};
+        }
+
+        Maxwell::Blend::Equation EquationRGB() const noexcept {
+            return UnpackBlendEquation(equation_rgb.Value());
+        }
+
+        Maxwell::Blend::Equation EquationAlpha() const noexcept {
+            return UnpackBlendEquation(equation_a.Value());
+        }
+
+        Maxwell::Blend::Factor SourceRGBFactor() const noexcept {
+            return UnpackBlendFactor(factor_source_rgb.Value());
+        }
+
+        Maxwell::Blend::Factor DestRGBFactor() const noexcept {
+            return UnpackBlendFactor(factor_dest_rgb.Value());
+        }
+
+        Maxwell::Blend::Factor SourceAlphaFactor() const noexcept {
+            return UnpackBlendFactor(factor_source_a.Value());
+        }
+
+        Maxwell::Blend::Factor DestAlphaFactor() const noexcept {
+            return UnpackBlendFactor(factor_dest_a.Value());
+        }
     };
+    static_assert(IsHashable<BlendingAttachment>);
 
     struct VertexInput {
         union Binding {
@@ -231,15 +262,10 @@ struct FixedPipelineState {
     static_assert(IsHashable<DepthStencil>);
 
     struct ColorBlending {
-        constexpr ColorBlending(
-            std::array<float, 4> blend_constants, std::size_t attachments_count,
-            std::array<BlendingAttachment, Maxwell::NumRenderTargets> attachments)
-            : attachments_count{attachments_count}, attachments{attachments} {}
-        ColorBlending() = default;
-
-        std::size_t attachments_count;
         std::array<BlendingAttachment, Maxwell::NumRenderTargets> attachments;
 
+        void Fill(const Maxwell& regs) noexcept;
+
         std::size_t Hash() const noexcept;
 
         bool operator==(const ColorBlending& rhs) const noexcept;
@@ -248,6 +274,7 @@ struct FixedPipelineState {
             return !operator==(rhs);
         }
     };
+    static_assert(IsHashable<ColorBlending>);
 
     VertexInput vertex_input;
     Rasterizer rasterizer;

+ 15 - 16
src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp

@@ -286,29 +286,28 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
     depth_stencil_ci.maxDepthBounds = 0.0f;
 
     std::array<VkPipelineColorBlendAttachmentState, Maxwell::NumRenderTargets> cb_attachments;
-    const std::size_t num_attachments =
-        std::min(cd.attachments_count, renderpass_params.color_attachments.size());
-    for (std::size_t i = 0; i < num_attachments; ++i) {
-        static constexpr std::array component_table = {
+    const std::size_t num_attachments = renderpass_params.color_attachments.size();
+    for (std::size_t index = 0; index < num_attachments; ++index) {
+        static constexpr std::array COMPONENT_TABLE = {
             VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT,
             VK_COLOR_COMPONENT_A_BIT};
-        const auto& blend = cd.attachments[i];
+        const auto& blend = cd.attachments[index];
 
         VkColorComponentFlags color_components = 0;
-        for (std::size_t j = 0; j < component_table.size(); ++j) {
-            if (blend.components[j]) {
-                color_components |= component_table[j];
+        for (std::size_t i = 0; i < COMPONENT_TABLE.size(); ++i) {
+            if (blend.Mask()[i]) {
+                color_components |= COMPONENT_TABLE[i];
             }
         }
 
-        VkPipelineColorBlendAttachmentState& attachment = cb_attachments[i];
-        attachment.blendEnable = blend.enable;
-        attachment.srcColorBlendFactor = MaxwellToVK::BlendFactor(blend.src_rgb_func);
-        attachment.dstColorBlendFactor = MaxwellToVK::BlendFactor(blend.dst_rgb_func);
-        attachment.colorBlendOp = MaxwellToVK::BlendEquation(blend.rgb_equation);
-        attachment.srcAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.src_a_func);
-        attachment.dstAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.dst_a_func);
-        attachment.alphaBlendOp = MaxwellToVK::BlendEquation(blend.a_equation);
+        VkPipelineColorBlendAttachmentState& attachment = cb_attachments[index];
+        attachment.blendEnable = blend.enable != 0;
+        attachment.srcColorBlendFactor = MaxwellToVK::BlendFactor(blend.SourceRGBFactor());
+        attachment.dstColorBlendFactor = MaxwellToVK::BlendFactor(blend.DestRGBFactor());
+        attachment.colorBlendOp = MaxwellToVK::BlendEquation(blend.EquationRGB());
+        attachment.srcAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.SourceAlphaFactor());
+        attachment.dstAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.DestAlphaFactor());
+        attachment.alphaBlendOp = MaxwellToVK::BlendEquation(blend.EquationAlpha());
         attachment.colorWriteMask = color_components;
     }