diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt | 14 | ||||
-rw-r--r-- | src/core/hle/service/am/applets/applet_mii_edit.cpp | 50 | ||||
-rw-r--r-- | src/core/hle/service/am/applets/applet_mii_edit.h | 7 | ||||
-rw-r--r-- | src/core/hle/service/mii/mii.cpp | 114 | ||||
-rw-r--r-- | src/core/hle/service/mii/mii.h | 18 | ||||
-rw-r--r-- | src/core/hle/service/mii/mii_manager.cpp | 6 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/char_info.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/core_data.cpp | 3 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/raw_data.cpp | 12 | ||||
-rw-r--r-- | src/video_core/engines/maxwell_dma.cpp | 5 | ||||
-rw-r--r-- | src/video_core/engines/maxwell_dma.h | 55 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/maxwell_to_vk.cpp | 2 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 10 | ||||
-rw-r--r-- | src/video_core/vulkan_common/vulkan_device.cpp | 8 | ||||
-rw-r--r-- | src/video_core/vulkan_common/vulkan_device.h | 8 |
15 files changed, 208 insertions, 106 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt index 74941f934..6fa847631 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt @@ -50,6 +50,7 @@ import org.yuzu.yuzu_emu.model.TaskViewModel import org.yuzu.yuzu_emu.utils.* import java.io.BufferedInputStream import java.io.BufferedOutputStream +import java.io.FileInputStream import java.io.FileOutputStream import java.util.zip.ZipEntry import java.util.zip.ZipInputStream @@ -639,7 +640,15 @@ class MainActivity : AppCompatActivity(), ThemeProvider { file.path.length ) stream.putNextEntry(ZipEntry(newPath)) - stream.write(file.readBytes()) + + val buffer = ByteArray(8096) + var read: Int + FileInputStream(file).use { fis -> + while (fis.read(buffer).also { read = it } != -1) { + stream.write(buffer, 0, read) + } + } + stream.closeEntry() } } @@ -664,7 +673,8 @@ class MainActivity : AppCompatActivity(), ThemeProvider { checkStream.use { stream -> var ze: ZipEntry? = null while (stream.nextEntry?.also { ze = it } != null) { - if (ze!!.name.trim() == "/config/config.ini") { + val itemName = ze!!.name.trim() + if (itemName == "/config/config.ini" || itemName == "config/config.ini") { isYuzuBackup = true return@use } diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp index 350a90818..ff77830d2 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit.cpp +++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp @@ -7,7 +7,9 @@ #include "core/frontend/applets/mii_edit.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applet_mii_edit.h" +#include "core/hle/service/mii/mii.h" #include "core/hle/service/mii/mii_manager.h" +#include "core/hle/service/sm/sm.h" namespace Service::AM::Applets { @@ -56,6 +58,12 @@ void MiiEdit::Initialize() { sizeof(MiiEditAppletInputV4)); break; } + + manager = system.ServiceManager().GetService<Mii::MiiDBModule>("mii:e")->GetMiiManager(); + if (manager == nullptr) { + manager = std::make_shared<Mii::MiiManager>(); + } + manager->Initialize(metadata); } bool MiiEdit::TransactionComplete() const { @@ -78,22 +86,46 @@ void MiiEdit::Execute() { // This is a default stub for each of the MiiEdit applet modes. switch (applet_input_common.applet_mode) { case MiiEditAppletMode::ShowMiiEdit: - case MiiEditAppletMode::AppendMii: case MiiEditAppletMode::AppendMiiImage: case MiiEditAppletMode::UpdateMiiImage: MiiEditOutput(MiiEditResult::Success, 0); break; - case MiiEditAppletMode::CreateMii: - case MiiEditAppletMode::EditMii: { - Mii::CharInfo char_info{}; + case MiiEditAppletMode::AppendMii: { Mii::StoreData store_data{}; - store_data.BuildBase(Mii::Gender::Male); - char_info.SetFromStoreData(store_data); + store_data.BuildRandom(Mii::Age::All, Mii::Gender::All, Mii::Race::All); + store_data.SetNickname({u'y', u'u', u'z', u'u'}); + store_data.SetChecksum(); + const auto result = manager->AddOrReplace(metadata, store_data); + + if (result.IsError()) { + MiiEditOutput(MiiEditResult::Cancel, 0); + break; + } + + s32 index = manager->FindIndex(store_data.GetCreateId(), false); + + if (index == -1) { + MiiEditOutput(MiiEditResult::Cancel, 0); + break; + } + + MiiEditOutput(MiiEditResult::Success, index); + break; + } + case MiiEditAppletMode::CreateMii: { + Mii::CharInfo char_info{}; + manager->BuildRandom(char_info, Mii::Age::All, Mii::Gender::All, Mii::Race::All); + + const MiiEditCharInfo edit_char_info{ + .mii_info{char_info}, + }; + MiiEditOutputForCharInfoEditing(MiiEditResult::Success, edit_char_info); + break; + } + case MiiEditAppletMode::EditMii: { const MiiEditCharInfo edit_char_info{ - .mii_info{applet_input_common.applet_mode == MiiEditAppletMode::EditMii - ? applet_input_v4.char_info.mii_info - : char_info}, + .mii_info{applet_input_v4.char_info.mii_info}, }; MiiEditOutputForCharInfoEditing(MiiEditResult::Success, edit_char_info); diff --git a/src/core/hle/service/am/applets/applet_mii_edit.h b/src/core/hle/service/am/applets/applet_mii_edit.h index 3f46fae1b..7ff34af49 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit.h +++ b/src/core/hle/service/am/applets/applet_mii_edit.h @@ -11,6 +11,11 @@ namespace Core { class System; } // namespace Core +namespace Service::Mii { +struct DatabaseSessionMetadata; +class MiiManager; +} // namespace Service::Mii + namespace Service::AM::Applets { class MiiEdit final : public Applet { @@ -40,6 +45,8 @@ private: MiiEditAppletInputV4 applet_input_v4{}; bool is_complete{false}; + std::shared_ptr<Mii::MiiManager> manager = nullptr; + Mii::DatabaseSessionMetadata metadata{}; }; } // namespace Service::AM::Applets diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index 8de806cfb..c28eed926 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp @@ -18,8 +18,10 @@ namespace Service::Mii { class IDatabaseService final : public ServiceFramework<IDatabaseService> { public: - explicit IDatabaseService(Core::System& system_, bool is_system_) - : ServiceFramework{system_, "IDatabaseService"}, is_system{is_system_} { + explicit IDatabaseService(Core::System& system_, std::shared_ptr<MiiManager> mii_manager, + bool is_system_) + : ServiceFramework{system_, "IDatabaseService"}, manager{mii_manager}, is_system{ + is_system_} { // clang-format off static const FunctionInfo functions[] = { {0, &IDatabaseService::IsUpdated, "IsUpdated"}, @@ -54,7 +56,7 @@ public: RegisterHandlers(functions); - manager.Initialize(metadata); + manager->Initialize(metadata); } private: @@ -64,7 +66,7 @@ private: LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); - const bool is_updated = manager.IsUpdated(metadata, source_flag); + const bool is_updated = manager->IsUpdated(metadata, source_flag); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); @@ -74,7 +76,7 @@ private: void IsFullDatabase(HLERequestContext& ctx) { LOG_DEBUG(Service_Mii, "called"); - const bool is_full_database = manager.IsFullDatabase(); + const bool is_full_database = manager->IsFullDatabase(); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); @@ -85,7 +87,7 @@ private: IPC::RequestParser rp{ctx}; const auto source_flag{rp.PopRaw<SourceFlag>()}; - const u32 mii_count = manager.GetCount(metadata, source_flag); + const u32 mii_count = manager->GetCount(metadata, source_flag); LOG_DEBUG(Service_Mii, "called with source_flag={}, mii_count={}", source_flag, mii_count); @@ -101,7 +103,7 @@ private: u32 mii_count{}; std::vector<CharInfoElement> char_info_elements(output_size); - const auto result = manager.Get(metadata, char_info_elements, mii_count, source_flag); + const auto result = manager->Get(metadata, char_info_elements, mii_count, source_flag); if (mii_count != 0) { ctx.WriteBuffer(char_info_elements); @@ -122,7 +124,7 @@ private: u32 mii_count{}; std::vector<CharInfo> char_info(output_size); - const auto result = manager.Get(metadata, char_info, mii_count, source_flag); + const auto result = manager->Get(metadata, char_info, mii_count, source_flag); if (mii_count != 0) { ctx.WriteBuffer(char_info); @@ -144,7 +146,7 @@ private: LOG_INFO(Service_Mii, "called with source_flag={}", source_flag); CharInfo new_char_info{}; - const auto result = manager.UpdateLatest(metadata, new_char_info, char_info, source_flag); + const auto result = manager->UpdateLatest(metadata, new_char_info, char_info, source_flag); if (result.IsFailure()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); @@ -183,7 +185,7 @@ private: } CharInfo char_info{}; - manager.BuildRandom(char_info, age, gender, race); + manager->BuildRandom(char_info, age, gender, race); IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; rb.Push(ResultSuccess); @@ -203,7 +205,7 @@ private: } CharInfo char_info{}; - manager.BuildDefault(char_info, index); + manager->BuildDefault(char_info, index); IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; rb.Push(ResultSuccess); @@ -217,7 +219,7 @@ private: u32 mii_count{}; std::vector<StoreDataElement> store_data_elements(output_size); - const auto result = manager.Get(metadata, store_data_elements, mii_count, source_flag); + const auto result = manager->Get(metadata, store_data_elements, mii_count, source_flag); if (mii_count != 0) { ctx.WriteBuffer(store_data_elements); @@ -238,7 +240,7 @@ private: u32 mii_count{}; std::vector<StoreData> store_data(output_size); - const auto result = manager.Get(metadata, store_data, mii_count, source_flag); + const auto result = manager->Get(metadata, store_data, mii_count, source_flag); if (mii_count != 0) { ctx.WriteBuffer(store_data); @@ -266,7 +268,7 @@ private: StoreData new_store_data{}; if (result.IsSuccess()) { - result = manager.UpdateLatest(metadata, new_store_data, store_data, source_flag); + result = manager->UpdateLatest(metadata, new_store_data, store_data, source_flag); } if (result.IsFailure()) { @@ -288,7 +290,7 @@ private: LOG_INFO(Service_Mii, "called with create_id={}, is_special={}", create_id.FormattedString(), is_special); - const s32 index = manager.FindIndex(create_id, is_special); + const s32 index = manager->FindIndex(create_id, is_special); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); @@ -309,14 +311,14 @@ private: } if (result.IsSuccess()) { - const u32 count = manager.GetCount(metadata, SourceFlag::Database); + const u32 count = manager->GetCount(metadata, SourceFlag::Database); if (new_index < 0 || new_index >= static_cast<s32>(count)) { result = ResultInvalidArgument; } } if (result.IsSuccess()) { - result = manager.Move(metadata, new_index, create_id); + result = manager->Move(metadata, new_index, create_id); } IPC::ResponseBuilder rb{ctx, 2}; @@ -336,7 +338,7 @@ private: } if (result.IsSuccess()) { - result = manager.AddOrReplace(metadata, store_data); + result = manager->AddOrReplace(metadata, store_data); } IPC::ResponseBuilder rb{ctx, 2}; @@ -356,7 +358,7 @@ private: } if (result.IsSuccess()) { - result = manager.Delete(metadata, create_id); + result = manager->Delete(metadata, create_id); } IPC::ResponseBuilder rb{ctx, 2}; @@ -376,7 +378,7 @@ private: } if (result.IsSuccess()) { - result = manager.DestroyFile(metadata); + result = manager->DestroyFile(metadata); } IPC::ResponseBuilder rb{ctx, 2}; @@ -396,7 +398,7 @@ private: } if (result.IsSuccess()) { - result = manager.DeleteFile(); + result = manager->DeleteFile(); } IPC::ResponseBuilder rb{ctx, 2}; @@ -416,7 +418,7 @@ private: } if (result.IsSuccess()) { - result = manager.Format(metadata); + result = manager->Format(metadata); } IPC::ResponseBuilder rb{ctx, 2}; @@ -434,7 +436,7 @@ private: } if (result.IsSuccess()) { - is_broken_with_clear_flag = manager.IsBrokenWithClearFlag(metadata); + is_broken_with_clear_flag = manager->IsBrokenWithClearFlag(metadata); } IPC::ResponseBuilder rb{ctx, 3}; @@ -449,7 +451,7 @@ private: LOG_DEBUG(Service_Mii, "called"); s32 index{}; - const auto result = manager.GetIndex(metadata, info, index); + const auto result = manager->GetIndex(metadata, info, index); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(result); @@ -462,7 +464,7 @@ private: LOG_INFO(Service_Mii, "called, interface_version={:08X}", interface_version); - manager.SetInterfaceVersion(metadata, interface_version); + manager->SetInterfaceVersion(metadata, interface_version); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -475,7 +477,7 @@ private: LOG_INFO(Service_Mii, "called"); CharInfo char_info{}; - const auto result = manager.ConvertV3ToCharInfo(char_info, mii_v3); + const auto result = manager->ConvertV3ToCharInfo(char_info, mii_v3); IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; rb.Push(result); @@ -489,7 +491,7 @@ private: LOG_INFO(Service_Mii, "called"); CharInfo char_info{}; - const auto result = manager.ConvertCoreDataToCharInfo(char_info, core_data); + const auto result = manager->ConvertCoreDataToCharInfo(char_info, core_data); IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; rb.Push(result); @@ -503,7 +505,7 @@ private: LOG_INFO(Service_Mii, "called"); CoreData core_data{}; - const auto result = manager.ConvertCharInfoToCoreData(core_data, char_info); + const auto result = manager->ConvertCharInfoToCoreData(core_data, char_info); IPC::ResponseBuilder rb{ctx, 2 + sizeof(CoreData) / sizeof(u32)}; rb.Push(result); @@ -516,41 +518,46 @@ private: LOG_INFO(Service_Mii, "called"); - const auto result = manager.Append(metadata, char_info); + const auto result = manager->Append(metadata, char_info); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } - MiiManager manager{}; + std::shared_ptr<MiiManager> manager = nullptr; DatabaseSessionMetadata metadata{}; bool is_system{}; }; -class MiiDBModule final : public ServiceFramework<MiiDBModule> { -public: - explicit MiiDBModule(Core::System& system_, const char* name_, bool is_system_) - : ServiceFramework{system_, name_}, is_system{is_system_} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"}, - }; - // clang-format on +MiiDBModule::MiiDBModule(Core::System& system_, const char* name_, + std::shared_ptr<MiiManager> mii_manager, bool is_system_) + : ServiceFramework{system_, name_}, manager{mii_manager}, is_system{is_system_} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"}, + }; + // clang-format on - RegisterHandlers(functions); + RegisterHandlers(functions); + + if (manager == nullptr) { + manager = std::make_shared<MiiManager>(); } +} -private: - void GetDatabaseService(HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IDatabaseService>(system, is_system); +MiiDBModule::~MiiDBModule() = default; - LOG_DEBUG(Service_Mii, "called"); - } +void MiiDBModule::GetDatabaseService(HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface<IDatabaseService>(system, manager, is_system); - bool is_system{}; -}; + LOG_DEBUG(Service_Mii, "called"); +} + +std::shared_ptr<MiiManager> MiiDBModule::GetMiiManager() { + return manager; +} class MiiImg final : public ServiceFramework<MiiImg> { public: @@ -596,11 +603,12 @@ private: void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); + std::shared_ptr<MiiManager> manager = nullptr; - server_manager->RegisterNamedService("mii:e", - std::make_shared<MiiDBModule>(system, "mii:e", true)); - server_manager->RegisterNamedService("mii:u", - std::make_shared<MiiDBModule>(system, "mii:u", false)); + server_manager->RegisterNamedService( + "mii:e", std::make_shared<MiiDBModule>(system, "mii:e", manager, true)); + server_manager->RegisterNamedService( + "mii:u", std::make_shared<MiiDBModule>(system, "mii:u", manager, false)); server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system)); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/mii/mii.h b/src/core/hle/service/mii/mii.h index ed4e3f62b..9aa4426f6 100644 --- a/src/core/hle/service/mii/mii.h +++ b/src/core/hle/service/mii/mii.h @@ -3,11 +3,29 @@ #pragma once +#include "core/hle/service/service.h" + namespace Core { class System; } namespace Service::Mii { +class MiiManager; + +class MiiDBModule final : public ServiceFramework<MiiDBModule> { +public: + explicit MiiDBModule(Core::System& system_, const char* name_, + std::shared_ptr<MiiManager> mii_manager, bool is_system_); + ~MiiDBModule() override; + + std::shared_ptr<MiiManager> GetMiiManager(); + +private: + void GetDatabaseService(HLERequestContext& ctx); + + std::shared_ptr<MiiManager> manager = nullptr; + bool is_system{}; +}; void LoopProcess(Core::System& system); diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp index a5a2a9232..dcfd6b2e2 100644 --- a/src/core/hle/service/mii/mii_manager.cpp +++ b/src/core/hle/service/mii/mii_manager.cpp @@ -130,11 +130,11 @@ Result MiiManager::GetIndex(const DatabaseSessionMetadata& metadata, const CharI } s32 index{}; - Result result = {}; - // FindIndex(index); + const bool is_special = metadata.magic == MiiMagic; + const auto result = database_manager.FindIndex(index, char_info.GetCreateId(), is_special); if (result.IsError()) { - return ResultNotFound; + index = -1; } if (index == -1) { diff --git a/src/core/hle/service/mii/types/char_info.cpp b/src/core/hle/service/mii/types/char_info.cpp index e90124af4..c82186c73 100644 --- a/src/core/hle/service/mii/types/char_info.cpp +++ b/src/core/hle/service/mii/types/char_info.cpp @@ -37,7 +37,7 @@ void CharInfo::SetFromStoreData(const StoreData& store_data) { eyebrow_aspect = store_data.GetEyebrowAspect(); eyebrow_rotate = store_data.GetEyebrowRotate(); eyebrow_x = store_data.GetEyebrowX(); - eyebrow_y = store_data.GetEyebrowY() + 3; + eyebrow_y = store_data.GetEyebrowY(); nose_type = store_data.GetNoseType(); nose_scale = store_data.GetNoseScale(); nose_y = store_data.GetNoseY(); diff --git a/src/core/hle/service/mii/types/core_data.cpp b/src/core/hle/service/mii/types/core_data.cpp index 465c6293a..1068031e3 100644 --- a/src/core/hle/service/mii/types/core_data.cpp +++ b/src/core/hle/service/mii/types/core_data.cpp @@ -171,7 +171,7 @@ void CoreData::BuildRandom(Age age, Gender gender, Race race) { u8 glasses_type{}; while (glasses_type_start < glasses_type_info.values[glasses_type]) { if (++glasses_type >= glasses_type_info.values_count) { - ASSERT(false); + glasses_type = 0; break; } } @@ -179,6 +179,7 @@ void CoreData::BuildRandom(Age age, Gender gender, Race race) { SetGlassType(static_cast<GlassType>(glasses_type)); SetGlassColor(RawData::GetGlassColorFromVer3(0)); SetGlassScale(4); + SetGlassY(static_cast<u8>(axis_y + 10)); SetMoleType(MoleType::None); SetMoleScale(4); diff --git a/src/core/hle/service/mii/types/raw_data.cpp b/src/core/hle/service/mii/types/raw_data.cpp index 5143abcc8..0e1a07fd7 100644 --- a/src/core/hle/service/mii/types/raw_data.cpp +++ b/src/core/hle/service/mii/types/raw_data.cpp @@ -1716,18 +1716,18 @@ const std::array<RandomMiiData4, 18> RandomMiiMouthType{ const std::array<RandomMiiData2, 3> RandomMiiGlassType{ RandomMiiData2{ .arg_1 = 0, - .values_count = 9, - .values = {90, 94, 96, 100, 0, 0, 0, 0, 0}, + .values_count = 4, + .values = {90, 94, 96, 100}, }, RandomMiiData2{ .arg_1 = 1, - .values_count = 9, - .values = {83, 86, 90, 93, 94, 96, 98, 100, 0}, + .values_count = 8, + .values = {83, 86, 90, 93, 94, 96, 98, 100}, }, RandomMiiData2{ .arg_1 = 2, - .values_count = 9, - .values = {78, 83, 0, 93, 0, 0, 98, 100, 0}, + .values_count = 8, + .values = {78, 83, 0, 93, 0, 0, 98, 100}, }, }; diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index da8eab7ee..279f0daa1 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp @@ -109,10 +109,11 @@ void MaxwellDMA::Launch() { const bool is_const_a_dst = regs.remap_const.dst_x == RemapConst::Swizzle::CONST_A; if (regs.launch_dma.remap_enable != 0 && is_const_a_dst) { ASSERT(regs.remap_const.component_size_minus_one == 3); - accelerate.BufferClear(regs.offset_out, regs.line_length_in, regs.remap_consta_value); + accelerate.BufferClear(regs.offset_out, regs.line_length_in, + regs.remap_const.remap_consta_value); read_buffer.resize_destructive(regs.line_length_in * sizeof(u32)); std::span<u32> span(reinterpret_cast<u32*>(read_buffer.data()), regs.line_length_in); - std::ranges::fill(span, regs.remap_consta_value); + std::ranges::fill(span, regs.remap_const.remap_consta_value); memory_manager.WriteBlockUnsafe(regs.offset_out, reinterpret_cast<u8*>(read_buffer.data()), regs.line_length_in * sizeof(u32)); diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h index 69e26cb32..1a43e24b6 100644 --- a/src/video_core/engines/maxwell_dma.h +++ b/src/video_core/engines/maxwell_dma.h @@ -214,14 +214,15 @@ public: NO_WRITE = 6, }; - PackedGPUVAddr address; + u32 remap_consta_value; + u32 remap_constb_value; union { + BitField<0, 12, u32> dst_components_raw; BitField<0, 3, Swizzle> dst_x; BitField<4, 3, Swizzle> dst_y; BitField<8, 3, Swizzle> dst_z; BitField<12, 3, Swizzle> dst_w; - BitField<0, 12, u32> dst_components_raw; BitField<16, 2, u32> component_size_minus_one; BitField<20, 2, u32> num_src_components_minus_one; BitField<24, 2, u32> num_dst_components_minus_one; @@ -274,55 +275,57 @@ private: struct Regs { union { struct { - u32 reserved[0x40]; + INSERT_PADDING_BYTES_NOINIT(0x100); u32 nop; - u32 reserved01[0xf]; + INSERT_PADDING_BYTES_NOINIT(0x3C); u32 pm_trigger; - u32 reserved02[0x3f]; + INSERT_PADDING_BYTES_NOINIT(0xFC); Semaphore semaphore; - u32 reserved03[0x2]; + INSERT_PADDING_BYTES_NOINIT(0x8); RenderEnable render_enable; PhysMode src_phys_mode; PhysMode dst_phys_mode; - u32 reserved04[0x26]; + INSERT_PADDING_BYTES_NOINIT(0x98); LaunchDMA launch_dma; - u32 reserved05[0x3f]; + INSERT_PADDING_BYTES_NOINIT(0xFC); PackedGPUVAddr offset_in; PackedGPUVAddr offset_out; s32 pitch_in; s32 pitch_out; u32 line_length_in; u32 line_count; - u32 reserved06[0xb6]; - u32 remap_consta_value; - u32 remap_constb_value; + INSERT_PADDING_BYTES_NOINIT(0x2E0); RemapConst remap_const; DMA::Parameters dst_params; - u32 reserved07[0x1]; + INSERT_PADDING_BYTES_NOINIT(0x4); DMA::Parameters src_params; - u32 reserved08[0x275]; + INSERT_PADDING_BYTES_NOINIT(0x9D4); u32 pm_trigger_end; - u32 reserved09[0x3ba]; + INSERT_PADDING_BYTES_NOINIT(0xEE8); }; std::array<u32, NUM_REGS> reg_array; }; } regs{}; + static_assert(sizeof(Regs) == NUM_REGS * 4); #define ASSERT_REG_POSITION(field_name, position) \ - static_assert(offsetof(MaxwellDMA::Regs, field_name) == position * 4, \ + static_assert(offsetof(MaxwellDMA::Regs, field_name) == position, \ "Field " #field_name " has invalid position") - ASSERT_REG_POSITION(launch_dma, 0xC0); - ASSERT_REG_POSITION(offset_in, 0x100); - ASSERT_REG_POSITION(offset_out, 0x102); - ASSERT_REG_POSITION(pitch_in, 0x104); - ASSERT_REG_POSITION(pitch_out, 0x105); - ASSERT_REG_POSITION(line_length_in, 0x106); - ASSERT_REG_POSITION(line_count, 0x107); - ASSERT_REG_POSITION(remap_const, 0x1C0); - ASSERT_REG_POSITION(dst_params, 0x1C3); - ASSERT_REG_POSITION(src_params, 0x1CA); - + ASSERT_REG_POSITION(semaphore, 0x240); + ASSERT_REG_POSITION(render_enable, 0x254); + ASSERT_REG_POSITION(src_phys_mode, 0x260); + ASSERT_REG_POSITION(launch_dma, 0x300); + ASSERT_REG_POSITION(offset_in, 0x400); + ASSERT_REG_POSITION(offset_out, 0x408); + ASSERT_REG_POSITION(pitch_in, 0x410); + ASSERT_REG_POSITION(pitch_out, 0x414); + ASSERT_REG_POSITION(line_length_in, 0x418); + ASSERT_REG_POSITION(line_count, 0x41C); + ASSERT_REG_POSITION(remap_const, 0x700); + ASSERT_REG_POSITION(dst_params, 0x70C); + ASSERT_REG_POSITION(src_params, 0x728); + ASSERT_REG_POSITION(pm_trigger_end, 0x1114); #undef ASSERT_REG_POSITION }; diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 35bf80ea3..208e88533 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp @@ -185,7 +185,7 @@ struct FormatTuple { {VK_FORMAT_BC2_SRGB_BLOCK}, // BC2_SRGB {VK_FORMAT_BC3_SRGB_BLOCK}, // BC3_SRGB {VK_FORMAT_BC7_SRGB_BLOCK}, // BC7_SRGB - {VK_FORMAT_R4G4B4A4_UNORM_PACK16}, // A4B4G4R4_UNORM + {VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT}, // A4B4G4R4_UNORM {VK_FORMAT_R4G4_UNORM_PACK8}, // G4R4_UNORM {VK_FORMAT_ASTC_4x4_SRGB_BLOCK}, // ASTC_2D_4X4_SRGB {VK_FORMAT_ASTC_8x8_SRGB_BLOCK}, // ASTC_2D_8X8_SRGB diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index b3e17c332..285a50ea4 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -600,7 +600,7 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im } void TryTransformSwizzleIfNeeded(PixelFormat format, std::array<SwizzleSource, 4>& swizzle, - bool emulate_bgr565) { + bool emulate_bgr565, bool emulate_a4b4g4r4) { switch (format) { case PixelFormat::A1B5G5R5_UNORM: std::ranges::transform(swizzle, swizzle.begin(), SwapBlueRed); @@ -616,6 +616,11 @@ void TryTransformSwizzleIfNeeded(PixelFormat format, std::array<SwizzleSource, 4 case PixelFormat::G4R4_UNORM: std::ranges::transform(swizzle, swizzle.begin(), SwapGreenRed); break; + case PixelFormat::A4B4G4R4_UNORM: + if (emulate_a4b4g4r4) { + std::ranges::reverse(swizzle); + } + break; default: break; } @@ -1649,7 +1654,8 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI }; if (!info.IsRenderTarget()) { swizzle = info.Swizzle(); - TryTransformSwizzleIfNeeded(format, swizzle, device->MustEmulateBGR565()); + TryTransformSwizzleIfNeeded(format, swizzle, device->MustEmulateBGR565(), + !device->IsExt4444FormatsSupported()); if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0) { std::ranges::transform(swizzle, swizzle.begin(), ConvertGreenRed); } diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 617417040..a88ff5ca5 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -76,6 +76,11 @@ constexpr std::array VK_FORMAT_R32G32B32_SFLOAT{ VK_FORMAT_UNDEFINED, }; +constexpr std::array VK_FORMAT_A4B4G4R4_UNORM_PACK16{ + VK_FORMAT_R4G4B4A4_UNORM_PACK16, + VK_FORMAT_UNDEFINED, +}; + } // namespace Alternatives enum class NvidiaArchitecture { @@ -110,6 +115,8 @@ constexpr const VkFormat* GetFormatAlternatives(VkFormat format) { return Alternatives::R8G8B8_SSCALED.data(); case VK_FORMAT_R32G32B32_SFLOAT: return Alternatives::VK_FORMAT_R32G32B32_SFLOAT.data(); + case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT: + return Alternatives::VK_FORMAT_A4B4G4R4_UNORM_PACK16.data(); default: return nullptr; } @@ -238,6 +245,7 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(vk::Physica VK_FORMAT_R32_SINT, VK_FORMAT_R32_UINT, VK_FORMAT_R4G4B4A4_UNORM_PACK16, + VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, VK_FORMAT_R4G4_UNORM_PACK8, VK_FORMAT_R5G5B5A1_UNORM_PACK16, VK_FORMAT_R5G6B5_UNORM_PACK16, diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 488fdd313..6c7fa34e5 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -45,6 +45,7 @@ VK_DEFINE_HANDLE(VmaAllocator) FEATURE(EXT, ExtendedDynamicState, EXTENDED_DYNAMIC_STATE, extended_dynamic_state) \ FEATURE(EXT, ExtendedDynamicState2, EXTENDED_DYNAMIC_STATE_2, extended_dynamic_state2) \ FEATURE(EXT, ExtendedDynamicState3, EXTENDED_DYNAMIC_STATE_3, extended_dynamic_state3) \ + FEATURE(EXT, 4444Formats, 4444_FORMATS, format_a4b4g4r4) \ FEATURE(EXT, IndexTypeUint8, INDEX_TYPE_UINT8, index_type_uint8) \ FEATURE(EXT, LineRasterization, LINE_RASTERIZATION, line_rasterization) \ FEATURE(EXT, PrimitiveTopologyListRestart, PRIMITIVE_TOPOLOGY_LIST_RESTART, \ @@ -97,6 +98,7 @@ VK_DEFINE_HANDLE(VmaAllocator) EXTENSION_NAME(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) \ EXTENSION_NAME(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME) \ EXTENSION_NAME(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME) \ + EXTENSION_NAME(VK_EXT_4444_FORMATS_EXTENSION_NAME) \ EXTENSION_NAME(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME) \ EXTENSION_NAME(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME) \ EXTENSION_NAME(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME) \ @@ -144,6 +146,7 @@ VK_DEFINE_HANDLE(VmaAllocator) #define FOR_EACH_VK_RECOMMENDED_FEATURE(FEATURE_NAME) \ FEATURE_NAME(custom_border_color, customBorderColors) \ FEATURE_NAME(extended_dynamic_state, extendedDynamicState) \ + FEATURE_NAME(format_a4b4g4r4, formatA4B4G4R4) \ FEATURE_NAME(index_type_uint8, indexTypeUint8) \ FEATURE_NAME(primitive_topology_list_restart, primitiveTopologyListRestart) \ FEATURE_NAME(provoking_vertex, provokingVertexLast) \ @@ -488,6 +491,11 @@ public: return extensions.extended_dynamic_state3; } + /// Returns true if the device supports VK_EXT_4444_formats. + bool IsExt4444FormatsSupported() const { + return features.format_a4b4g4r4.formatA4B4G4R4; + } + /// Returns true if the device supports VK_EXT_extended_dynamic_state3. bool IsExtExtendedDynamicState3BlendingSupported() const { return dynamic_state3_blending; |