Vulkan: Implement Dynamic States 2
This commit is contained in:
		@@ -48,23 +48,16 @@ void RefreshXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell&
 | 
			
		||||
}
 | 
			
		||||
} // Anonymous namespace
 | 
			
		||||
 | 
			
		||||
void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d,
 | 
			
		||||
                                 bool has_extended_dynamic_state, bool has_dynamic_vertex_input) {
 | 
			
		||||
void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFeatures& features) {
 | 
			
		||||
    const Maxwell& regs = maxwell3d.regs;
 | 
			
		||||
    const auto topology_ = maxwell3d.draw_manager->GetDrawState().topology;
 | 
			
		||||
    const std::array enabled_lut{
 | 
			
		||||
        regs.polygon_offset_point_enable,
 | 
			
		||||
        regs.polygon_offset_line_enable,
 | 
			
		||||
        regs.polygon_offset_fill_enable,
 | 
			
		||||
    };
 | 
			
		||||
    const u32 topology_index = static_cast<u32>(topology_);
 | 
			
		||||
 | 
			
		||||
    raw1 = 0;
 | 
			
		||||
    extended_dynamic_state.Assign(has_extended_dynamic_state ? 1 : 0);
 | 
			
		||||
    dynamic_vertex_input.Assign(has_dynamic_vertex_input ? 1 : 0);
 | 
			
		||||
    extended_dynamic_state.Assign(features.has_extended_dynamic_state ? 1 : 0);
 | 
			
		||||
    extended_dynamic_state_2.Assign(features.has_extended_dynamic_state_2 ? 1 : 0);
 | 
			
		||||
    extended_dynamic_state_3.Assign(features.has_extended_dynamic_state_3 ? 1 : 0);
 | 
			
		||||
    dynamic_vertex_input.Assign(features.has_dynamic_vertex_input ? 1 : 0);
 | 
			
		||||
    xfb_enabled.Assign(regs.transform_feedback_enabled != 0);
 | 
			
		||||
    primitive_restart_enable.Assign(regs.primitive_restart.enabled != 0 ? 1 : 0);
 | 
			
		||||
    depth_bias_enable.Assign(enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]] != 0 ? 1 : 0);
 | 
			
		||||
    depth_clamp_disabled.Assign(regs.viewport_clip_control.geometry_clip ==
 | 
			
		||||
                                    Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
 | 
			
		||||
                                regs.viewport_clip_control.geometry_clip ==
 | 
			
		||||
@@ -84,7 +77,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d,
 | 
			
		||||
    msaa_mode.Assign(regs.anti_alias_samples_mode);
 | 
			
		||||
 | 
			
		||||
    raw2 = 0;
 | 
			
		||||
    rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0);
 | 
			
		||||
 | 
			
		||||
    const auto test_func =
 | 
			
		||||
        regs.alpha_test_enabled != 0 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always_GL;
 | 
			
		||||
    alpha_test_func.Assign(PackComparisonOp(test_func));
 | 
			
		||||
