diff --git a/README.md b/README.md index 99f758c75..c2567698b 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 4025. +This is the source code for early-access 4026. ## Legal Notice diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 29a40bdfd..249b73ba2 100755 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -74,6 +74,11 @@ std::optional OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { case IR::Attribute::ClipDistance7: { const u32 base{static_cast(IR::Attribute::ClipDistance0)}; const u32 index{static_cast(attr) - base}; + if (index >= ctx.profile.max_user_clip_distances) { + LOG_WARNING(Shader, "Ignoring clip distance store {} >= {} supported", index, + ctx.profile.max_user_clip_distances); + return std::nullopt; + } const Id clip_num{ctx.Const(index)}; return OutputAccessChain(ctx, ctx.output_f32, ctx.clip_distances, clip_num); } diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 7a07c8862..104a4d329 100755 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -1533,7 +1533,8 @@ void EmitContext::DefineOutputs(const IR::Program& program) { if (stage == Stage::Fragment) { throw NotImplementedException("Storing ClipDistance in fragment stage"); } - const Id type{TypeArray(F32[1], Const(8U))}; + const Id type{TypeArray( + F32[1], Const(std::min(info.used_clip_distances, profile.max_user_clip_distances)))}; clip_distances = DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance); } if (info.stores[IR::Attribute::Layer] && diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index 582cf91e3..af7d89b2f 100755 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp @@ -913,7 +913,11 @@ void GatherInfoFromHeader(Environment& env, Info& info) { } for (size_t index = 0; index < 8; ++index) { const u16 mask{header.vtg.omap_systemc.clip_distances}; - info.stores.Set(IR::Attribute::ClipDistance0 + index, ((mask >> index) & 1) != 0); + const bool used{((mask >> index) & 1) != 0}; + info.stores.Set(IR::Attribute::ClipDistance0 + index, used); + if (used) { + info.used_clip_distances = static_cast(index) + 1; + } } info.stores.Set(IR::Attribute::PrimitiveId, header.vtg.omap_systemb.primitive_array_id != 0); diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index f4ae2341b..70ea46bb2 100755 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -87,6 +87,8 @@ struct Profile { bool has_broken_robust{}; u64 min_ssbo_alignment{}; + + u32 max_user_clip_distances{}; }; } // namespace Shader diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index 705933e3d..501fd84a6 100755 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h @@ -227,6 +227,8 @@ struct Info { bool requires_layer_emulation{}; IR::Attribute emulated_layer{}; + u32 used_clip_distances{}; + boost::container::static_vector constant_buffer_descriptors; boost::container::static_vector storage_buffers_descriptors; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index eb6f5d92d..b0aa5d02e 100755 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -233,6 +233,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo .ignore_nan_fp_comparisons = true, .gl_max_compute_smem_size = device.GetMaxComputeSharedMemorySize(), .min_ssbo_alignment = device.GetShaderStorageBufferAlignment(), + .max_user_clip_distances = 8, }, host_info{ .support_float64 = true, diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index ab6bc66ca..e903f4582 100755 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -563,22 +563,27 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bi } buffer_handles.push_back(handle); } + const u32 device_max = device.GetMaxVertexInputBindings(); + const u32 min_binding = std::min(bindings.min_index, device_max); + const u32 max_binding = std::min(bindings.max_index, device_max); + const u32 binding_count = max_binding - min_binding; + if (binding_count == 0) { + return; + } if (device.IsExtExtendedDynamicStateSupported()) { - scheduler.Record([this, bindings_ = std::move(bindings), - buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { - cmdbuf.BindVertexBuffers2EXT(bindings_.min_index, - std::min(bindings_.max_index - bindings_.min_index, - device.GetMaxVertexInputBindings()), - buffer_handles_.data(), bindings_.offsets.data(), - bindings_.sizes.data(), bindings_.strides.data()); + scheduler.Record([bindings_ = std::move(bindings), + buffer_handles_ = std::move(buffer_handles), + binding_count](vk::CommandBuffer cmdbuf) { + cmdbuf.BindVertexBuffers2EXT(bindings_.min_index, binding_count, buffer_handles_.data(), + bindings_.offsets.data(), bindings_.sizes.data(), + bindings_.strides.data()); }); } else { - scheduler.Record([this, bindings_ = std::move(bindings), - buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { - cmdbuf.BindVertexBuffers(bindings_.min_index, - std::min(bindings_.max_index - bindings_.min_index, - device.GetMaxVertexInputBindings()), - buffer_handles_.data(), bindings_.offsets.data()); + scheduler.Record([bindings_ = std::move(bindings), + buffer_handles_ = std::move(buffer_handles), + binding_count](vk::CommandBuffer cmdbuf) { + cmdbuf.BindVertexBuffers(bindings_.min_index, binding_count, buffer_handles_.data(), + bindings_.offsets.data()); }); } } diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 1adb6d90a..2f32b7d09 100755 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -374,6 +374,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device .has_broken_robust = device.IsNvidia() && device.GetNvidiaArch() <= NvidiaArchitecture::Arch_Pascal, .min_ssbo_alignment = device.GetStorageBufferAlignment(), + .max_user_clip_distances = device.GetMaxUserClipDistances(), }; host_info = Shader::HostTranslateInfo{ diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 9c41a773e..8c9265dd1 100755 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -695,6 +695,11 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR std::min(properties.properties.limits.maxVertexInputBindings, 16U); } + if (is_turnip) { + LOG_WARNING(Render_Vulkan, "Turnip requires higher-than-reported binding limits"); + properties.properties.limits.maxVertexInputBindings = 32; + } + if (!extensions.extended_dynamic_state && extensions.extended_dynamic_state2) { LOG_INFO(Render_Vulkan, "Removing extendedDynamicState2 due to missing extendedDynamicState"); diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 5e8c431dd..4b2fac8ed 100755 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -651,6 +651,10 @@ public: return properties.properties.limits.maxViewports; } + u32 GetMaxUserClipDistances() const { + return properties.properties.limits.maxClipDistances; + } + bool SupportsConditionalBarriers() const { return supports_conditional_barriers; } diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index 72ce4d8cf..c45bf248d 100755 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp @@ -193,8 +193,8 @@ void ConfigureUi::RequestGameListUpdate() { void ConfigureUi::SetConfiguration() { ui->theme_combobox->setCurrentIndex( ui->theme_combobox->findData(QString::fromStdString(UISettings::values.theme))); - ui->language_combobox->setCurrentIndex( - ui->language_combobox->findData(QString::fromStdString(UISettings::values.language))); + ui->language_combobox->setCurrentIndex(ui->language_combobox->findData( + QString::fromStdString(UISettings::values.language.GetValue()))); ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue()); ui->show_compat->setChecked(UISettings::values.show_compat.GetValue()); ui->show_size->setChecked(UISettings::values.show_size.GetValue()); diff --git a/src/yuzu/configuration/qt_config.cpp b/src/yuzu/configuration/qt_config.cpp index 636c5e640..417a43ec5 100755 --- a/src/yuzu/configuration/qt_config.cpp +++ b/src/yuzu/configuration/qt_config.cpp @@ -187,7 +187,6 @@ void QtConfig::ReadPathValues() { BeginGroup(Settings::TranslateCategory(Settings::Category::Paths)); UISettings::values.roms_path = ReadStringSetting(std::string("romsPath")); - UISettings::values.symbols_path = ReadStringSetting(std::string("symbolsPath")); UISettings::values.game_dir_deprecated = ReadStringSetting(std::string("gameListRootDir"), std::string(".")); UISettings::values.game_dir_deprecated_deepscan = @@ -225,8 +224,6 @@ void QtConfig::ReadPathValues() { UISettings::values.recent_files = QString::fromStdString(ReadStringSetting(std::string("recentFiles"))) .split(QStringLiteral(", "), Qt::SkipEmptyParts, Qt::CaseSensitive); - UISettings::values.language = - ReadStringSetting(std::string("language"), std::make_optional(std::string(""))); EndGroup(); } @@ -409,7 +406,6 @@ void QtConfig::SavePathValues() { BeginGroup(Settings::TranslateCategory(Settings::Category::Paths)); WriteSetting(std::string("romsPath"), UISettings::values.roms_path); - WriteSetting(std::string("symbolsPath"), UISettings::values.symbols_path); BeginArray(std::string("gamedirs")); for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) { SetArrayIndex(i); @@ -422,7 +418,6 @@ void QtConfig::SavePathValues() { WriteSetting(std::string("recentFiles"), UISettings::values.recent_files.join(QStringLiteral(", ")).toStdString()); - WriteSetting(std::string("language"), UISettings::values.language); EndGroup(); } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index cb3491885..0ff120f36 100755 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -5147,12 +5147,12 @@ void GMainWindow::UpdateUITheme() { void GMainWindow::LoadTranslation() { bool loaded; - if (UISettings::values.language.empty()) { + if (UISettings::values.language.GetValue().empty()) { // If the selected language is empty, use system locale loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/")); } else { // Otherwise load from the specified file - loaded = translator.load(QString::fromStdString(UISettings::values.language), + loaded = translator.load(QString::fromStdString(UISettings::values.language.GetValue()), QStringLiteral(":/languages/")); } @@ -5164,7 +5164,7 @@ void GMainWindow::LoadTranslation() { } void GMainWindow::OnLanguageChanged(const QString& locale) { - if (UISettings::values.language != std::string("en")) { + if (UISettings::values.language.GetValue() != std::string("en")) { qApp->removeTranslator(&translator); } diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 9cd0717cd..a4c62c5cb 100755 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h @@ -154,12 +154,11 @@ struct Values { Setting screenshot_height{linkage, 0, "screenshot_height", Category::Screenshots}; std::string roms_path; - std::string symbols_path; std::string game_dir_deprecated; bool game_dir_deprecated_deepscan; QVector game_dirs; QStringList recent_files; - std::string language; + Setting language{linkage, {}, "language", Category::Paths}; std::string theme;