diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index f0c253dffb..014b4a318e 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -806,58 +806,6 @@ void BufferCache

::UpdateVertexBufferSlot(u32 index, const Binding& binding) { template void BufferCache

::BindHostVertexBuffers() { - bool needs_vertex_input_refresh = false; - bool use_vertex_input_dynamic_state = false; - bool use_dynamic_stride = false; - u32 max_dynamic_stride = 0; - std::array min_dynamic_stride{}; - if constexpr (!IS_OPENGL) { - use_vertex_input_dynamic_state = runtime.UsesVertexInputDynamicState(); - if (use_vertex_input_dynamic_state) { - for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) { - if (maxwell3d->dirty.flags[Dirty::VertexBuffer0 + index]) { - needs_vertex_input_refresh = true; - break; - } - } - } - - use_dynamic_stride = runtime.UsesDynamicVertexBindingStride(); - if (use_dynamic_stride) { - max_dynamic_stride = runtime.GetMaxVertexInputBindingStride(); - for (const auto& attribute : maxwell3d->regs.vertex_attrib_format) { - if (attribute.constant != 0) { - continue; - } - const u32 binding = attribute.buffer; - if (binding >= NUM_VERTEX_BUFFERS) { - continue; - } - const u32 extent = attribute.offset + attribute.SizeInBytes(); - min_dynamic_stride[binding] = (std::max)(min_dynamic_stride[binding], extent); - } - } - } - - const auto sanitize_stride = [&](u32 binding, u32 stride) -> u32 { - if constexpr (IS_OPENGL) { - return stride; - } else { - if (!use_dynamic_stride || stride == 0) { - return stride; - } - const u32 min_stride = min_dynamic_stride[binding]; - const u32 required_stride = (std::max)(stride, min_stride); - if (required_stride <= max_dynamic_stride) { - return required_stride; - } - if (min_stride > max_dynamic_stride) { - return 0; - } - return max_dynamic_stride; - } - }; - #ifdef ANDROID const bool use_optimized_vertex_buffers = Settings::values.use_optimized_vertex_buffers.GetValue(); #else @@ -890,8 +838,7 @@ void BufferCache

::BindHostVertexBuffers() { continue; } flags[Dirty::VertexBuffer0 + index] = false; - const u32 stride = - sanitize_stride(index, maxwell3d->regs.vertex_streams[index].stride); + const u32 stride = maxwell3d->regs.vertex_streams[index].stride; const u32 offset = buffer.Offset(binding.device_addr); buffer.MarkUsage(offset, binding.size); if (!bindings.buffers.empty() && index != last_index + 1) { @@ -934,8 +881,7 @@ void BufferCache

::BindHostVertexBuffers() { const Binding& binding = channel_state->vertex_buffers[index]; Buffer& buffer = slot_buffers[binding.buffer_id]; - const u32 stride = - sanitize_stride(index, maxwell3d->regs.vertex_streams[index].stride); + const u32 stride = maxwell3d->regs.vertex_streams[index].stride; const u32 offset = buffer.Offset(binding.device_addr); buffer.MarkUsage(offset, binding.size); @@ -947,12 +893,6 @@ void BufferCache

::BindHostVertexBuffers() { runtime.BindVertexBuffers(host_bindings); } } - - if constexpr (!IS_OPENGL) { - if (needs_vertex_input_refresh) { - runtime.NotifyVertexInputBindingChange(); - } - } } template diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 9f19f802f3..c8dd68e3dc 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 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -161,28 +161,6 @@ public: return max_dynamic_storage_buffers; } - bool UsesDynamicVertexBindingStride() const { - return device.IsExtExtendedDynamicStateSupported() && !use_vertex_input_dynamic_state; - } - - bool UsesVertexInputDynamicState() const { - return use_vertex_input_dynamic_state; - } - - void NotifyVertexInputBindingChange() { - needs_vertex_input_refresh = true; - } - - bool ConsumeVertexInputBindingChange() { - const bool refresh = needs_vertex_input_refresh; - needs_vertex_input_refresh = false; - return refresh; - } - - u32 GetMaxVertexInputBindingStride() const { - return device.GetMaxVertexInputBindingStride(); - } - private: void BindBuffer(VkBuffer buffer, u32 offset, u32 size) { guest_descriptor_queue.AddBuffer(buffer, offset, size); @@ -206,7 +184,6 @@ private: QuadIndexedPass quad_index_pass; bool use_vertex_input_dynamic_state = false; - bool needs_vertex_input_refresh = false; bool limit_dynamic_storage_buffers = false; u32 max_dynamic_storage_buffers = (std::numeric_limits::max)(); }; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index e3e2737e3b..1a41e50a36 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -82,9 +82,6 @@ public: const std::array& infos); bool HasDynamicVertexInput() const noexcept { return key.state.dynamic_vertex_input; } - bool UsesVertexAttribute(size_t index) const noexcept { - return index < Maxwell::NumVertexAttributes && stage_infos[0].loads.Generic(index); - } bool SupportsAlphaToCoverage() const noexcept { return fragment_has_color0_output; } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 108e6d649e..ad431c9ac5 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1014,6 +1014,20 @@ void RasterizerVulkan::UpdateDynamicStates() { // EDS3 Enables: LogicOpEnable, DepthClamp, LineStipple, ConservativeRaster if (device.IsExtExtendedDynamicState3EnablesSupported()) { + using namespace Tegra::Engines; + // AMD Workaround: LogicOp incompatible with float render targets + if (device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_OPEN_SOURCE || + device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_PROPRIETARY) { + const auto has_float = std::any_of( + regs.vertex_attrib_format.begin(), regs.vertex_attrib_format.end(), + [](const auto& attrib) { + return attrib.type == Maxwell3D::Regs::VertexAttribute::Type::Float; + } + ); + if (regs.logic_op.enable) { + regs.logic_op.enable = static_cast(!has_float); + } + } UpdateLogicOpEnable(regs); UpdateDepthClampEnable(regs); UpdateLineRasterizationMode(regs); @@ -1031,7 +1045,7 @@ void RasterizerVulkan::UpdateDynamicStates() { // Vertex Input Dynamic State: Independent from EDS levels if (device.IsExtVertexInputDynamicStateSupported()) { if (auto* gp = pipeline_cache.CurrentGraphicsPipeline(); gp && gp->HasDynamicVertexInput()) { - UpdateVertexInput(regs, *gp); + UpdateVertexInput(regs); } } } @@ -1711,11 +1725,9 @@ void RasterizerVulkan::UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& }); } -void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs, - const GraphicsPipeline& pipeline) { +void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) { auto& dirty{maxwell3d->dirty.flags}; - const bool force_vertex_input_refresh = buffer_cache_runtime.ConsumeVertexInputBindingChange(); - if (!dirty[Dirty::VertexInput] && !force_vertex_input_refresh) { + if (!dirty[Dirty::VertexInput]) { return; } dirty[Dirty::VertexInput] = false; @@ -1746,9 +1758,6 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs, if (attribute.constant) { continue; } - if (!pipeline.UsesVertexAttribute(index)) { - continue; - } const size_t binding{attribute.buffer}; if (binding >= max_vertex_bindings) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index b3bf6c8b7c..b689c6b660 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -191,8 +191,7 @@ private: void UpdateLogicOp(Tegra::Engines::Maxwell3D::Regs& regs); void UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs); - void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs, - const GraphicsPipeline& pipeline); + void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs); Tegra::GPU& gpu; Tegra::MaxwellDeviceMemoryManager& device_memory; diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index f974505b2d..226619d8d6 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -153,17 +153,11 @@ void Scheduler::RequestOutsideRenderPassOperationContext() { } bool Scheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) { - const auto consume_eds_refresh = [this] { - if (!state.needs_state_enable_refresh) { - return; - } - state_tracker.InvalidateExtendedDynamicStateFlags(); - state.needs_state_enable_refresh = false; - }; - if (state.graphics_pipeline == pipeline) { - if (pipeline && pipeline->UsesExtendedDynamicState()) { - consume_eds_refresh(); + if (pipeline && pipeline->UsesExtendedDynamicState() && + state.needs_state_enable_refresh) { + state_tracker.InvalidateStateEnableFlag(); + state.needs_state_enable_refresh = false; } return false; } @@ -176,8 +170,9 @@ bool Scheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) { if (!pipeline->UsesExtendedDynamicState()) { state.needs_state_enable_refresh = true; - } else { - consume_eds_refresh(); + } else if (state.needs_state_enable_refresh) { + state_tracker.InvalidateStateEnableFlag(); + state.needs_state_enable_refresh = false; } return true; diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h index f7c61ed7ef..74bae9e181 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.h +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -101,37 +101,6 @@ public: (*flags)[Dirty::StateEnable] = true; } - void InvalidateExtendedDynamicStateFlags() { - InvalidateStateEnableFlag(); - - (*flags)[Dirty::CullMode] = true; - (*flags)[Dirty::DepthCompareOp] = true; - (*flags)[Dirty::FrontFace] = true; - (*flags)[Dirty::StencilOp] = true; - (*flags)[Dirty::DepthBoundsEnable] = true; - (*flags)[Dirty::DepthTestEnable] = true; - (*flags)[Dirty::DepthWriteEnable] = true; - (*flags)[Dirty::StencilTestEnable] = true; - - (*flags)[Dirty::PrimitiveRestartEnable] = true; - (*flags)[Dirty::RasterizerDiscardEnable] = true; - (*flags)[Dirty::DepthBiasEnable] = true; - (*flags)[Dirty::LogicOp] = true; - - (*flags)[Dirty::LogicOpEnable] = true; - (*flags)[Dirty::DepthClampEnable] = true; - (*flags)[Dirty::LineRasterizationMode] = true; - (*flags)[Dirty::LineStippleEnable] = true; - (*flags)[Dirty::ConservativeRasterizationMode] = true; - (*flags)[Dirty::AlphaToCoverageEnable] = true; - (*flags)[Dirty::AlphaToOneEnable] = true; - - (*flags)[Dirty::Blending] = true; - (*flags)[Dirty::ColorMask] = true; - (*flags)[Dirty::BlendEnable] = true; - (*flags)[Dirty::BlendEquations] = true; - } - bool TouchViewports() { const bool dirty_viewports = Exchange(Dirty::Viewports, false); const bool rescale_viewports = Exchange(VideoCommon::Dirty::RescaleViewports, false); diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 7777f945f4..8914ef0eb3 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -783,10 +783,6 @@ public: return properties.properties.limits.maxVertexInputBindings; } - u32 GetMaxVertexInputBindingStride() const { - return properties.properties.limits.maxVertexInputBindingStride; - } - u32 GetMaxViewports() const { return properties.properties.limits.maxViewports; }