aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan/vk_rasterizer.cpp
diff options
context:
space:
mode:
authorkraibse <33869366+kraibse@users.noreply.github.com>2026-11-02 16:01:57 +0100
committerkraibse <33869366+kraibse@users.noreply.github.com>2026-11-02 16:01:57 +0100
commitb374709aa202d586dd09f81f3389da8d73fea0d7 (patch)
tree5c4033d827c517aca9cc73dc497fbb3e81291bf1 /src/video_core/renderer_vulkan/vk_rasterizer.cpp
parent021c9724371e45fa694c9ee3106b9011364d2853 (diff)
parentce1b1de6f1beed36958368f89cda466937ff9716 (diff)
Merge remote-tracking branch 'origin/nx2' into codex/upstream-loading-hotkeys
Diffstat (limited to 'src/video_core/renderer_vulkan/vk_rasterizer.cpp')
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp57
1 files changed, 55 insertions, 2 deletions
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index cb31a0e7e4..d3dbba6163 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -9,6 +9,7 @@
#include <memory>
#include <cstdio>
#include <cstdlib>
+#include <filesystem>
#include <tuple>
#include <set>
#include <fstream>
@@ -279,9 +280,37 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
report_failure("no pipeline");
return;
}
+ // Task/mesh pipelines: the draw's vertex count is the number of task workgroups.
+ mesh_draw = pipeline->IsMeshPipeline();
+ // EDEN_NX2_NO_MESH=1: skip task/mesh draws as before they were supported (A/B comparisons).
+ // EDEN_NX2_NO_MESH_FILE=<path>: skip them while that file exists (checked every 1024 draws),
+ // to compare the same scene with and without them in one run.
+ static const bool no_mesh_always{std::getenv("EDEN_NX2_NO_MESH") != nullptr};
+ static const char* const no_mesh_file{std::getenv("EDEN_NX2_NO_MESH_FILE")};
+ static bool no_mesh{no_mesh_always};
+ static u32 no_mesh_check{};
+ if (no_mesh_file && (no_mesh_check++ % 1024) == 0) {
+ no_mesh = std::filesystem::exists(no_mesh_file);
+ }
+ if (mesh_draw && (no_mesh || !device.IsExtMeshShaderSupported())) {
+ report_failure(no_mesh ? "EDEN_NX2_NO_MESH" : "no VK_EXT_mesh_shader");
+ return;
+ }
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
// update engine as channel may be different.
pipeline->SetEngine(maxwell3d, gpu_memory);
+ const u32 repack_dirty = buffer_cache_runtime.SetVertexRepackLayout(
+ maxwell3d->regs, pipeline->HasDynamicVertexInput());
+ if (repack_dirty) {
+ auto& flags = maxwell3d->dirty.flags;
+ flags[VideoCommon::Dirty::VertexBuffers] = true;
+ flags[Dirty::VertexInput] = true;
+ for (u32 binding = 0; binding < 32; ++binding) {
+ if (repack_dirty & (1U << binding)) {
+ flags[VideoCommon::Dirty::VertexBuffer0 + binding] = true;
+ }
+ }
+ }
if (Profile::Scope scope{Profile::Zone::Configure}; !pipeline->Configure(is_indexed)) {
report_failure("configure failed");
return;
@@ -541,6 +570,12 @@ void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
const u32 num_instances{instance_count};
const DrawParams draw_params{MakeDrawParams(draw_state, num_instances, is_indexed)};
+ if (mesh_draw) {
+ scheduler.Record([groups = draw_params.num_vertices](vk::CommandBuffer cmdbuf) {
+ cmdbuf.DrawMeshTasksEXT(groups, 1, 1);
+ });
+ return;
+ }
scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) {
if (draw_params.is_indexed) {
cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances,
@@ -573,6 +608,14 @@ void RasterizerVulkan::DrawIndirect() {
const auto& params = maxwell3d->draw_manager.indirect_state;
buffer_cache.SetDrawIndirect(&params);
PrepareDraw(params.is_indexed, [this, &params] {
+ if (mesh_draw) {
+ // Indirect task/mesh draws would need vkCmdDrawMeshTasksIndirectEXT's layout.
+ static bool logged{};
+ if (!std::exchange(logged, true)) {
+ LOG_WARNING(Render_Vulkan, "Indirect task/mesh draw skipped");
+ }
+ return;
+ }
const auto indirect_buffer = buffer_cache.GetDrawIndirectBuffer();
const auto& buffer = indirect_buffer.first;
const auto& offset = indirect_buffer.second;
@@ -1200,6 +1243,7 @@ void RasterizerVulkan::FlushCommands() {
void RasterizerVulkan::TickFrame() {
draw_counter = 0;
+ pipeline_cache.TickFrame();
guest_descriptor_queue.TickFrame();
compute_pass_descriptor_queue.TickFrame();
descriptor_buffer_ring.TickFrame();
@@ -1231,6 +1275,14 @@ bool RasterizerVulkan::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surf
return texture_cache.BlitImage(dst, src, copy_config);
}
+bool RasterizerVulkan::AccelerateTemporalUpscale(
+ const Tegra::Engines::Fermi2D::Surface& src, const Tegra::Engines::Fermi2D::Surface& dst,
+ const Tegra::Engines::Fermi2D::Surface& motion_vectors, std::array<f32, 2> jitter,
+ std::array<f32, 2> motion_scale) {
+ std::scoped_lock lock{texture_cache.mutex};
+ return texture_cache.TemporalUpscale(dst, src, motion_vectors, jitter, motion_scale);
+}
+
Tegra::Engines::AccelerateDMAInterface& RasterizerVulkan::AccessAccelerateDMA() {
return accelerate_dma;
}
@@ -2261,7 +2313,8 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs)
.location = index,
.binding = binding,
.format = MaxwellToVK::VertexFormat(device, attribute.type, attribute.size),
- .offset = attribute.offset,
+ .offset = attribute.offset +
+ (buffer_cache_runtime.IsVertexRepacked(binding) && attribute.offset >= 65 ? 3 : 0),
});
}
@@ -2272,7 +2325,7 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs)
.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
.pNext = nullptr,
.binding = binding,
- .stride = input_binding.stride,
+ .stride = buffer_cache_runtime.IsVertexRepacked(binding) ? 72U : input_binding.stride.Value(),
.inputRate = is_instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX,
.divisor = is_instanced ? input_binding.frequency : 1,
});