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);