From 8553e7e7ded7f3f52946812694485e4324a974f3 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Tue, 27 Jan 2026 23:50:02 -0400 Subject: [PATCH] [vulkan] Increased logic handling of DynamicState and VertexInputDynamicState --- src/video_core/buffer_cache/buffer_cache.h | 10 +- .../buffer_cache/buffer_cache_base.h | 6 +- .../renderer_opengl/gl_buffer_cache.cpp | 5 +- .../renderer_opengl/gl_buffer_cache.h | 5 +- .../renderer_opengl/gl_graphics_pipeline.cpp | 4 +- .../renderer_vulkan/vk_buffer_cache.cpp | 10 +- .../renderer_vulkan/vk_buffer_cache.h | 8 +- .../renderer_vulkan/vk_graphics_pipeline.cpp | 3 +- .../renderer_vulkan/vk_graphics_pipeline.h | 8 +- .../renderer_vulkan/vk_rasterizer.cpp | 685 ++++++++++++++---- .../renderer_vulkan/vk_rasterizer.h | 61 +- .../vulkan_common/vulkan_device.cpp | 14 +- 12 files changed, 599 insertions(+), 220 deletions(-) diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index b368ffea05..b61a574f58 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project @@ -352,7 +352,7 @@ void BufferCache

::UpdateComputeBuffers() { } template -void BufferCache