@@ -106,7 +99,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d,
 | 
			
		||||
    point_size = Common::BitCast<u32>(regs.point_size);
 | 
			
		||||
 | 
			
		||||
    if (maxwell3d.dirty.flags[Dirty::VertexInput]) {
 | 
			
		||||
        if (has_dynamic_vertex_input) {
 | 
			
		||||
        if (features.has_dynamic_vertex_input) {
 | 
			
		||||
            // Dirty flag will be reset by the command buffer update
 | 
			
		||||
            static constexpr std::array LUT{
 | 
			
		||||
                0u, // Invalid
 | 
			
		||||
@@ -158,9 +151,17 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d,
 | 
			
		||||
            return static_cast<u16>(viewport.swizzle.raw);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    dynamic_state.raw1 = 0;
 | 
			
		||||
    dynamic_state.raw2 = 0;
 | 
			
		||||
    if (!extended_dynamic_state) {
 | 
			
		||||
        dynamic_state.Refresh(regs);
 | 
			
		||||
    }
 | 
			
		||||
    if (!extended_dynamic_state_2) {
 | 
			
		||||
        dynamic_state.Refresh2(regs, topology);
 | 
			
		||||
    }
 | 
			
		||||
    if (!extended_dynamic_state_3) {
 | 
			
		||||
        dynamic_state.Refresh3(regs);
 | 
			
		||||
    }
 | 
			
		||||
    if (xfb_enabled) {
 | 
			
		||||
        RefreshXfbState(xfb_state, regs);
 | 
			
		||||
    }
 | 
			
		||||
@@ -212,8 +213,6 @@ void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) {
 | 
			
		||||
        packed_front_face = 1 - packed_front_face;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    raw1 = 0;
 | 
			
		||||
    raw2 = 0;
 | 
			
		||||
    front.action_stencil_fail.Assign(PackStencilOp(regs.stencil_front_op.fail));
 | 
			
		||||
    front.action_depth_fail.Assign(PackStencilOp(regs.stencil_front_op.zfail));
 | 
			
		||||
    front.action_depth_pass.Assign(PackStencilOp(regs.stencil_front_op.zpass));
 | 
			
		||||
@@ -242,6 +241,21 @@ void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) {
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FixedPipelineState::DynamicState::Refresh2(const Maxwell& regs, Maxwell::PrimitiveTopology topology_) {
 | 
			
		||||
    const std::array enabled_lut{
 | 
			
		||||
        regs.polygon_offset_point_enable,
 | 
			
		||||
        regs.polygon_offset_line_enable,
 | 
			
		||||
        regs.polygon_offset_fill_enable,
 | 
			
		||||
    };
 | 
			
		||||
    const u32 topology_index = static_cast<u32>(topology_);
 | 
			
		||||
 | 
			
		||||
    rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0);
 | 
			
		||||
    primitive_restart_enable.Assign(regs.primitive_restart.enabled != 0 ? 1 : 0);
 | 
			
		||||
    depth_bias_enable.Assign(enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]] != 0 ? 1 : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FixedPipelineState::DynamicState::Refresh3(const Maxwell&) {}
 | 
			
		||||
 | 
			
		||||
size_t FixedPipelineState::Hash() const noexcept {
 | 
			
		||||
    const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), Size());
 | 
			
		||||
    return static_cast<size_t>(hash);
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,14 @@ namespace Vulkan {
 | 
			
		||||
 | 
			
		||||
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
 | 
			
		||||
 | 
			
		||||
struct DynamicFeatures {
 | 
			
		||||
    bool has_extended_dynamic_state;
 | 
			
		||||
    bool has_extended_dynamic_state_2;
 | 
			
		||||
    bool has_extended_dynamic_state_2_extra;
 | 
			
		||||
    bool has_extended_dynamic_state_3;
 | 
			
		||||
    bool has_dynamic_vertex_input;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct FixedPipelineState {
 | 
			
		||||
    static u32 PackComparisonOp(Maxwell::ComparisonOp op) noexcept;
 | 
			
		||||
    static Maxwell::ComparisonOp UnpackComparisonOp(u32 packed) noexcept;
 | 
			
		||||
@@ -133,6 +141,14 @@ struct FixedPipelineState {
 | 
			
		||||
    struct DynamicState {
 | 
			
		||||
        union {
 | 
			
		||||
            u32 raw1;
 | 
			
		||||
            BitField<0, 2, u32> cull_face;
 | 
			
		||||
            BitField<2, 1, u32> cull_enable;
 | 
			
		||||
            BitField<3, 1, u32> primitive_restart_enable;
 | 
			
		||||
            BitField<4, 1, u32> depth_bias_enable;
 | 
			
		||||
            BitField<5, 1, u32> rasterize_enable;
 | 
			
		||||
        };
 | 
			
		||||
        union {
 | 
			
		||||
            u32 raw2;
 | 
			
		||||
            StencilFace<0> front;
 | 
			
		||||
            StencilFace<12> back;
 | 
			
		||||
            BitField<24, 1, u32> stencil_enable;
 | 
			
		||||
@@ -142,15 +158,12 @@ struct FixedPipelineState {
 | 
			
		||||
            BitField<28, 1, u32> front_face;
 | 
			
		||||
            BitField<29, 3, u32> depth_test_func;
 | 
			
		||||
        };
 | 
			
		||||
        union {
 | 
			
		||||
            u32 raw2;
 | 
			
		||||
            BitField<0, 2, u32> cull_face;
 | 
			
		||||
            BitField<2, 1, u32> cull_enable;
 | 
			
		||||
        };
 | 
			
		||||
        // Vertex stride is a 12 bits value, we have 4 bits to spare per element
 | 
			
		||||
        std::array<u16, Maxwell::NumVertexArrays> vertex_strides;
 | 
			
		||||
 | 
			
		||||
        void Refresh(const Maxwell& regs);
 | 
			
		||||
        void Refresh2(const Maxwell& regs, Maxwell::PrimitiveTopology topology);
 | 
			
		||||
        void Refresh3(const Maxwell& regs);
 | 
			
		||||
 | 
			
		||||
        Maxwell::ComparisonOp DepthTestFunc() const noexcept {
 | 
			
		||||
            return UnpackComparisonOp(depth_test_func);
 | 
			
		||||
@@ -168,10 +181,10 @@ struct FixedPipelineState {
 | 
			
		||||
    union {
 | 
			
		||||
        u32 raw1;
 | 
			
		||||
        BitField<0, 1, u32> extended_dynamic_state;
 | 
			
		||||
        BitField<1, 1, u32> dynamic_vertex_input;
 | 
			
		||||
        BitField<2, 1, u32> xfb_enabled;
 | 
			
		||||
        BitField<3, 1, u32> primitive_restart_enable;
 | 
			
		||||
        BitField<4, 1, u32> depth_bias_enable;
 | 
			
		||||
        BitField<1, 1, u32> extended_dynamic_state_2;
 | 
			
		||||
        BitField<2, 1, u32> extended_dynamic_state_3;
 | 
			
		||||
        BitField<3, 1, u32> dynamic_vertex_input;
 | 
			
		||||
        BitField<4, 1, u32> xfb_enabled;
 | 
			
		||||
        BitField<5, 1, u32> depth_clamp_disabled;
 | 
			
		||||
        BitField<6, 1, u32> ndc_minus_one_to_one;
 | 
			
		||||
        BitField<7, 2, u32> polygon_mode;
 | 
			
		||||
@@ -186,7 +199,6 @@ struct FixedPipelineState {
 | 
			
		||||
    };
 | 
			
		||||
    union {
 | 
			
		||||
        u32 raw2;
 | 
			
		||||
        BitField<0, 1, u32> rasterize_enable;
 | 
			
		||||
        BitField<1, 3, u32> alpha_test_func;
 | 
			
		||||
        BitField<4, 1, u32> early_z;
 | 
			
		||||
        BitField<5, 1, u32> depth_enabled;
 | 
			
		||||
@@ -215,8 +227,7 @@ struct FixedPipelineState {
 | 
			
		||||
    DynamicState dynamic_state;
 | 
			
		||||
    VideoCommon::TransformFeedbackState xfb_state;
 | 
			
		||||
 | 
			
		||||
    void Refresh(Tegra::Engines::Maxwell3D& maxwell3d, bool has_extended_dynamic_state,
 | 
			
		||||
                 bool has_dynamic_vertex_input);
 | 
			
		||||
    void Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFeatures& features);
 | 
			
		||||
 | 
			
		||||
    size_t Hash() const noexcept;
 | 
			
		||||
 | 
			
		||||
@@ -231,14 +242,18 @@ struct FixedPipelineState {
 | 
			
		||||
            // When transform feedback is enabled, use the whole struct
 | 
			
		||||
            return sizeof(*this);
 | 
			
		||||
        }
 | 
			
		||||
        if (dynamic_vertex_input) {
 | 
			
		||||
        if (dynamic_vertex_input && extended_dynamic_state_2) {
 | 
			
		||||
            // Exclude dynamic state and attributes
 | 
			
		||||
            return offsetof(FixedPipelineState, attributes);
 | 
			
		||||
        }
 | 
			
		||||
        if (extended_dynamic_state) {
 | 
			
		||||
        if (extended_dynamic_state_2) {
 | 
			
		||||
            // Exclude dynamic state
 | 
			
		||||
            return offsetof(FixedPipelineState, dynamic_state);
 | 
			
		||||
        }
 | 
			
		||||
        if (extended_dynamic_state) {
 | 
			
		||||
            // Exclude dynamic state
 | 
			
		||||
            return offsetof(FixedPipelineState, dynamic_state.raw2);
 | 
			
		||||
        }
 | 
			
		||||
        // Default
 | 
			
		||||
        return offsetof(FixedPipelineState, xfb_state);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -525,6 +525,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
 | 
			
		||||
    if (!key.state.extended_dynamic_state) {
 | 
			
		||||
        dynamic = key.state.dynamic_state;
 | 
			
		||||
    }
 | 
			
		||||
    if (!key.state.extended_dynamic_state_2) {
 | 
			
		||||
        dynamic.raw2 = key.state.dynamic_state.raw2;
 | 
			
		||||
    }
 | 
			
		||||
    static_vector<VkVertexInputBindingDescription, 32> vertex_bindings;
 | 
			
		||||
    static_vector<VkVertexInputBindingDivisorDescriptionEXT, 32> vertex_binding_divisors;
 | 
			
		||||
    static_vector<VkVertexInputAttributeDescription, 32> vertex_attributes;
 | 
			
		||||
@@ -625,7 +628,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
 | 
			
		||||
        .pNext = nullptr,
 | 
			
		||||
        .flags = 0,
 | 
			
		||||
        .topology = input_assembly_topology,
 | 
			
		||||
        .primitiveRestartEnable = key.state.primitive_restart_enable != 0 &&
 | 
			
		||||
        .primitiveRestartEnable = key.state.dynamic_state.primitive_restart_enable != 0 &&
 | 
			
		||||
                                  ((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
 | 
			
		||||
                                    device.IsTopologyListPrimitiveRestartSupported()) ||
 | 
			
		||||
                                   SupportsPrimitiveRestart(input_assembly_topology) ||
 | 
			
		||||
@@ -674,13 +677,13 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
 | 
			
		||||
        .depthClampEnable =
 | 
			
		||||
            static_cast<VkBool32>(key.state.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE),
 | 
			
		||||
        .rasterizerDiscardEnable =
 | 
			
		||||
            static_cast<VkBool32>(key.state.rasterize_enable == 0 ? VK_TRUE : VK_FALSE),
 | 
			
		||||
            static_cast<VkBool32>(dynamic.rasterize_enable == 0 ? VK_TRUE : VK_FALSE),
 | 
			
		||||
        .polygonMode =
 | 
			
		||||
            MaxwellToVK::PolygonMode(FixedPipelineState::UnpackPolygonMode(key.state.polygon_mode)),
 | 
			
		||||
        .cullMode = static_cast<VkCullModeFlags>(
 | 
			
		||||
            dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE),
 | 
			
		||||
        .frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()),
 | 
			
		||||
        .depthBiasEnable = key.state.depth_bias_enable,
 | 
			
		||||
        .depthBiasEnable = (dynamic.depth_bias_enable == 0 ? VK_TRUE : VK_FALSE),
 | 
			
		||||
        .depthBiasConstantFactor = 0.0f,
 | 
			
		||||
        .depthBiasClamp = 0.0f,
 | 
			
		||||
        .depthBiasSlopeFactor = 0.0f,
 | 
			
		||||
@@ -788,7 +791,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
 | 
			
		||||
        .pAttachments = cb_attachments.data(),
 | 
			
		||||
        .blendConstants = {},
 | 
			
		||||
    };
 | 
			
		||||
    static_vector<VkDynamicState, 19> dynamic_states{
 | 
			
		||||
    static_vector<VkDynamicState, 22> dynamic_states{
 | 
			
		||||
        VK_DYNAMIC_STATE_VIEWPORT,           VK_DYNAMIC_STATE_SCISSOR,
 | 
			
		||||
        VK_DYNAMIC_STATE_DEPTH_BIAS,         VK_DYNAMIC_STATE_BLEND_CONSTANTS,
 | 
			
		||||
        VK_DYNAMIC_STATE_DEPTH_BOUNDS,       VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
 | 
			
		||||
@@ -811,6 +814,14 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
 | 
			
		||||
            dynamic_states.push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
 | 
			
		||||
        }
 | 
			
		||||
        dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end());
 | 
			
		||||
        if (key.state.extended_dynamic_state_2) {
 | 
			
		||||
            static constexpr std::array extended2{
 | 
			
		||||
                VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT,
 | 
			
		||||
                VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT,
 | 
			
		||||
                VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT,
 | 
			
		||||
            };
 | 
			
		||||
            dynamic_states.insert(dynamic_states.end(), extended2.begin(), extended2.end());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
 | 
			
		||||
        .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
 | 
			
		||||
 
 | 
			
		||||
@@ -351,6 +351,14 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
 | 
			
		||||
        LOG_WARNING(Render_Vulkan, "maxVertexInputBindings is too low: {} < {}",
 | 
			
		||||
                    device.GetMaxVertexInputBindings(), Maxwell::NumVertexArrays);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dynamic_features = DynamicFeatures{
 | 
			
		||||
        .has_extended_dynamic_state = device.IsExtExtendedDynamicStateSupported(),
 | 
			
		||||
        .has_extended_dynamic_state_2 = device.IsExtExtendedDynamicState2Supported(),
 | 
			
		||||
        .has_extended_dynamic_state_2_extra = device.IsExtExtendedDynamicState2ExtrasSupported(),
 | 
			
		||||
        .has_extended_dynamic_state_3 = device.IsExtExtendedDynamicState3Supported(),
 | 
			
		||||
        .has_dynamic_vertex_input = device.IsExtVertexInputDynamicStateSupported(),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PipelineCache::~PipelineCache() = default;
 | 
			
		||||
@@ -362,8 +370,7 @@ GraphicsPipeline* PipelineCache::CurrentGraphicsPipeline() {
 | 
			
		||||
        current_pipeline = nullptr;
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    graphics_key.state.Refresh(*maxwell3d, device.IsExtExtendedDynamicStateSupported(),
 | 
			
		||||
                               device.IsExtVertexInputDynamicStateSupported());
 | 
			
		||||
    graphics_key.state.Refresh(*maxwell3d, dynamic_features);
 | 
			
		||||
 | 
			
		||||
    if (current_pipeline) {
 | 
			
		||||
        GraphicsPipeline* const next{current_pipeline->Next(graphics_key)};
 | 
			
		||||
@@ -439,14 +446,17 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
 | 
			
		||||
        });
 | 
			
		||||
        ++state.total;
 | 
			
		||||
    }};
 | 
			
		||||
    const bool extended_dynamic_state = device.IsExtExtendedDynamicStateSupported();
 | 
			
		||||
    const bool dynamic_vertex_input = device.IsExtVertexInputDynamicStateSupported();
 | 
			
		||||
    const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) {
 | 
			
		||||
        GraphicsPipelineCacheKey key;
 | 
			
		||||
        file.read(reinterpret_cast<char*>(&key), sizeof(key));
 | 
			
		||||
 | 
			
		||||
        if ((key.state.extended_dynamic_state != 0) != extended_dynamic_state ||
 | 
			
		||||
            (key.state.dynamic_vertex_input != 0) != dynamic_vertex_input) {
 | 
			
		||||
        if ((key.state.extended_dynamic_state != 0) !=
 | 
			
		||||
                dynamic_features.has_extended_dynamic_state ||
 | 
			
		||||
            (key.state.extended_dynamic_state_2 != 0) !=
 | 
			
		||||
                dynamic_features.has_extended_dynamic_state_2 ||
 | 
			
		||||
            (key.state.extended_dynamic_state_3 != 0) !=
 | 
			
		||||
                dynamic_features.has_extended_dynamic_state_3 ||
 | 
			
		||||
            (key.state.dynamic_vertex_input != 0) != dynamic_features.has_dynamic_vertex_input) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        workers.QueueWork([this, key, envs = std::move(envs), &state, &callback]() mutable {
 | 
			
		||||
 
 | 
			
		||||
@@ -160,6 +160,7 @@ private:
 | 
			
		||||
 | 
			
		||||
    Common::ThreadWorker workers;
 | 
			
		||||
    Common::ThreadWorker serialization_thread;
 | 
			
		||||
    DynamicFeatures dynamic_features;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Vulkan
 | 
			
		||||
 
 | 
			
		||||
@@ -680,16 +680,26 @@ void RasterizerVulkan::UpdateDynamicStates() {
 | 
			
		||||
    UpdateLineWidth(regs);
 | 
			
		||||
    if (device.IsExtExtendedDynamicStateSupported()) {
 | 
			
		||||
        UpdateCullMode(regs);
 | 
			
		||||
        UpdateDepthBoundsTestEnable(regs);
 | 
			
		||||
        UpdateDepthTestEnable(regs);
 | 
			
		||||
        UpdateDepthWriteEnable(regs);
 | 
			
		||||
 | 
			
		||||
        UpdateDepthCompareOp(regs);
 | 
			
		||||
        UpdateFrontFace(regs);
 | 
			
		||||
        UpdateStencilOp(regs);
 | 
			
		||||
        UpdateStencilTestEnable(regs);
 | 
			
		||||
 | 
			
		||||
        if (device.IsExtVertexInputDynamicStateSupported()) {
 | 
			
		||||
            UpdateVertexInput(regs);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (state_tracker.TouchStateEnable()) {
 | 
			
		||||
            UpdateDepthBoundsTestEnable(regs);
 | 
			
		||||
            UpdateDepthTestEnable(regs);
 | 
			
		||||
            UpdateDepthWriteEnable(regs);
 | 
			
		||||
            UpdateStencilTestEnable(regs);
 | 
			
		||||
            if (device.IsExtExtendedDynamicState2Supported()) {
 | 
			
		||||
                UpdatePrimitiveRestartEnable(regs);
 | 
			
		||||
                UpdateRasterizerDiscardEnable(regs);
 | 
			
		||||
                UpdateDepthBiasEnable(regs);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -909,6 +919,58 @@ void RasterizerVulkan::UpdateDepthWriteEnable(Tegra::Engines::Maxwell3D::Regs& r
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerVulkan::UpdatePrimitiveRestartEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
 | 
			
		||||
    if (!state_tracker.TouchPrimitiveRestartEnable()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    scheduler.Record([enable = regs.primitive_restart.enabled](vk::CommandBuffer cmdbuf) {
 | 
			
		||||
        cmdbuf.SetPrimitiveRestartEnableEXT(enable);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerVulkan::UpdateRasterizerDiscardEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
 | 
			
		||||
    if (!state_tracker.TouchRasterizerDiscardEnable()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    scheduler.Record([disable = regs.rasterize_enable](vk::CommandBuffer cmdbuf) {
 | 
			
		||||
        cmdbuf.SetRasterizerDiscardEnableEXT(disable == 0);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerVulkan::UpdateDepthBiasEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
 | 
			
		||||
    if (!state_tracker.TouchDepthBiasEnable()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    constexpr size_t POINT = 0;
 | 
			
		||||
    constexpr size_t LINE = 1;
 | 
			
		||||
    constexpr size_t POLYGON = 2;
 | 
			
		||||
    constexpr std::array POLYGON_OFFSET_ENABLE_LUT = {
 | 
			
		||||
        POINT,   // Points
 | 
			
		||||
        LINE,    // Lines
 | 
			
		||||
        LINE,    // LineLoop
 | 
			
		||||
        LINE,    // LineStrip
 | 
			
		||||
        POLYGON, // Triangles
 | 
			
		||||
        POLYGON, // TriangleStrip
 | 
			
		||||
        POLYGON, // TriangleFan
 | 
			
		||||
        POLYGON, // Quads
 | 
			
		||||
        POLYGON, // QuadStrip
 | 
			
		||||
        POLYGON, // Polygon
 | 
			
		||||
        LINE,    // LinesAdjacency
 | 
			
		||||
        LINE,    // LineStripAdjacency
 | 
			
		||||
        POLYGON, // TrianglesAdjacency
 | 
			
		||||
        POLYGON, // TriangleStripAdjacency
 | 
			
		||||
        POLYGON, // Patches
 | 
			
		||||
    };
 | 
			
		||||
    const std::array enabled_lut{
 | 
			
		||||
        regs.polygon_offset_point_enable,
 | 
			
		||||
        regs.polygon_offset_line_enable,
 | 
			
		||||
        regs.polygon_offset_fill_enable,
 | 
			
		||||
    };
 | 
			
		||||
    const u32 topology_index = static_cast<u32>(maxwell3d->draw_manager->GetDrawState().topology);
 | 
			
		||||
    const u32 enable = enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]];
 | 
			
		||||
    scheduler.Record([enable](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthBiasEnableEXT(enable); });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerVulkan::UpdateDepthCompareOp(Tegra::Engines::Maxwell3D::Regs& regs) {
 | 
			
		||||
    if (!state_tracker.TouchDepthCompareOp()) {
 | 
			
		||||
        return;
 | 
			
		||||
 
 | 
			
		||||
@@ -139,6 +139,9 @@ private:
 | 
			
		||||
    void UpdateDepthTestEnable(Tegra::Engines::Maxwell3D::Regs& regs);
 | 
			
		||||
    void UpdateDepthWriteEnable(Tegra::Engines::Maxwell3D::Regs& regs);
 | 
			
		||||
    void UpdateDepthCompareOp(Tegra::Engines::Maxwell3D::Regs& regs);
 | 
			
		||||
    void UpdatePrimitiveRestartEnable(Tegra::Engines::Maxwell3D::Regs& regs);
 | 
			
		||||
    void UpdateRasterizerDiscardEnable(Tegra::Engines::Maxwell3D::Regs& regs);
 | 
			
		||||
    void UpdateDepthBiasEnable(Tegra::Engines::Maxwell3D::Regs& regs);
 | 
			
		||||
    void UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs);
 | 
			
		||||
    void UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs);
 | 
			
		||||
    void UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs);
 | 
			
		||||
 
 | 
			
		||||
@@ -27,10 +27,27 @@ using Flags = Maxwell3D::DirtyState::Flags;
 | 
			
		||||
 | 
			
		||||
Flags MakeInvalidationFlags() {
 | 
			
		||||
    static constexpr int INVALIDATION_FLAGS[]{
 | 
			
		||||
        Viewports,         Scissors,       DepthBias, BlendConstants,    DepthBounds,
 | 
			
		||||
        StencilProperties, LineWidth,      CullMode,  DepthBoundsEnable, DepthTestEnable,
 | 
			
		||||
        DepthWriteEnable,  DepthCompareOp, FrontFace, StencilOp,         StencilTestEnable,
 | 
			
		||||
        VertexBuffers,     VertexInput,
 | 
			
		||||
        Viewports,
 | 
			
		||||
        Scissors,
 | 
			
		||||
        DepthBias,
 | 
			
		||||
        BlendConstants,
 | 
			
		||||
        DepthBounds,
 | 
			
		||||
        StencilProperties,
 | 
			
		||||
        LineWidth,
 | 
			
		||||
        CullMode,
 | 
			
		||||
        DepthBoundsEnable,
 | 
			
		||||
        DepthTestEnable,
 | 
			
		||||
        DepthWriteEnable,
 | 
			
		||||
        DepthCompareOp,
 | 
			
		||||
        FrontFace,
 | 
			
		||||
        StencilOp,
 | 
			
		||||
        StencilTestEnable,
 | 
			
		||||
        VertexBuffers,
 | 
			
		||||
        VertexInput,
 | 
			
		||||
        StateEnable,
 | 
			
		||||
        PrimitiveRestartEnable,
 | 
			
		||||
        RasterizerDiscardEnable,
 | 
			
		||||
        DepthBiasEnable,
 | 
			
		||||
    };
 | 
			
		||||
    Flags flags{};
 | 
			
		||||
    for (const int flag : INVALIDATION_FLAGS) {
 | 
			
		||||
@@ -96,16 +113,20 @@ void SetupDirtyCullMode(Tables& tables) {
 | 
			
		||||
    table[OFF(gl_cull_test_enabled)] = CullMode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SetupDirtyDepthBoundsEnable(Tables& tables) {
 | 
			
		||||
    tables[0][OFF(depth_bounds_enable)] = DepthBoundsEnable;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SetupDirtyDepthTestEnable(Tables& tables) {
 | 
			
		||||
    tables[0][OFF(depth_test_enable)] = DepthTestEnable;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SetupDirtyDepthWriteEnable(Tables& tables) {
 | 
			
		||||
    tables[0][OFF(depth_write_enabled)] = DepthWriteEnable;
 | 
			
		||||
void SetupDirtyStateEnable(Tables& tables) {
 | 
			
		||||
    const auto setup = [&](size_t position, u8 flag) {
 | 
			
		||||
        tables[0][position] = flag;
 | 
			
		||||
        tables[1][position] = StateEnable;
 | 
			
		||||
    };
 | 
			
		||||
    setup(OFF(depth_bounds_enable), DepthBoundsEnable);
 | 
			
		||||
    setup(OFF(depth_test_enable), DepthTestEnable);
 | 
			
		||||
    setup(OFF(depth_write_enabled), DepthWriteEnable);
 | 
			
		||||
    setup(OFF(stencil_enable), StencilTestEnable);
 | 
			
		||||
    setup(OFF(primitive_restart.enabled), PrimitiveRestartEnable);
 | 
			
		||||
    setup(OFF(rasterize_enable), RasterizerDiscardEnable);
 | 
			
		||||
    setup(OFF(polygon_offset_point_enable), DepthBiasEnable);
 | 
			
		||||
    setup(OFF(polygon_offset_line_enable), DepthBiasEnable);
 | 
			
		||||
    setup(OFF(polygon_offset_fill_enable), DepthBiasEnable);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SetupDirtyDepthCompareOp(Tables& tables) {
 | 
			
		||||
@@ -133,10 +154,6 @@ void SetupDirtyStencilOp(Tables& tables) {
 | 
			
		||||
    tables[1][OFF(stencil_two_side_enable)] = StencilOp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SetupDirtyStencilTestEnable(Tables& tables) {
 | 
			
		||||
    tables[0][OFF(stencil_enable)] = StencilTestEnable;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SetupDirtyBlending(Tables& tables) {
 | 
			
		||||
    tables[0][OFF(color_mask_common)] = Blending;
 | 
			
		||||
    tables[0][OFF(blend_per_target_enabled)] = Blending;
 | 
			
		||||
@@ -185,13 +202,10 @@ void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) {
 | 
			
		||||
    SetupDirtyStencilProperties(tables);
 | 
			
		||||
    SetupDirtyLineWidth(tables);
 | 
			
		||||
    SetupDirtyCullMode(tables);
 | 
			
		||||
    SetupDirtyDepthBoundsEnable(tables);
 | 
			
		||||
    SetupDirtyDepthTestEnable(tables);
 | 
			
		||||
    SetupDirtyDepthWriteEnable(tables);
 | 
			
		||||
    SetupDirtyStateEnable(tables);
 | 
			
		||||
    SetupDirtyDepthCompareOp(tables);
 | 
			
		||||
    SetupDirtyFrontFace(tables);
 | 
			
		||||
    SetupDirtyStencilOp(tables);
 | 
			
		||||
    SetupDirtyStencilTestEnable(tables);
 | 
			
		||||
    SetupDirtyBlending(tables);
 | 
			
		||||
    SetupDirtyViewportSwizzles(tables);
 | 
			
		||||
    SetupDirtyVertexAttributes(tables);
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,10 @@ enum : u8 {
 | 
			
		||||
    FrontFace,
 | 
			
		||||
    StencilOp,
 | 
			
		||||
    StencilTestEnable,
 | 
			
		||||
    PrimitiveRestartEnable,
 | 
			
		||||
    RasterizerDiscardEnable,
 | 
			
		||||
    DepthBiasEnable,
 | 
			
		||||
    StateEnable,
 | 
			
		||||
 | 
			
		||||
    Blending,
 | 
			
		||||
    ViewportSwizzles,
 | 
			
		||||
@@ -111,6 +115,10 @@ public:
 | 
			
		||||
        return Exchange(Dirty::CullMode, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool TouchStateEnable() {
 | 
			
		||||
        return Exchange(Dirty::StateEnable, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool TouchDepthBoundsTestEnable() {
 | 
			
		||||
        return Exchange(Dirty::DepthBoundsEnable, false);
 | 
			
		||||
    }
 | 
			
		||||
@@ -123,6 +131,18 @@ public:
 | 
			
		||||
        return Exchange(Dirty::DepthWriteEnable, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool TouchPrimitiveRestartEnable() {
 | 
			
		||||
        return Exchange(Dirty::PrimitiveRestartEnable, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool TouchRasterizerDiscardEnable() {
 | 
			
		||||
        return Exchange(Dirty::RasterizerDiscardEnable, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool TouchDepthBiasEnable() {
 | 
			
		||||
        return Exchange(Dirty::DepthBiasEnable, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool TouchDepthCompareOp() {
 | 
			
		||||
        return Exchange(Dirty::DepthCompareOp, false);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -569,6 +569,34 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
 | 
			
		||||
        LOG_INFO(Render_Vulkan, "Device doesn't support extended dynamic state");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    VkPhysicalDeviceExtendedDynamicState2FeaturesEXT dynamic_state2;
 | 
			
		||||
    if (ext_extended_dynamic_state2) {
 | 
			
		||||
        dynamic_state2 = {
 | 
			
		||||
            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT,
 | 
			
		||||
            .pNext = nullptr,
 | 
			
		||||
            .extendedDynamicState2 = VK_TRUE,
 | 
			
		||||
            .extendedDynamicState2LogicOp = ext_extended_dynamic_state2_extra ? VK_TRUE : VK_FALSE,
 | 
			
		||||
            .extendedDynamicState2PatchControlPoints =
 | 
			
		||||
                ext_extended_dynamic_state2_extra ? VK_TRUE : VK_FALSE,
 | 
			
		||||
        };
 | 
			
		||||
        SetNext(next, dynamic_state2);
 | 
			
		||||
    } else {
 | 
			
		||||
        LOG_INFO(Render_Vulkan, "Device doesn't support extended dynamic state 2");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    VkPhysicalDeviceExtendedDynamicState3FeaturesEXT dynamic_state3;
 | 
			
		||||
    if (ext_extended_dynamic_state3) {
 | 
			
		||||
        dynamic_state3 = {
 | 
			
		||||
            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT,
 | 
			
		||||
            .pNext = nullptr,
 | 
			
		||||
            .extendedDynamicState3ColorBlendEnable = VK_TRUE,
 | 
			
		||||
            .extendedDynamicState3ColorBlendEquation = VK_TRUE,
 | 
			
		||||
        };
 | 
			
		||||
        SetNext(next, dynamic_state3);
 | 
			
		||||
    } else {
 | 
			
		||||
        LOG_INFO(Render_Vulkan, "Device doesn't support extended dynamic state 3");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    VkPhysicalDeviceLineRasterizationFeaturesEXT line_raster;
 | 
			
		||||
    if (ext_line_rasterization) {
 | 
			
		||||
        line_raster = {
 | 
			
		||||
@@ -1091,6 +1119,8 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
 | 
			
		||||
    bool has_ext_transform_feedback{};
 | 
			
		||||
    bool has_ext_custom_border_color{};
 | 
			
		||||
    bool has_ext_extended_dynamic_state{};
 | 
			
		||||
    bool has_ext_extended_dynamic_state2{};
 | 
			
		||||
    bool has_ext_extended_dynamic_state3{};
 | 
			
		||||
    bool has_ext_shader_atomic_int64{};
 | 
			
		||||
    bool has_ext_provoking_vertex{};
 | 
			
		||||
    bool has_ext_vertex_input_dynamic_state{};
 | 
			
		||||
@@ -1135,6 +1165,10 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
 | 
			
		||||
        test(has_ext_transform_feedback, VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, false);
 | 
			
		||||
        test(has_ext_custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, false);
 | 
			
		||||
        test(has_ext_extended_dynamic_state, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, false);
 | 
			
		||||
        test(has_ext_extended_dynamic_state2, VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME,
 | 
			
		||||
             false);
 | 
			
		||||
        test(has_ext_extended_dynamic_state3, VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME,
 | 
			
		||||
             false);
 | 
			
		||||
        test(has_ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, true);
 | 
			
		||||
        test(has_ext_provoking_vertex, VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, false);
 | 
			
		||||
        test(has_ext_vertex_input_dynamic_state, VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME,
 | 
			
		||||
@@ -1284,6 +1318,36 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
 | 
			
		||||
            ext_extended_dynamic_state = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (has_ext_extended_dynamic_state2) {
 | 
			
		||||
        VkPhysicalDeviceExtendedDynamicState2FeaturesEXT extended_dynamic_state2;
 | 
			
		||||
        extended_dynamic_state2.sType =
 | 
			
		||||
            VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT;
 | 
			
		||||
        extended_dynamic_state2.pNext = nullptr;
 | 
			
		||||
        features.pNext = &extended_dynamic_state2;
 | 
			
		||||
        physical.GetFeatures2(features);
 | 
			
		||||
 | 
			
		||||
        if (extended_dynamic_state2.extendedDynamicState2) {
 | 
			
		||||
            extensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
 | 
			
		||||
            ext_extended_dynamic_state2 = true;
 | 
			
		||||
            ext_extended_dynamic_state2_extra =
 | 
			
		||||
                extended_dynamic_state2.extendedDynamicState2LogicOp &&
 | 
			
		||||
                extended_dynamic_state2.extendedDynamicState2PatchControlPoints;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (has_ext_extended_dynamic_state3) {
 | 
			
		||||
        VkPhysicalDeviceExtendedDynamicState3FeaturesEXT extended_dynamic_state3;
 | 
			
		||||
        extended_dynamic_state3.sType =
 | 
			
		||||
            VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT;
 | 
			
		||||
        extended_dynamic_state3.pNext = nullptr;
 | 
			
		||||
        features.pNext = &extended_dynamic_state3;
 | 
			
		||||
        physical.GetFeatures2(features);
 | 
			
		||||
 | 
			
		||||
        if (extended_dynamic_state3.extendedDynamicState3ColorBlendEnable &&
 | 
			
		||||
            extended_dynamic_state3.extendedDynamicState3ColorBlendEquation) {
 | 
			
		||||
            extensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
 | 
			
		||||
            ext_extended_dynamic_state3 = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (has_ext_line_rasterization) {
 | 
			
		||||
        VkPhysicalDeviceLineRasterizationFeaturesEXT line_raster;
 | 
			
		||||
        line_raster.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT;
 | 
			
		||||
 
 | 
			
		||||
@@ -286,6 +286,20 @@ public:
 | 
			
		||||
        return ext_extended_dynamic_state;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns true if the device supports VK_EXT_extended_dynamic_state2.
 | 
			
		||||
    bool IsExtExtendedDynamicState2Supported() const {
 | 
			
		||||
        return ext_extended_dynamic_state2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool IsExtExtendedDynamicState2ExtrasSupported() const {
 | 
			
		||||
        return ext_extended_dynamic_state2_extra;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns true if the device supports VK_EXT_extended_dynamic_state3.
 | 
			
		||||
    bool IsExtExtendedDynamicState3Supported() const {
 | 
			
		||||
        return ext_extended_dynamic_state3;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns true if the device supports VK_EXT_line_rasterization.
 | 
			
		||||
    bool IsExtLineRasterizationSupported() const {
 | 
			
		||||
        return ext_line_rasterization;
 | 
			
		||||
@@ -468,6 +482,9 @@ private:
 | 
			
		||||
    bool ext_transform_feedback{};          ///< Support for VK_EXT_transform_feedback.
 | 
			
		||||
    bool ext_custom_border_color{};         ///< Support for VK_EXT_custom_border_color.
 | 
			
		||||
    bool ext_extended_dynamic_state{};      ///< Support for VK_EXT_extended_dynamic_state.
 | 
			
		||||
    bool ext_extended_dynamic_state2{};      ///< Support for VK_EXT_extended_dynamic_state2.
 | 
			
		||||
    bool ext_extended_dynamic_state2_extra{}; ///< Support for VK_EXT_extended_dynamic_state2.
 | 
			
		||||
    bool ext_extended_dynamic_state3{};      ///< Support for VK_EXT_extended_dynamic_state3.
 | 
			
		||||
    bool ext_line_rasterization{};          ///< Support for VK_EXT_line_rasterization.
 | 
			
		||||
    bool ext_vertex_input_dynamic_state{};  ///< Support for VK_EXT_vertex_input_dynamic_state.
 | 
			
		||||
    bool ext_shader_stencil_export{};       ///< Support for VK_EXT_shader_stencil_export.
 | 
			
		||||
 
 | 
			
		||||
@@ -122,6 +122,9 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
 | 
			
		||||
    X(vkCmdSetDepthCompareOpEXT);
 | 
			
		||||
    X(vkCmdSetDepthTestEnableEXT);
 | 
			
		||||
    X(vkCmdSetDepthWriteEnableEXT);
 | 
			
		||||
    X(vkCmdSetPrimitiveRestartEnableEXT);
 | 
			
		||||
    X(vkCmdSetRasterizerDiscardEnableEXT);
 | 
			
		||||
    X(vkCmdSetDepthBiasEnableEXT);
 | 
			
		||||
    X(vkCmdSetFrontFaceEXT);
 | 
			
		||||
    X(vkCmdSetLineWidth);
 | 
			
		||||
    X(vkCmdSetPrimitiveTopologyEXT);
 | 
			
		||||
 
 | 
			
		||||
@@ -234,6 +234,9 @@ struct DeviceDispatch : InstanceDispatch {
 | 
			
		||||
    PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT{};
 | 
			
		||||
    PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT{};
 | 
			
		||||
    PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT{};
 | 
			
		||||
    PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT{};
 | 
			
		||||
    PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT{};
 | 
			
		||||
    PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT{};
 | 
			
		||||
    PFN_vkCmdSetEvent vkCmdSetEvent{};
 | 
			
		||||
    PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT{};
 | 
			
		||||
    PFN_vkCmdSetLineWidth vkCmdSetLineWidth{};
 | 
			
		||||
@@ -1219,6 +1222,18 @@ public:
 | 
			
		||||
        dld->vkCmdSetDepthWriteEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetPrimitiveRestartEnableEXT(bool enable) const noexcept {
 | 
			
		||||
        dld->vkCmdSetPrimitiveRestartEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetRasterizerDiscardEnableEXT(bool enable) const noexcept {
 | 
			
		||||
        dld->vkCmdSetRasterizerDiscardEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetDepthBiasEnableEXT(bool enable) const noexcept {
 | 
			
		||||
        dld->vkCmdSetDepthBiasEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetFrontFaceEXT(VkFrontFace front_face) const noexcept {
 | 
			
		||||
        dld->vkCmdSetFrontFaceEXT(handle, front_face);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user