diff options
| author | PastaLaPate <pastalapate@proton.me> | 2026-11-02 20:34:15 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-11-02 20:34:15 +0100 |
| commit | 6f002badce45fa2fdb414043544c829e834a7e27 (patch) | |
| tree | 51c21a851fbc8218ebe7febb69fb710a891cc4fc /src/video_core/renderer_vulkan/vk_rasterizer.cpp | |
| parent | 396f011ea875dfe4fdb1b0f489651ab74a505b74 (diff) | |
| parent | 046646e3514ca4950622d75609e68498f889989e (diff) | |
Merge branch 'nx2' into ci/qt-6.12.0
Diffstat (limited to 'src/video_core/renderer_vulkan/vk_rasterizer.cpp')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index bbb49d5432..978f8be547 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,6 +280,22 @@ 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); @@ -553,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, @@ -585,6 +608,14 @@ void RasterizerVulkan::DrawIndirect() { const auto& params = maxwell3d->draw_manager.indirect_state; buffer_cache.SetDrawIndirect(¶ms); PrepareDraw(params.is_indexed, [this, ¶ms] { + 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; @@ -891,6 +922,11 @@ void RasterizerVulkan::DispatchCompute() { return; } std::scoped_lock lock{texture_cache.mutex, buffer_cache.mutex}; + // Command list pages the dispatch writes are copied for the split's front right after it. + buffer_cache.Nx2CollectListCopies(true); + SCOPE_EXIT { + buffer_cache.Nx2CollectListCopies(false); + }; if (!pipeline->Configure(*kepler_compute, *gpu_memory, scheduler, buffer_cache, texture_cache)) { if (kepler_compute->IsNativeMode()) throw Shader::RuntimeError("Native compute resources unavailable"); @@ -913,6 +949,7 @@ void RasterizerVulkan::DispatchCompute() { } cmdbuf.DispatchIndirect(indirect_buffer, indirect_offset); }); + SubmitNx2ListCopies(); return; } const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z}; @@ -935,6 +972,7 @@ void RasterizerVulkan::DispatchCompute() { } cmdbuf.Dispatch(dim[0], dim[1], dim[2]); }); + SubmitNx2ListCopies(); // Log compute dispatch if (GPU::Logging::IsActive() && @@ -976,6 +1014,29 @@ void Vulkan::RasterizerVulkan::DisableGraphicsUniformBuffer(size_t stage, u32 in void RasterizerVulkan::FlushAll() {} +void RasterizerVulkan::SubmitNx2ListCopies() { + if (buffer_cache.Nx2CopyListPages(scheduler.CurrentTick())) { + scheduler.Flush(); + } +} + +VideoCore::RasterizerInterface::GpuWrittenList RasterizerVulkan::ReadGpuWrittenCommandList( + DAddr addr, std::span<u8> out) { + // No cache lock: the front only reads the copies, under their own lock. + switch (buffer_cache.Nx2ReadListCopy(addr, out)) { + case BufferCache::Nx2ListRead::Copied: + return GpuWrittenList::Copied; + case BufferCache::Nx2ListRead::Synced: + return GpuWrittenList::Synced; + default: + return GpuWrittenList::Unknown; + } +} + +void RasterizerVulkan::NoteGpuWrittenCommandListSynced(DAddr page) { + buffer_cache.Nx2NoteListSynced(page); +} + void RasterizerVulkan::FlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) { if (addr == 0 || size == 0) { return; @@ -1212,6 +1273,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(); @@ -1287,6 +1349,8 @@ void RasterizerVulkan::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si bool uploaded; { std::scoped_lock lock{buffer_cache.mutex}; + // Guest memory has the words now: a command list copy of the page no longer does. + buffer_cache.Nx2NoteListHostWrite(*cpu_addr, copy_size); uploaded = buffer_cache.InlineMemory(*cpu_addr, copy_size, memory); if (!uploaded && !defer) { buffer_cache.WriteMemory(*cpu_addr, copy_size); @@ -1382,7 +1446,13 @@ bool AccelerateDMA::BufferClear(GPUVAddr src_address, u64 amount, u32 value) { bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) { std::scoped_lock lock{buffer_cache.mutex}; - return buffer_cache.DMACopy(src_address, dest_address, amount); + buffer_cache.Nx2CollectListCopies(true); + const bool copied = buffer_cache.DMACopy(src_address, dest_address, amount); + if (buffer_cache.Nx2CopyListPages(scheduler.CurrentTick())) { + scheduler.Flush(); + } + buffer_cache.Nx2CollectListCopies(false); + return copied; } template <bool IS_IMAGE_UPLOAD> |