::BindHostGeometryBuffers(bool is_indexed) { +void BufferCache

::BindHostGeometryBuffers(bool is_indexed, bool use_dynamic_vertex_input) { if (is_indexed) { BindHostIndexBuffer(); } else if constexpr (!HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) { @@ -363,7 +363,7 @@ void BufferCache

::BindHostGeometryBuffers(bool is_indexed) { draw_state.vertex_buffer.count); } } - BindHostVertexBuffers(); + BindHostVertexBuffers(use_dynamic_vertex_input); BindHostTransformFeedbackBuffers(); if (current_draw_indirect) { BindHostDrawIndirectBuffers(); @@ -764,7 +764,7 @@ void BufferCache

::BindHostIndexBuffer() { } template -void BufferCache

::BindHostVertexBuffers() { +void BufferCache

::BindHostVertexBuffers(bool use_dynamic_vertex_input) { HostBindings host_bindings; bool any_valid{false}; auto& flags = maxwell3d->dirty.flags; @@ -800,7 +800,7 @@ void BufferCache

::BindHostVertexBuffers() { host_bindings.sizes.push_back(binding.size); host_bindings.strides.push_back(stride); } - runtime.BindVertexBuffers(host_bindings); + runtime.BindVertexBuffers(host_bindings, use_dynamic_vertex_input); } } diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index ed50634683..925b83dff9 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project @@ -232,7 +232,7 @@ public: void UpdateComputeBuffers(); - void BindHostGeometryBuffers(bool is_indexed); + void BindHostGeometryBuffers(bool is_indexed, bool use_dynamic_vertex_input = false); void BindHostStageBuffers(size_t stage); @@ -358,7 +358,7 @@ private: void BindHostIndexBuffer(); - void BindHostVertexBuffers(); + void BindHostVertexBuffers(bool use_dynamic_vertex_input = false); void BindHostDrawIndirectBuffers(); diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index 59829b667f..77ca0c07c9 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -242,7 +242,8 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, } } -void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bindings) { +void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bindings, + bool /*use_dynamic_vertex_input*/) { // TODO: Should HostBindings provide the correct runtime types to avoid these transforms? std::array buffer_handles; std::array buffer_strides; diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index 23ebe50196..03a6e20acb 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -101,7 +101,8 @@ public: void BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size, u32 stride); - void BindVertexBuffers(VideoCommon::HostBindings& bindings); + void BindVertexBuffers(VideoCommon::HostBindings& bindings, + bool use_dynamic_vertex_input = false); void BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, u32 offset, u32 size); diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 2abbd0de78..3f34bd10c2 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -436,7 +436,7 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) { bind_stage_info(4); } buffer_cache.UpdateGraphicsBuffers(is_indexed); - buffer_cache.BindHostGeometryBuffers(is_indexed); + buffer_cache.BindHostGeometryBuffers(is_indexed, false); if (!IsBuilt()) { WaitForBuild(); diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 6256bc8bd8..bba04c6b5e 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -551,11 +551,12 @@ void BufferCacheRuntime::BindQuadIndexBuffer(PrimitiveTopology topology, u32 fir } } -void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride) { +void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride, + bool use_dynamic_vertex_input) { if (index >= device.GetMaxVertexInputBindings()) { return; } - if (device.IsExtExtendedDynamicStateSupported()) { + if (use_dynamic_vertex_input && device.IsExtExtendedDynamicStateSupported()) { scheduler.Record([index, buffer, offset, size, stride](vk::CommandBuffer cmdbuf) { const VkDeviceSize vk_offset = buffer != VK_NULL_HANDLE ? offset : 0; const VkDeviceSize vk_size = buffer != VK_NULL_HANDLE ? size : VK_WHOLE_SIZE; @@ -574,7 +575,8 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset } } -void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bindings) { +void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bindings, + bool use_dynamic_vertex_input) { boost::container::small_vector buffer_handles; for (u32 index = 0; index < bindings.buffers.size(); ++index) { auto handle = bindings.buffers[index]->Handle(); @@ -595,7 +597,7 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bi if (binding_count == 0) { return; } - if (device.IsExtExtendedDynamicStateSupported()) { + if (use_dynamic_vertex_input && device.IsExtExtendedDynamicStateSupported()) { scheduler.Record([bindings_ = std::move(bindings), buffer_handles_ = std::move(buffer_handles), binding_count](vk::CommandBuffer cmdbuf) { diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index b73fcd162b..7bcfb8d72f 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -123,9 +123,11 @@ public: void BindQuadIndexBuffer(PrimitiveTopology topology, u32 first, u32 count); - void BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride); + void BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride, + bool use_dynamic_vertex_input); - void BindVertexBuffers(VideoCommon::HostBindings& bindings); + void BindVertexBuffers(VideoCommon::HostBindings& bindings, + bool use_dynamic_vertex_input); void BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size); diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index b8798f274f..aa87b588c1 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -459,7 +459,7 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) { } buffer_cache.UpdateGraphicsBuffers(is_indexed); - buffer_cache.BindHostGeometryBuffers(is_indexed); + buffer_cache.BindHostGeometryBuffers(is_indexed, HasDynamicVertexInput()); guest_descriptor_queue.Acquire(); @@ -519,6 +519,7 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling, uses_render_area = render_area.uses_render_area, render_area_data = render_area.words](vk::CommandBuffer cmdbuf) { if (bind_pipeline) { + if (pre_bind_callback) pre_bind_callback(cmdbuf); cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); } cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS, diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 34941d6e8d..f0feccfc6a 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -21,6 +21,7 @@ #include "video_core/renderer_vulkan/vk_descriptor_pool.h" #include "video_core/renderer_vulkan/vk_texture_cache.h" #include "video_core/vulkan_common/vulkan_wrapper.h" +#include namespace VideoCore { class ShaderNotify; @@ -128,6 +129,9 @@ public: gpu_memory = gpu_memory_; } + void SetPreBindCallback(std::function cb) { pre_bind_callback = std::move(cb); } + void ClearPreBindCallback() { pre_bind_callback = {};} + private: template bool ConfigureImpl(bool is_indexed); @@ -135,6 +139,8 @@ private: void ConfigureDraw(const RescalingPushConstant& rescaling, const RenderAreaPushConstant& render_are); + std::function pre_bind_callback; + void MakePipeline(VkRenderPass render_pass); void Validate(); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 691d818912..91237ac112 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -225,6 +225,9 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) { UpdateDynamicStates(); + pipeline->SetPreBindCallback([this](vk::CommandBuffer cmdbuf) { RecordDynamicStates(cmdbuf); }); + SCOPE_EXIT { pipeline->ClearPreBindCallback(); }; + if (!pipeline->Configure(is_indexed)) return; @@ -1047,6 +1050,219 @@ void RasterizerVulkan::UpdateDynamicStates() { } } +void RasterizerVulkan::RecordDynamicStates(vk::CommandBuffer cmdbuf) { + auto& regs = maxwell3d->regs; + + // Viewports + if (state_tracker.TouchViewports()) { + if (!regs.viewport_scale_offset_enabled) { + float x = static_cast(regs.surface_clip.x); + float y = static_cast(regs.surface_clip.y); + float width = (std::max)(1.0f, static_cast(regs.surface_clip.width)); + float height = (std::max)(1.0f, static_cast(regs.surface_clip.height)); + if (regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft) { + y += height; + height = -height; + } + VkViewport viewport{ + .x = x, + .y = y, + .width = width, + .height = height, + .minDepth = 0.0f, + .maxDepth = 1.0f, + }; + if (!device.IsExtDepthRangeUnrestrictedSupported()) { + viewport.minDepth = std::clamp(viewport.minDepth, 0.0f, 1.0f); + viewport.maxDepth = std::clamp(viewport.maxDepth, 0.0f, 1.0f); + } + cmdbuf.SetViewport(0, viewport); + } else { + const bool is_rescaling{texture_cache.IsRescaling()}; + const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f; + const std::array viewport_list{ + GetViewportState(device, regs, 0, scale), GetViewportState(device, regs, 1, scale), + GetViewportState(device, regs, 2, scale), GetViewportState(device, regs, 3, scale), + GetViewportState(device, regs, 4, scale), GetViewportState(device, regs, 5, scale), + GetViewportState(device, regs, 6, scale), GetViewportState(device, regs, 7, scale), + GetViewportState(device, regs, 8, scale), GetViewportState(device, regs, 9, scale), + GetViewportState(device, regs, 10, scale), GetViewportState(device, regs, 11, scale), + GetViewportState(device, regs, 12, scale), GetViewportState(device, regs, 13, scale), + GetViewportState(device, regs, 14, scale), GetViewportState(device, regs, 15, scale), + }; + const u32 num_viewports = std::min(device.GetMaxViewports(), Maxwell::NumViewports); + const vk::Span viewports(viewport_list.data(), num_viewports); + cmdbuf.SetViewport(0, viewports); + } + } + + // Scissors + if (state_tracker.TouchScissors()) { + if (!regs.viewport_scale_offset_enabled) { + u32 x = regs.surface_clip.x; + u32 y = regs.surface_clip.y; + u32 width = (std::max)(1u, static_cast(regs.surface_clip.width)); + u32 height = (std::max)(1u, static_cast(regs.surface_clip.height)); + if (regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft) { + y = regs.surface_clip.height - (y + height); + } + VkRect2D scissor{}; + scissor.offset.x = static_cast(x); + scissor.offset.y = static_cast(y); + scissor.extent.width = width; + scissor.extent.height = height; + cmdbuf.SetScissor(0, scissor); + } else { + u32 up_scale = 1; + u32 down_shift = 0; + if (texture_cache.IsRescaling()) { + up_scale = Settings::values.resolution_info.up_scale; + down_shift = Settings::values.resolution_info.down_shift; + } + const std::array scissor_list{ + GetScissorState(regs, 0, up_scale, down_shift), + GetScissorState(regs, 1, up_scale, down_shift), + GetScissorState(regs, 2, up_scale, down_shift), + GetScissorState(regs, 3, up_scale, down_shift), + GetScissorState(regs, 4, up_scale, down_shift), + GetScissorState(regs, 5, up_scale, down_shift), + GetScissorState(regs, 6, up_scale, down_shift), + GetScissorState(regs, 7, up_scale, down_shift), + GetScissorState(regs, 8, up_scale, down_shift), + GetScissorState(regs, 9, up_scale, down_shift), + GetScissorState(regs, 10, up_scale, down_shift), + GetScissorState(regs, 11, up_scale, down_shift), + GetScissorState(regs, 12, up_scale, down_shift), + GetScissorState(regs, 13, up_scale, down_shift), + GetScissorState(regs, 14, up_scale, down_shift), + GetScissorState(regs, 15, up_scale, down_shift), + }; + const u32 num_scissors = std::min(device.GetMaxViewports(), Maxwell::NumViewports); + const vk::Span scissors(scissor_list.data(), num_scissors); + cmdbuf.SetScissor(0, scissors); + } + } + + // Depth bias + if (state_tracker.TouchDepthBias()) { + float units = regs.depth_bias / 2.0f; + const bool is_d24 = regs.zeta.format == Tegra::DepthFormat::Z24_UNORM_S8_UINT || + regs.zeta.format == Tegra::DepthFormat::X8Z24_UNORM || + regs.zeta.format == Tegra::DepthFormat::S8Z24_UNORM || + regs.zeta.format == Tegra::DepthFormat::V8Z24_UNORM; + if (is_d24 && !device.SupportsD24DepthBuffer()) { + static constexpr const size_t length = sizeof(NEEDS_D24) / sizeof(NEEDS_D24[0]); + static constexpr const u64* start = NEEDS_D24; + static constexpr const u64* end = NEEDS_D24 + length; + const u64* it = std::find(start, end, program_id); + if (it != end) { + const double rescale_factor = + static_cast(1ULL << (32 - 24)) / (static_cast(0x1.ep+127)); + units = static_cast(static_cast(units) * rescale_factor); + } + } + if (device.IsExtDepthBiasControlSupported()) { + static VkDepthBiasRepresentationInfoEXT bias_info{ + .sType = VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT, + .pNext = nullptr, + .depthBiasRepresentation = + VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT, + .depthBiasExact = VK_FALSE, + }; + cmdbuf.SetDepthBias(units, regs.depth_bias_clamp, regs.slope_scale_depth_bias, &bias_info); + } else { + cmdbuf.SetDepthBias(units, regs.depth_bias_clamp, regs.slope_scale_depth_bias); + } + } + + // Blend constants + if (state_tracker.TouchBlendConstants()) { + const std::array blend_color = {regs.blend_color.r, regs.blend_color.g, regs.blend_color.b, + regs.blend_color.a}; + cmdbuf.SetBlendConstants(blend_color.data()); + } + + // Depth bounds + if (state_tracker.TouchDepthBounds()) { + cmdbuf.SetDepthBounds(regs.depth_bounds[0], regs.depth_bounds[1]); + } + + // Stencil faces + if (state_tracker.TouchStencilProperties()) { + const VkStencilOpState front_state{ + .failOp = static_cast(regs.stencil_front_fail), + .passOp = static_cast(regs.stencil_front_pass), + .depthFailOp = static_cast(regs.stencil_front_depth_fail), + .compareOp = static_cast(regs.stencil_front_compare), + .compareMask = regs.stencil_front_mask, + .writeMask = regs.stencil_front_write_mask, + .reference = regs.stencil_front_reference, + }; + const VkStencilOpState back_state{ + .failOp = static_cast(regs.stencil_back_fail), + .passOp = static_cast(regs.stencil_back_pass), + .depthFailOp = static_cast(regs.stencil_back_depth_fail), + .compareOp = static_cast(regs.stencil_back_compare), + .compareMask = regs.stencil_back_mask, + .writeMask = regs.stencil_back_write_mask, + .reference = regs.stencil_back_reference, + }; + cmdbuf.SetStencilOpEXT(front_state, back_state); + if (state_tracker.TouchStencilReference()) { + cmdbuf.SetStencilReference(front_state.reference, back_state.reference); + } + } + + // Line width + if (state_tracker.TouchLineWidth()) { + cmdbuf.SetLineWidth(regs.line_width); + } + + // Extended Dynamic State (a subset) - call existing helpers but target cmdbuf where appropriate + if (device.IsExtExtendedDynamicStateSupported()) { + UpdateCullMode(regs, &cmdbuf); + UpdateDepthCompareOp(regs, &cmdbuf); + UpdateFrontFace(regs, &cmdbuf); + UpdateStencilOp(regs, &cmdbuf); + if (state_tracker.TouchStateEnable()) { + UpdateDepthBoundsTestEnable(regs, &cmdbuf); + UpdateDepthTestEnable(regs, &cmdbuf); + UpdateDepthWriteEnable(regs, &cmdbuf); + UpdateStencilTestEnable(regs, &cmdbuf); + } + } + + if (device.IsExtExtendedDynamicState2Supported()) { + UpdatePrimitiveRestartEnable(regs, &cmdbuf); + UpdateRasterizerDiscardEnable(regs, &cmdbuf); + UpdateDepthBiasEnable(regs, &cmdbuf); + } + + if (device.IsExtExtendedDynamicState2ExtrasSupported()) { + UpdateLogicOp(regs, &cmdbuf); + } + + if (device.IsExtExtendedDynamicState3EnablesSupported()) { + UpdateLogicOpEnable(regs, &cmdbuf); + UpdateDepthClampEnable(regs, &cmdbuf); + UpdateLineRasterizationMode(regs, &cmdbuf); + UpdateLineStippleEnable(regs, &cmdbuf); + UpdateConservativeRasterizationMode(regs, &cmdbuf); + UpdateAlphaToCoverageEnable(regs, &cmdbuf); + UpdateAlphaToOneEnable(regs, &cmdbuf); + } + + if (device.IsExtExtendedDynamicState3BlendingSupported()) { + UpdateBlending(regs, &cmdbuf); + } + + if (device.IsExtVertexInputDynamicStateSupported()) { + if (auto* gp = pipeline_cache.CurrentGraphicsPipeline(); gp && gp->HasDynamicVertexInput()) { + UpdateVertexInput(regs, &cmdbuf); + } + } +} + void RasterizerVulkan::HandleTransformFeedback() { static std::once_flag warn_unsupported; @@ -1072,7 +1288,7 @@ void RasterizerVulkan::HandleTransformFeedback() { } } -void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchViewports()) { return; } @@ -1093,9 +1309,11 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg .minDepth = 0.0f, .maxDepth = 1.0f, }; - scheduler.Record([viewport](vk::CommandBuffer cmdbuf) { - cmdbuf.SetViewport(0, viewport); - }); + if (cmdbuf) { + cmdbuf->SetViewport(0, viewport); + } else { + scheduler.Record([viewport](vk::CommandBuffer cmdbuf) { cmdbuf.SetViewport(0, viewport); }); + } return; } const bool is_rescaling{texture_cache.IsRescaling()}; @@ -1110,14 +1328,20 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg GetViewportState(device, regs, 12, scale), GetViewportState(device, regs, 13, scale), GetViewportState(device, regs, 14, scale), GetViewportState(device, regs, 15, scale), }; - scheduler.Record([this, viewport_list](vk::CommandBuffer cmdbuf) { + if (cmdbuf) { const u32 num_viewports = std::min(device.GetMaxViewports(), Maxwell::NumViewports); const vk::Span viewports(viewport_list.data(), num_viewports); - cmdbuf.SetViewport(0, viewports); - }); + cmdbuf->SetViewport(0, viewports); + } else { + scheduler.Record([this, viewport_list](vk::CommandBuffer cmdbuf) { + const u32 num_viewports = std::min(device.GetMaxViewports(), Maxwell::NumViewports); + const vk::Span viewports(viewport_list.data(), num_viewports); + cmdbuf.SetViewport(0, viewports); + }); + } } -void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchScissors()) { return; } @@ -1134,9 +1358,11 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs scissor.offset.y = static_cast(y); scissor.extent.width = width; scissor.extent.height = height; - scheduler.Record([scissor](vk::CommandBuffer cmdbuf) { - cmdbuf.SetScissor(0, scissor); - }); + if (cmdbuf) { + cmdbuf->SetScissor(0, scissor); + } else { + scheduler.Record([scissor](vk::CommandBuffer cmdbuf) { cmdbuf.SetScissor(0, scissor); }); + } return; } u32 up_scale = 1; @@ -1163,14 +1389,20 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs GetScissorState(regs, 14, up_scale, down_shift), GetScissorState(regs, 15, up_scale, down_shift), }; - scheduler.Record([this, scissor_list](vk::CommandBuffer cmdbuf) { + if (cmdbuf) { const u32 num_scissors = std::min(device.GetMaxViewports(), Maxwell::NumViewports); const vk::Span scissors(scissor_list.data(), num_scissors); - cmdbuf.SetScissor(0, scissors); - }); + cmdbuf->SetScissor(0, scissors); + } else { + scheduler.Record([this, scissor_list](vk::CommandBuffer cmdbuf) { + const u32 num_scissors = std::min(device.GetMaxViewports(), Maxwell::NumViewports); + const vk::Span scissors(scissor_list.data(), num_scissors); + cmdbuf.SetScissor(0, scissors); + }); + } } -void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchDepthBias()) { return; } @@ -1197,8 +1429,7 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) { } } - scheduler.Record([constant = units, clamp = regs.depth_bias_clamp, - factor = regs.slope_scale_depth_bias, this](vk::CommandBuffer cmdbuf) { + if (cmdbuf) { if (device.IsExtDepthBiasControlSupported()) { static VkDepthBiasRepresentationInfoEXT bias_info{ .sType = VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT, @@ -1208,32 +1439,57 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) { .depthBiasExact = VK_FALSE, }; - cmdbuf.SetDepthBias(constant, clamp, factor, &bias_info); + cmdbuf->SetDepthBias(units, regs.depth_bias_clamp, regs.slope_scale_depth_bias, &bias_info); } else { - cmdbuf.SetDepthBias(constant, clamp, factor); + cmdbuf->SetDepthBias(units, regs.depth_bias_clamp, regs.slope_scale_depth_bias); } - }); + } else { + scheduler.Record([constant = units, clamp = regs.depth_bias_clamp, + factor = regs.slope_scale_depth_bias, this](vk::CommandBuffer cmdbuf) { + if (device.IsExtDepthBiasControlSupported()) { + static VkDepthBiasRepresentationInfoEXT bias_info{ + .sType = VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT, + .pNext = nullptr, + .depthBiasRepresentation = + VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT, + .depthBiasExact = VK_FALSE, + }; + + cmdbuf.SetDepthBias(constant, clamp, factor, &bias_info); + } else { + cmdbuf.SetDepthBias(constant, clamp, factor); + } + }); + } } -void RasterizerVulkan::UpdateBlendConstants(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateBlendConstants(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchBlendConstants()) { return; } const std::array blend_color = {regs.blend_color.r, regs.blend_color.g, regs.blend_color.b, regs.blend_color.a}; - scheduler.Record( - [blend_color](vk::CommandBuffer cmdbuf) { cmdbuf.SetBlendConstants(blend_color.data()); }); + if (cmdbuf) { + cmdbuf->SetBlendConstants(blend_color.data()); + } else { + scheduler.Record([blend_color](vk::CommandBuffer cmdbuf) { cmdbuf.SetBlendConstants(blend_color.data()); }); + } } -void RasterizerVulkan::UpdateDepthBounds(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateDepthBounds(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchDepthBounds()) { return; } - scheduler.Record([min = regs.depth_bounds[0], max = regs.depth_bounds[1]]( - vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthBounds(min, max); }); + if (cmdbuf) { + cmdbuf->SetDepthBounds(regs.depth_bounds[0], regs.depth_bounds[1]); + } else { + scheduler.Record([min = regs.depth_bounds[0], max = regs.depth_bounds[1]](vk::CommandBuffer cmdbuf) { + cmdbuf.SetDepthBounds(min, max); + }); + } } -void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchStencilProperties()) { return; } @@ -1257,17 +1513,25 @@ void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs) return; } } - scheduler.Record([front_ref = regs.stencil_front_ref, back_ref = regs.stencil_back_ref, - two_sided = regs.stencil_two_side_enable](vk::CommandBuffer cmdbuf) { - const bool set_back = two_sided && front_ref != back_ref; - // Front face - cmdbuf.SetStencilReference(set_back ? VK_STENCIL_FACE_FRONT_BIT - : VK_STENCIL_FACE_FRONT_AND_BACK, - front_ref); + if (cmdbuf) { + const bool set_back = regs.stencil_two_side_enable && regs.stencil_front_ref != regs.stencil_back_ref; + cmdbuf->SetStencilReference(set_back ? VK_STENCIL_FACE_FRONT_BIT : VK_STENCIL_FACE_FRONT_AND_BACK, + regs.stencil_front_ref); if (set_back) { - cmdbuf.SetStencilReference(VK_STENCIL_FACE_BACK_BIT, back_ref); + cmdbuf->SetStencilReference(VK_STENCIL_FACE_BACK_BIT, regs.stencil_back_ref); } - }); + } else { + scheduler.Record([front_ref = regs.stencil_front_ref, back_ref = regs.stencil_back_ref, + two_sided = regs.stencil_two_side_enable](vk::CommandBuffer cmdbuf) { + const bool set_back = two_sided && front_ref != back_ref; + cmdbuf.SetStencilReference(set_back ? VK_STENCIL_FACE_FRONT_BIT + : VK_STENCIL_FACE_FRONT_AND_BACK, + front_ref); + if (set_back) { + cmdbuf.SetStencilReference(VK_STENCIL_FACE_BACK_BIT, back_ref); + } + }); + } }(); } if (update_write_mask) { @@ -1282,18 +1546,26 @@ void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs) return; } } - scheduler.Record([front_write_mask = regs.stencil_front_mask, - back_write_mask = regs.stencil_back_mask, - two_sided = regs.stencil_two_side_enable](vk::CommandBuffer cmdbuf) { - const bool set_back = two_sided && front_write_mask != back_write_mask; - // Front face - cmdbuf.SetStencilWriteMask(set_back ? VK_STENCIL_FACE_FRONT_BIT - : VK_STENCIL_FACE_FRONT_AND_BACK, - front_write_mask); + if (cmdbuf) { + const bool set_back = regs.stencil_two_side_enable && regs.stencil_front_mask != regs.stencil_back_mask; + cmdbuf->SetStencilWriteMask(set_back ? VK_STENCIL_FACE_FRONT_BIT : VK_STENCIL_FACE_FRONT_AND_BACK, + regs.stencil_front_mask); if (set_back) { - cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_BACK_BIT, back_write_mask); + cmdbuf->SetStencilWriteMask(VK_STENCIL_FACE_BACK_BIT, regs.stencil_back_mask); } - }); + } else { + scheduler.Record([front_write_mask = regs.stencil_front_mask, + back_write_mask = regs.stencil_back_mask, + two_sided = regs.stencil_two_side_enable](vk::CommandBuffer cmdbuf) { + const bool set_back = two_sided && front_write_mask != back_write_mask; + cmdbuf.SetStencilWriteMask(set_back ? VK_STENCIL_FACE_FRONT_BIT + : VK_STENCIL_FACE_FRONT_AND_BACK, + front_write_mask); + if (set_back) { + cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_BACK_BIT, back_write_mask); + } + }); + } }(); } if (update_compare_masks) { @@ -1308,40 +1580,56 @@ void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs) return; } } - scheduler.Record([front_test_mask = regs.stencil_front_func_mask, - back_test_mask = regs.stencil_back_func_mask, - two_sided = regs.stencil_two_side_enable](vk::CommandBuffer cmdbuf) { - const bool set_back = two_sided && front_test_mask != back_test_mask; - // Front face - cmdbuf.SetStencilCompareMask(set_back ? VK_STENCIL_FACE_FRONT_BIT - : VK_STENCIL_FACE_FRONT_AND_BACK, - front_test_mask); + if (cmdbuf) { + const bool set_back = regs.stencil_two_side_enable && regs.stencil_front_func_mask != regs.stencil_back_func_mask; + cmdbuf->SetStencilCompareMask(set_back ? VK_STENCIL_FACE_FRONT_BIT : VK_STENCIL_FACE_FRONT_AND_BACK, + regs.stencil_front_func_mask); if (set_back) { - cmdbuf.SetStencilCompareMask(VK_STENCIL_FACE_BACK_BIT, back_test_mask); + cmdbuf->SetStencilCompareMask(VK_STENCIL_FACE_BACK_BIT, regs.stencil_back_func_mask); } - }); + } else { + scheduler.Record([front_test_mask = regs.stencil_front_func_mask, + back_test_mask = regs.stencil_back_func_mask, + two_sided = regs.stencil_two_side_enable](vk::CommandBuffer cmdbuf) { + const bool set_back = two_sided && front_test_mask != back_test_mask; + cmdbuf.SetStencilCompareMask(set_back ? VK_STENCIL_FACE_FRONT_BIT + : VK_STENCIL_FACE_FRONT_AND_BACK, + front_test_mask); + if (set_back) { + cmdbuf.SetStencilCompareMask(VK_STENCIL_FACE_BACK_BIT, back_test_mask); + } + }); + } }(); } state_tracker.ClearStencilReset(); } -void RasterizerVulkan::UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchLineWidth()) { return; } - const float width = - regs.line_anti_alias_enable ? regs.line_width_smooth : regs.line_width_aliased; - scheduler.Record([width](vk::CommandBuffer cmdbuf) { cmdbuf.SetLineWidth(width); }); + const float width = regs.line_anti_alias_enable ? regs.line_width_smooth : regs.line_width_aliased; + if (cmdbuf) { + cmdbuf->SetLineWidth(width); + } else { + scheduler.Record([width](vk::CommandBuffer cmdbuf) { cmdbuf.SetLineWidth(width); }); + } } -void RasterizerVulkan::UpdateCullMode(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateCullMode(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchCullMode()) { return; } - scheduler.Record([enabled = regs.gl_cull_test_enabled, - cull_face = regs.gl_cull_face](vk::CommandBuffer cmdbuf) { - cmdbuf.SetCullModeEXT(enabled ? MaxwellToVK::CullFace(cull_face) : VK_CULL_MODE_NONE); - }); + if (cmdbuf) { + cmdbuf->SetCullModeEXT(regs.gl_cull_test_enabled ? MaxwellToVK::CullFace(regs.gl_cull_face) + : VK_CULL_MODE_NONE); + } else { + scheduler.Record([enabled = regs.gl_cull_test_enabled, + cull_face = regs.gl_cull_face](vk::CommandBuffer cmdbuf) { + cmdbuf.SetCullModeEXT(enabled ? MaxwellToVK::CullFace(cull_face) : VK_CULL_MODE_NONE); + }); + } } void RasterizerVulkan::UpdateDepthBoundsTestEnable(Tegra::Engines::Maxwell3D::Regs& regs) { @@ -1358,43 +1646,51 @@ void RasterizerVulkan::UpdateDepthBoundsTestEnable(Tegra::Engines::Maxwell3D::Re }); } -void RasterizerVulkan::UpdateDepthTestEnable(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateDepthTestEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchDepthTestEnable()) { return; } - scheduler.Record([enable = regs.depth_test_enable](vk::CommandBuffer cmdbuf) { - cmdbuf.SetDepthTestEnableEXT(enable); - }); + if (cmdbuf) { + cmdbuf->SetDepthTestEnableEXT(regs.depth_test_enable); + } else { + scheduler.Record([enable = regs.depth_test_enable](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthTestEnableEXT(enable); }); + } } -void RasterizerVulkan::UpdateDepthWriteEnable(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateDepthWriteEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchDepthWriteEnable()) { return; } - scheduler.Record([enable = regs.depth_write_enabled](vk::CommandBuffer cmdbuf) { - cmdbuf.SetDepthWriteEnableEXT(enable); - }); + if (cmdbuf) { + cmdbuf->SetDepthWriteEnableEXT(regs.depth_write_enabled); + } else { + scheduler.Record([enable = regs.depth_write_enabled](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthWriteEnableEXT(enable); }); + } } -void RasterizerVulkan::UpdatePrimitiveRestartEnable(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdatePrimitiveRestartEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchPrimitiveRestartEnable()) { return; } - scheduler.Record([enable = regs.primitive_restart.enabled](vk::CommandBuffer cmdbuf) { - cmdbuf.SetPrimitiveRestartEnableEXT(enable); - }); + if (cmdbuf) { + cmdbuf->SetPrimitiveRestartEnableEXT(regs.primitive_restart.enabled); + } else { + scheduler.Record([enable = regs.primitive_restart.enabled](vk::CommandBuffer cmdbuf) { cmdbuf.SetPrimitiveRestartEnableEXT(enable); }); + } } -void RasterizerVulkan::UpdateRasterizerDiscardEnable(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateRasterizerDiscardEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchRasterizerDiscardEnable()) { return; } - scheduler.Record([disable = regs.rasterize_enable](vk::CommandBuffer cmdbuf) { - cmdbuf.SetRasterizerDiscardEnableEXT(disable == 0); - }); + if (cmdbuf) { + cmdbuf->SetRasterizerDiscardEnableEXT(regs.rasterize_enable == 0); + } else { + scheduler.Record([disable = regs.rasterize_enable](vk::CommandBuffer cmdbuf) { cmdbuf.SetRasterizerDiscardEnableEXT(disable == 0); }); + } } -void RasterizerVulkan::UpdateConservativeRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateConservativeRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchConservativeRasterizationMode()) { return; } @@ -1402,15 +1698,20 @@ void RasterizerVulkan::UpdateConservativeRasterizationMode(Tegra::Engines::Maxwe if (!device.SupportsDynamicState3ConservativeRasterizationMode()) { return; } - - scheduler.Record([enable = regs.conservative_raster_enable](vk::CommandBuffer cmdbuf) { - cmdbuf.SetConservativeRasterizationModeEXT( - enable ? VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT - : VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT); - }); + if (cmdbuf) { + cmdbuf->SetConservativeRasterizationModeEXT( + regs.conservative_raster_enable ? VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT + : VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT); + } else { + scheduler.Record([enable = regs.conservative_raster_enable](vk::CommandBuffer cmdbuf) { + cmdbuf.SetConservativeRasterizationModeEXT( + enable ? VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT + : VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT); + }); + } } -void RasterizerVulkan::UpdateLineStippleEnable(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateLineStippleEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchLineStippleEnable()) { return; } @@ -1418,13 +1719,16 @@ void RasterizerVulkan::UpdateLineStippleEnable(Tegra::Engines::Maxwell3D::Regs& if (!device.SupportsDynamicState3LineStippleEnable()) { return; } - - scheduler.Record([enable = regs.line_stipple_enable](vk::CommandBuffer cmdbuf) { - cmdbuf.SetLineStippleEnableEXT(enable); - }); + if (cmdbuf) { + cmdbuf->SetLineStippleEnableEXT(regs.line_stipple_enable); + } else { + scheduler.Record([enable = regs.line_stipple_enable](vk::CommandBuffer cmdbuf) { + cmdbuf.SetLineStippleEnableEXT(enable); + }); + } } -void RasterizerVulkan::UpdateLineRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateLineRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!device.IsExtLineRasterizationSupported()) { return; } @@ -1456,12 +1760,16 @@ void RasterizerVulkan::UpdateLineRasterizationMode(Tegra::Engines::Maxwell3D::Re }); } } - scheduler.Record([mode](vk::CommandBuffer cmdbuf) { - cmdbuf.SetLineRasterizationModeEXT(mode); - }); + if (cmdbuf) { + cmdbuf->SetLineRasterizationModeEXT(mode); + } else { + scheduler.Record([mode](vk::CommandBuffer cmdbuf) { + cmdbuf.SetLineRasterizationModeEXT(mode); + }); + } } -void RasterizerVulkan::UpdateDepthBiasEnable(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateDepthBiasEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchDepthBiasEnable()) { return; } @@ -1492,23 +1800,30 @@ void RasterizerVulkan::UpdateDepthBiasEnable(Tegra::Engines::Maxwell3D::Regs& re }; const u32 topology_index = static_cast(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 != 0); }); + if (cmdbuf) { + cmdbuf->SetDepthBiasEnableEXT(enable != 0); + } else { + scheduler.Record([enable](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthBiasEnableEXT(enable != 0); }); + } } -void RasterizerVulkan::UpdateLogicOpEnable(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateLogicOpEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchLogicOpEnable()) { return; } if (!device.SupportsDynamicState3LogicOpEnable()) { return; } - scheduler.Record([enable = regs.logic_op.enable](vk::CommandBuffer cmdbuf) { - cmdbuf.SetLogicOpEnableEXT(enable != 0); - }); + if (cmdbuf) { + cmdbuf->SetLogicOpEnableEXT(regs.logic_op.enable != 0); + } else { + scheduler.Record([enable = regs.logic_op.enable](vk::CommandBuffer cmdbuf) { + cmdbuf.SetLogicOpEnableEXT(enable != 0); + }); + } } -void RasterizerVulkan::UpdateDepthClampEnable(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateDepthClampEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchDepthClampEnable()) { return; } @@ -1521,11 +1836,14 @@ void RasterizerVulkan::UpdateDepthClampEnable(Tegra::Engines::Maxwell3D::Regs& r Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ || regs.viewport_clip_control.geometry_clip == Maxwell::ViewportClipControl::GeometryClip::FrustumZ); - scheduler.Record( - [is_enabled](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthClampEnableEXT(is_enabled); }); + if (cmdbuf) { + cmdbuf->SetDepthClampEnableEXT(is_enabled); + } else { + scheduler.Record([is_enabled](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthClampEnableEXT(is_enabled); }); + } } -void RasterizerVulkan::UpdateAlphaToCoverageEnable(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateAlphaToCoverageEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchAlphaToCoverageEnable()) { return; } @@ -1535,12 +1853,16 @@ void RasterizerVulkan::UpdateAlphaToCoverageEnable(Tegra::Engines::Maxwell3D::Re GraphicsPipeline* const pipeline = pipeline_cache.CurrentGraphicsPipeline(); const bool enable = pipeline != nullptr && pipeline->SupportsAlphaToCoverage() && regs.anti_alias_alpha_control.alpha_to_coverage != 0; - scheduler.Record([enable](vk::CommandBuffer cmdbuf) { - cmdbuf.SetAlphaToCoverageEnableEXT(enable ? VK_TRUE : VK_FALSE); - }); + if (cmdbuf) { + cmdbuf->SetAlphaToCoverageEnableEXT(enable ? VK_TRUE : VK_FALSE); + } else { + scheduler.Record([enable](vk::CommandBuffer cmdbuf) { + cmdbuf.SetAlphaToCoverageEnableEXT(enable ? VK_TRUE : VK_FALSE); + }); + } } -void RasterizerVulkan::UpdateAlphaToOneEnable(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateAlphaToOneEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchAlphaToOneEnable()) { return; } @@ -1555,21 +1877,29 @@ void RasterizerVulkan::UpdateAlphaToOneEnable(Tegra::Engines::Maxwell3D::Regs& r GraphicsPipeline* const pipeline = pipeline_cache.CurrentGraphicsPipeline(); const bool enable = pipeline != nullptr && pipeline->SupportsAlphaToOne() && regs.anti_alias_alpha_control.alpha_to_one != 0; - scheduler.Record([enable](vk::CommandBuffer cmdbuf) { - cmdbuf.SetAlphaToOneEnableEXT(enable ? VK_TRUE : VK_FALSE); - }); + if (cmdbuf) { + cmdbuf->SetAlphaToOneEnableEXT(enable ? VK_TRUE : VK_FALSE); + } else { + scheduler.Record([enable](vk::CommandBuffer cmdbuf) { + cmdbuf.SetAlphaToOneEnableEXT(enable ? VK_TRUE : VK_FALSE); + }); + } } -void RasterizerVulkan::UpdateDepthCompareOp(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateDepthCompareOp(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchDepthCompareOp()) { return; } - scheduler.Record([func = regs.depth_test_func](vk::CommandBuffer cmdbuf) { - cmdbuf.SetDepthCompareOpEXT(MaxwellToVK::ComparisonOp(func)); - }); + if (cmdbuf) { + cmdbuf->SetDepthCompareOpEXT(MaxwellToVK::ComparisonOp(regs.depth_test_func)); + } else { + scheduler.Record([func = regs.depth_test_func](vk::CommandBuffer cmdbuf) { + cmdbuf.SetDepthCompareOpEXT(MaxwellToVK::ComparisonOp(func)); + }); + } } -void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchFrontFace()) { return; } @@ -1579,11 +1909,14 @@ void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) { front_face = front_face == VK_FRONT_FACE_CLOCKWISE ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE; } - scheduler.Record( - [front_face](vk::CommandBuffer cmdbuf) { cmdbuf.SetFrontFaceEXT(front_face); }); + if (cmdbuf) { + cmdbuf->SetFrontFaceEXT(front_face); + } else { + scheduler.Record([front_face](vk::CommandBuffer cmdbuf) { cmdbuf.SetFrontFaceEXT(front_face); }); + } } -void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchStencilOp()) { return; } @@ -1597,37 +1930,57 @@ void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs) { const Maxwell::StencilOp::Op back_zfail = regs.stencil_back_op.zfail; const Maxwell::StencilOp::Op back_zpass = regs.stencil_back_op.zpass; const Maxwell::ComparisonOp back_compare = regs.stencil_back_op.func; - scheduler.Record([fail, zfail, zpass, compare, back_fail, back_zfail, back_zpass, - back_compare](vk::CommandBuffer cmdbuf) { - cmdbuf.SetStencilOpEXT(VK_STENCIL_FACE_FRONT_BIT, MaxwellToVK::StencilOp(fail), + if (cmdbuf) { + cmdbuf->SetStencilOpEXT(VK_STENCIL_FACE_FRONT_BIT, MaxwellToVK::StencilOp(fail), MaxwellToVK::StencilOp(zpass), MaxwellToVK::StencilOp(zfail), MaxwellToVK::ComparisonOp(compare)); - cmdbuf.SetStencilOpEXT(VK_STENCIL_FACE_BACK_BIT, MaxwellToVK::StencilOp(back_fail), + cmdbuf->SetStencilOpEXT(VK_STENCIL_FACE_BACK_BIT, MaxwellToVK::StencilOp(back_fail), MaxwellToVK::StencilOp(back_zpass), MaxwellToVK::StencilOp(back_zfail), MaxwellToVK::ComparisonOp(back_compare)); - }); + } else { + scheduler.Record([fail, zfail, zpass, compare, back_fail, back_zfail, back_zpass, + back_compare](vk::CommandBuffer cmdbuf) { + cmdbuf.SetStencilOpEXT(VK_STENCIL_FACE_FRONT_BIT, MaxwellToVK::StencilOp(fail), + MaxwellToVK::StencilOp(zpass), MaxwellToVK::StencilOp(zfail), + MaxwellToVK::ComparisonOp(compare)); + cmdbuf.SetStencilOpEXT(VK_STENCIL_FACE_BACK_BIT, MaxwellToVK::StencilOp(back_fail), + MaxwellToVK::StencilOp(back_zpass), + MaxwellToVK::StencilOp(back_zfail), + MaxwellToVK::ComparisonOp(back_compare)); + }); + } } else { // Front face defines the stencil op of both faces - scheduler.Record([fail, zfail, zpass, compare](vk::CommandBuffer cmdbuf) { - cmdbuf.SetStencilOpEXT(VK_STENCIL_FACE_FRONT_AND_BACK, MaxwellToVK::StencilOp(fail), + if (cmdbuf) { + cmdbuf->SetStencilOpEXT(VK_STENCIL_FACE_FRONT_AND_BACK, MaxwellToVK::StencilOp(fail), MaxwellToVK::StencilOp(zpass), MaxwellToVK::StencilOp(zfail), MaxwellToVK::ComparisonOp(compare)); - }); + } else { + scheduler.Record([fail, zfail, zpass, compare](vk::CommandBuffer cmdbuf) { + cmdbuf.SetStencilOpEXT(VK_STENCIL_FACE_FRONT_AND_BACK, MaxwellToVK::StencilOp(fail), + MaxwellToVK::StencilOp(zpass), MaxwellToVK::StencilOp(zfail), + MaxwellToVK::ComparisonOp(compare)); + }); + } } } -void RasterizerVulkan::UpdateLogicOp(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateLogicOp(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchLogicOp()) { return; } const auto op_value = static_cast(regs.logic_op.op); auto op = op_value >= 0x1500 && op_value < 0x1510 ? static_cast(op_value - 0x1500) : VK_LOGIC_OP_NO_OP; - scheduler.Record([op](vk::CommandBuffer cmdbuf) { cmdbuf.SetLogicOpEXT(op); }); + if (cmdbuf) { + cmdbuf->SetLogicOpEXT(op); + } else { + scheduler.Record([op](vk::CommandBuffer cmdbuf) { cmdbuf.SetLogicOpEXT(op); }); + } } -void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { if (!state_tracker.TouchBlending()) { return; } @@ -1650,9 +2003,13 @@ void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs) { current |= VK_COLOR_COMPONENT_A_BIT; } } - scheduler.Record([setup_masks](vk::CommandBuffer cmdbuf) { - cmdbuf.SetColorWriteMaskEXT(0, setup_masks); - }); + if (cmdbuf) { + cmdbuf->SetColorWriteMaskEXT(0, setup_masks); + } else { + scheduler.Record([setup_masks](vk::CommandBuffer cmdbuf) { + cmdbuf.SetColorWriteMaskEXT(0, setup_masks); + }); + } } if (state_tracker.TouchBlendEnable()) { @@ -1660,9 +2017,13 @@ void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs) { std::ranges::transform( regs.blend.enable, setup_enables.begin(), [&](const auto& is_enabled) { return is_enabled != 0 ? VK_TRUE : VK_FALSE; }); - scheduler.Record([setup_enables](vk::CommandBuffer cmdbuf) { - cmdbuf.SetColorBlendEnableEXT(0, setup_enables); - }); + if (cmdbuf) { + cmdbuf->SetColorBlendEnableEXT(0, setup_enables); + } else { + scheduler.Record([setup_enables](vk::CommandBuffer cmdbuf) { + cmdbuf.SetColorBlendEnableEXT(0, setup_enables); + }); + } } if (state_tracker.TouchBlendEquations()) { @@ -1702,22 +2063,30 @@ void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs) { } } - scheduler.Record([setup_blends](vk::CommandBuffer cmdbuf) { - cmdbuf.SetColorBlendEquationEXT(0, setup_blends); + if (cmdbuf) { + cmdbuf->SetColorBlendEquationEXT(0, setup_blends); + } else { + scheduler.Record([setup_blends](vk::CommandBuffer cmdbuf) { + cmdbuf.SetColorBlendEquationEXT(0, setup_blends); + }); + } + } +} + +void RasterizerVulkan::UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { + if (!state_tracker.TouchStencilTestEnable()) { + return; + } + if (cmdbuf) { + cmdbuf->SetStencilTestEnableEXT(regs.stencil_enable); + } else { + scheduler.Record([enable = regs.stencil_enable](vk::CommandBuffer cmdbuf) { + cmdbuf.SetStencilTestEnableEXT(enable); }); } } -void RasterizerVulkan::UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs) { - if (!state_tracker.TouchStencilTestEnable()) { - return; - } - scheduler.Record([enable = regs.stencil_enable](vk::CommandBuffer cmdbuf) { - cmdbuf.SetStencilTestEnableEXT(enable); - }); -} - -void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) { +void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf) { auto& dirty{maxwell3d->dirty.flags}; if (!dirty[Dirty::VertexInput]) { return; @@ -1770,9 +2139,13 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) .divisor = is_instanced ? input_binding.frequency : 1, }); } - scheduler.Record([bindings, attributes](vk::CommandBuffer cmdbuf) { - cmdbuf.SetVertexInputEXT(bindings, attributes); - }); + if (cmdbuf) { + cmdbuf->SetVertexInputEXT(bindings, attributes); + } else { + scheduler.Record([bindings, attributes](vk::CommandBuffer cmdbuf) { + cmdbuf.SetVertexInputEXT(bindings, attributes); + }); + } } void RasterizerVulkan::InitializeChannel(Tegra::Control::ChannelState& channel) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index b689c6b660..6012d0b07e 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -161,37 +161,38 @@ private: void HandleTransformFeedback(); - void UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateBlendConstants(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateDepthBounds(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs); + void UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateBlendConstants(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateDepthBounds(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); - void UpdateCullMode(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateDepthBoundsTestEnable(Tegra::Engines::Maxwell3D::Regs& regs); - 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 UpdateConservativeRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateLineStippleEnable(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateLineStipple(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateLineRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateDepthBiasEnable(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateLogicOpEnable(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateDepthClampEnable(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateAlphaToCoverageEnable(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateAlphaToOneEnable(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); - void UpdateLogicOp(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs); + void UpdateCullMode(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateDepthBoundsTestEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateDepthTestEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateDepthWriteEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateDepthCompareOp(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdatePrimitiveRestartEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateRasterizerDiscardEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateConservativeRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateLineStippleEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateLineStipple(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateLineRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateDepthBiasEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateLogicOpEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateDepthClampEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateAlphaToCoverageEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateAlphaToOneEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateLogicOp(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); - void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs); + void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs, vk::CommandBuffer* cmdbuf = nullptr); + void RecordDynamicStates(vk::CommandBuffer cmdbuf); Tegra::GPU& gpu; Tegra::MaxwellDeviceMemoryManager& device_memory; diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 63e1154bc2..7ce5c231bf 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -663,11 +663,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR "allowing Eden to use {} (75%) to avoid heap exhaustion", sampler_limit, reserved, sampler_heap_budget); } - // Qualcomm proprietary drivers have issues with MSAA->MSAA image blits. - LOG_WARNING(Render_Vulkan, - "Qualcomm drivers do not support MSAA->MSAA image blits. " - "MSAA scaling will use 3D helpers. MSAA resolves work normally."); - cant_blit_msaa = true; } if (extensions.sampler_filter_minmax && is_amd) { @@ -1259,7 +1254,6 @@ bool Device::GetSuitability(bool requires_swapchain) { features.extended_dynamic_state3.extendedDynamicState3LogicOpEnable = false; } - // Return whether we were suitable. return suitable; } @@ -1360,7 +1354,6 @@ void Device::RemoveUnsuitableExtensions() { VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); // VK_EXT_robustness2 - // Enable if at least one robustness2 feature is available extensions.robustness_2 = features.robustness2.robustBufferAccess2 || features.robustness2.robustImageAccess2 || features.robustness2.nullDescriptor; @@ -1369,7 +1362,6 @@ void Device::RemoveUnsuitableExtensions() { VK_EXT_ROBUSTNESS_2_EXTENSION_NAME); // VK_EXT_image_robustness - // Enable if robustImageAccess is available extensions.image_robustness = features.image_robustness.robustImageAccess; RemoveExtensionFeatureIfUnsuitable(extensions.image_robustness, features.image_robustness, VK_EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME); @@ -1523,15 +1515,15 @@ void Device::RemoveUnsuitableExtensions() { RemoveExtensionFeatureIfUnsuitable(extensions.maintenance6, features.maintenance6, VK_KHR_MAINTENANCE_6_EXTENSION_NAME); - // VK_KHR_maintenance7 (proposed for Vulkan 1.4, no features) + // VK_KHR_maintenance7 extensions.maintenance7 = loaded_extensions.contains(VK_KHR_MAINTENANCE_7_EXTENSION_NAME); RemoveExtensionIfUnsuitable(extensions.maintenance7, VK_KHR_MAINTENANCE_7_EXTENSION_NAME); - // VK_KHR_maintenance8 (proposed for Vulkan 1.4, no features) + // VK_KHR_maintenance8 extensions.maintenance8 = loaded_extensions.contains(VK_KHR_MAINTENANCE_8_EXTENSION_NAME); RemoveExtensionIfUnsuitable(extensions.maintenance8, VK_KHR_MAINTENANCE_8_EXTENSION_NAME); - // VK_KHR_maintenance9 (proposed for Vulkan 1.4, no features) + // VK_KHR_maintenance9 extensions.maintenance9 = loaded_extensions.contains(VK_KHR_MAINTENANCE_9_EXTENSION_NAME); RemoveExtensionIfUnsuitable(extensions.maintenance9, VK_KHR_MAINTENANCE_9_EXTENSION_NAME);