fix(vulkan): MP4 Mountain Jitter

This commit is contained in:
collecting
2026-02-10 02:03:57 -05:00
parent b04f92eda8
commit 48fa6d0e03
4 changed files with 37 additions and 36 deletions

View File

@@ -163,11 +163,10 @@ void WindowAdaptPass::CreateDescriptorSetLayout() {
}
void WindowAdaptPass::CreatePipelineLayout() {
// Support up to 3 push constant ranges:
// Support up to 2 push constant ranges:
// 0: PresentPushConstants (vertex shader)
// 1: Lanczos quality (fragment shader) - optional
// 2: CRT parameters (fragment shader) - optional
std::array<VkPushConstantRange, 3> ranges{};
// 1: Fragment shader parameters (Lanczos + CRT)
std::array<VkPushConstantRange, 2> ranges{};
// Range 0: The existing constants for the Vertex Shader
ranges[0] = {
@@ -176,16 +175,14 @@ void WindowAdaptPass::CreatePipelineLayout() {
.size = sizeof(PresentPushConstants),
};
// Range 1: Lanczos quality for the Fragment Shader
ranges[1] = {
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.offset = sizeof(PresentPushConstants),
.size = sizeof(s32),
};
// Range 2: CRT parameters for the Fragment Shader
// Offset after PresentPushConstants + Lanczos (if used)
// CRT constants: 8 floats + 1 int = 36 bytes
// Range 1: All parameters for the Fragment Shader (Lanczos + CRT)
// We combine them into a single range because Vulkan does not allow multiple ranges
// for the same stage if they are provided separately in some drivers/configs.
// Spec says: "For each shader stage, there must be at most one push constant range
// that includes that stage in its stageFlags." - actually the spec says:
// "Each element of pPushConstantRanges must contain at least one stage flag in stageFlags"
// and "Any two elements of pPushConstantRanges must not include the same stage flag in
// stageFlags"
struct CRTPushConstants {
float scanline_strength;
float curvature;
@@ -197,10 +194,10 @@ void WindowAdaptPass::CreatePipelineLayout() {
float screen_width;
float screen_height;
};
ranges[2] = {
ranges[1] = {
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.offset = sizeof(PresentPushConstants) + sizeof(s32),
.size = sizeof(CRTPushConstants),
.offset = sizeof(PresentPushConstants),
.size = sizeof(s32) + sizeof(CRTPushConstants),
};
pipeline_layout = device.GetLogical().CreatePipelineLayout(VkPipelineLayoutCreateInfo{

View File

@@ -8,10 +8,11 @@
#include <vector>
#include "common/alignment.h"
#include "common/literals.h"
#include "common/common_types.h"
#include "common/literals.h"
#include "video_core/renderer_vulkan/vk_buffer_cache.h"
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
@@ -660,7 +661,8 @@ vk::Buffer BufferCacheRuntime::CreateNullBuffer() {
.flags = 0,
.size = 4,
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT |
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,

View File

@@ -873,17 +873,16 @@ private:
return;
}
has_flushed_end_pending = true;
UpdateBuffers();
if (!has_started || buffers_count == 0) {
scheduler.Record([](vk::CommandBuffer cmdbuf) {
cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr);
});
UpdateBuffers();
return;
}
scheduler.Record([this, total = static_cast<u32>(buffers_count)](vk::CommandBuffer cmdbuf) {
cmdbuf.BeginTransformFeedbackEXT(0, total, counter_buffers.data(), offsets.data());
});
UpdateBuffers();
}
void FlushEndTFB() {
@@ -899,15 +898,17 @@ private:
cmdbuf.EndTransformFeedbackEXT(0, 0, nullptr, nullptr);
});
} else {
scheduler.Record([this,
total = static_cast<u32>(buffers_count)](vk::CommandBuffer cmdbuf) {
cmdbuf.EndTransformFeedbackEXT(0, total, counter_buffers.data(), offsets.data());
});
scheduler.Record(
[this, total = static_cast<u32>(buffers_count)](vk::CommandBuffer cmdbuf) {
cmdbuf.EndTransformFeedbackEXT(0, total, counter_buffers.data(),
offsets.data());
});
}
} catch (...) {
// If query ending fails, we'll log it but continue
// This prevents crashes from malformed query states
LOG_WARNING(Render_Vulkan, "Failed to end transform feedback query, continuing execution");
LOG_WARNING(Render_Vulkan,
"Failed to end transform feedback query, continuing execution");
}
}
@@ -1188,10 +1189,9 @@ struct QueryCacheRuntimeImpl {
StagingBufferPool& staging_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue,
DescriptorPool& descriptor_pool)
: rasterizer{rasterizer_}, device_memory{device_memory_},
buffer_cache{buffer_cache_}, device{device_},
memory_allocator{memory_allocator_}, scheduler{scheduler_}, staging_pool{staging_pool_},
guest_streamer(0, runtime),
: rasterizer{rasterizer_}, device_memory{device_memory_}, buffer_cache{buffer_cache_},
device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
staging_pool{staging_pool_}, guest_streamer(0, runtime),
sample_streamer(static_cast<size_t>(QueryType::ZPassPixelCount64), runtime, rasterizer,
device, scheduler, memory_allocator, compute_pass_descriptor_queue,
descriptor_pool),

View File

@@ -9,6 +9,7 @@
#include "video_core/renderer_vulkan/renderer_vulkan.h"
#include "citron/util/title_ids.h"
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
@@ -38,7 +39,7 @@
#include "video_core/texture_cache/texture_cache_base.h"
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
#include "citron/util/title_ids.h"
namespace Vulkan {
@@ -66,13 +67,13 @@ struct DrawParams {
VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t index, float scale) {
const auto& src = regs.viewport_transform[index];
const auto conv = [scale](float value) {
float new_value = value * scale;
const double new_value = static_cast<double>(value) * static_cast<double>(scale);
if (scale < 1.0f) {
const bool sign = std::signbit(value);
new_value = std::round(std::abs(new_value));
new_value = sign ? -new_value : new_value;
double rounded = std::round(std::abs(new_value));
return static_cast<float>(sign ? -rounded : rounded);
}
return new_value;
return static_cast<float>(new_value);
};
const float x = conv(src.translate_x - src.scale_x);
const float width = conv(src.scale_x * 2.0f);
@@ -1107,7 +1108,8 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
};
}
scheduler.Record([this, viewport_list](vk::CommandBuffer cmdbuf) {
const u32 num_viewports = std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports);
const u32 num_viewports =
std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports);
const vk::Span<VkViewport> viewports(viewport_list.data(), num_viewports);
cmdbuf.SetViewport(0, viewports);
});