mirror of
https://git.eden-emu.dev/archive/citron
synced 2026-03-22 17:46:08 -04:00
fix(vulkan): MP4 Mountain Jitter
This commit is contained in:
@@ -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{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user