diff options
Diffstat (limited to 'src')
23 files changed, 350 insertions, 58 deletions
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 9fa082dd5..9cf71680c 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp | |||
| @@ -141,10 +141,6 @@ public: | |||
| 141 | if (nsp->IsExtractedType()) { | 141 | if (nsp->IsExtractedType()) { |
| 142 | return InstallError; | 142 | return InstallError; |
| 143 | } | 143 | } |
| 144 | } else if (file_extension == "xci") { | ||
| 145 | jconst xci = | ||
| 146 | std::make_shared<FileSys::XCI>(m_vfs->OpenFile(filename, FileSys::Mode::Read)); | ||
| 147 | nsp = xci->GetSecurePartitionNSP(); | ||
| 148 | } else { | 144 | } else { |
| 149 | return ErrorFilenameExtension; | 145 | return ErrorFilenameExtension; |
| 150 | } | 146 | } |
diff --git a/src/common/settings.h b/src/common/settings.h index ae5e5d2b8..98ab0ec2e 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -351,6 +351,8 @@ struct Values { | |||
| 351 | linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug}; | 351 | linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug}; |
| 352 | Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey", | 352 | Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey", |
| 353 | Category::RendererDebug}; | 353 | Category::RendererDebug}; |
| 354 | // TODO: remove this once AMDVLK supports VK_EXT_depth_bias_control | ||
| 355 | bool renderer_amdvlk_depth_bias_workaround{}; | ||
| 354 | 356 | ||
| 355 | // System | 357 | // System |
| 356 | SwitchableSetting<Language, true> language_index{linkage, | 358 | SwitchableSetting<Language, true> language_index{linkage, |
diff --git a/src/core/core.cpp b/src/core/core.cpp index e8300cd05..08cbb8978 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -381,6 +381,10 @@ struct System::Impl { | |||
| 381 | room_member->SendGameInfo(game_info); | 381 | room_member->SendGameInfo(game_info); |
| 382 | } | 382 | } |
| 383 | 383 | ||
| 384 | // Workarounds: | ||
| 385 | // Activate this in Super Smash Brothers Ultimate, it only affects AMD cards using AMDVLK | ||
| 386 | Settings::values.renderer_amdvlk_depth_bias_workaround = program_id == 0x1006A800016E000ULL; | ||
| 387 | |||
| 384 | status = SystemResultStatus::Success; | 388 | status = SystemResultStatus::Success; |
| 385 | return status; | 389 | return status; |
| 386 | } | 390 | } |
| @@ -440,6 +444,9 @@ struct System::Impl { | |||
| 440 | room_member->SendGameInfo(game_info); | 444 | room_member->SendGameInfo(game_info); |
| 441 | } | 445 | } |
| 442 | 446 | ||
| 447 | // Workarounds | ||
| 448 | Settings::values.renderer_amdvlk_depth_bias_workaround = false; | ||
| 449 | |||
| 443 | LOG_DEBUG(Core, "Shutdown OK"); | 450 | LOG_DEBUG(Core, "Shutdown OK"); |
| 444 | } | 451 | } |
| 445 | 452 | ||
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index e9bd04842..a83622f7c 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -2094,9 +2094,6 @@ void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) { | |||
| 2094 | 2094 | ||
| 2095 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { | 2095 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { |
| 2096 | auto message_queue = std::make_shared<AppletMessageQueue>(system); | 2096 | auto message_queue = std::make_shared<AppletMessageQueue>(system); |
| 2097 | // Needed on game boot | ||
| 2098 | message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); | ||
| 2099 | |||
| 2100 | auto server_manager = std::make_unique<ServerManager>(system); | 2097 | auto server_manager = std::make_unique<ServerManager>(system); |
| 2101 | 2098 | ||
| 2102 | server_manager->RegisterNamedService( | 2099 | server_manager->RegisterNamedService( |
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 ff77830d2..50adc7c02 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit.cpp +++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp | |||
| @@ -145,6 +145,8 @@ void MiiEdit::MiiEditOutput(MiiEditResult result, s32 index) { | |||
| 145 | .index{index}, | 145 | .index{index}, |
| 146 | }; | 146 | }; |
| 147 | 147 | ||
| 148 | LOG_INFO(Input, "called, result={}, index={}", result, index); | ||
| 149 | |||
| 148 | std::vector<u8> out_data(sizeof(MiiEditAppletOutput)); | 150 | std::vector<u8> out_data(sizeof(MiiEditAppletOutput)); |
| 149 | std::memcpy(out_data.data(), &applet_output, sizeof(MiiEditAppletOutput)); | 151 | std::memcpy(out_data.data(), &applet_output, sizeof(MiiEditAppletOutput)); |
| 150 | 152 | ||
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 2492bbc16..c2054e8a0 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -329,6 +329,7 @@ public: | |||
| 329 | {13, &IFileSystem::CleanDirectoryRecursively, "CleanDirectoryRecursively"}, | 329 | {13, &IFileSystem::CleanDirectoryRecursively, "CleanDirectoryRecursively"}, |
| 330 | {14, &IFileSystem::GetFileTimeStampRaw, "GetFileTimeStampRaw"}, | 330 | {14, &IFileSystem::GetFileTimeStampRaw, "GetFileTimeStampRaw"}, |
| 331 | {15, nullptr, "QueryEntry"}, | 331 | {15, nullptr, "QueryEntry"}, |
| 332 | {16, &IFileSystem::GetFileSystemAttribute, "GetFileSystemAttribute"}, | ||
| 332 | }; | 333 | }; |
| 333 | RegisterHandlers(functions); | 334 | RegisterHandlers(functions); |
| 334 | } | 335 | } |
| @@ -521,6 +522,46 @@ public: | |||
| 521 | rb.PushRaw(vfs_timestamp); | 522 | rb.PushRaw(vfs_timestamp); |
| 522 | } | 523 | } |
| 523 | 524 | ||
| 525 | void GetFileSystemAttribute(HLERequestContext& ctx) { | ||
| 526 | LOG_WARNING(Service_FS, "(STUBBED) called"); | ||
| 527 | |||
| 528 | struct FileSystemAttribute { | ||
| 529 | u8 dir_entry_name_length_max_defined; | ||
| 530 | u8 file_entry_name_length_max_defined; | ||
| 531 | u8 dir_path_name_length_max_defined; | ||
| 532 | u8 file_path_name_length_max_defined; | ||
| 533 | INSERT_PADDING_BYTES_NOINIT(0x5); | ||
| 534 | u8 utf16_dir_entry_name_length_max_defined; | ||
| 535 | u8 utf16_file_entry_name_length_max_defined; | ||
| 536 | u8 utf16_dir_path_name_length_max_defined; | ||
| 537 | u8 utf16_file_path_name_length_max_defined; | ||
| 538 | INSERT_PADDING_BYTES_NOINIT(0x18); | ||
| 539 | s32 dir_entry_name_length_max; | ||
| 540 | s32 file_entry_name_length_max; | ||
| 541 | s32 dir_path_name_length_max; | ||
| 542 | s32 file_path_name_length_max; | ||
| 543 | INSERT_PADDING_WORDS_NOINIT(0x5); | ||
| 544 | s32 utf16_dir_entry_name_length_max; | ||
| 545 | s32 utf16_file_entry_name_length_max; | ||
| 546 | s32 utf16_dir_path_name_length_max; | ||
| 547 | s32 utf16_file_path_name_length_max; | ||
| 548 | INSERT_PADDING_WORDS_NOINIT(0x18); | ||
| 549 | INSERT_PADDING_WORDS_NOINIT(0x1); | ||
| 550 | }; | ||
| 551 | static_assert(sizeof(FileSystemAttribute) == 0xc0, | ||
| 552 | "FileSystemAttribute has incorrect size"); | ||
| 553 | |||
| 554 | FileSystemAttribute savedata_attribute{}; | ||
| 555 | savedata_attribute.dir_entry_name_length_max_defined = true; | ||
| 556 | savedata_attribute.file_entry_name_length_max_defined = true; | ||
| 557 | savedata_attribute.dir_entry_name_length_max = 0x40; | ||
| 558 | savedata_attribute.file_entry_name_length_max = 0x40; | ||
| 559 | |||
| 560 | IPC::ResponseBuilder rb{ctx, 50}; | ||
| 561 | rb.Push(ResultSuccess); | ||
| 562 | rb.PushRaw(savedata_attribute); | ||
| 563 | } | ||
| 564 | |||
| 524 | private: | 565 | private: |
| 525 | VfsDirectoryServiceWrapper backend; | 566 | VfsDirectoryServiceWrapper backend; |
| 526 | SizeGetter size; | 567 | SizeGetter size; |
diff --git a/src/core/hle/service/mii/mii_database_manager.cpp b/src/core/hle/service/mii/mii_database_manager.cpp index c39898594..0080b6705 100644 --- a/src/core/hle/service/mii/mii_database_manager.cpp +++ b/src/core/hle/service/mii/mii_database_manager.cpp | |||
| @@ -168,7 +168,7 @@ Result DatabaseManager::FindIndex(s32& out_index, const Common::UUID& create_id, | |||
| 168 | return ResultSuccess; | 168 | return ResultSuccess; |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | for (std::size_t i = 0; i <= index; ++i) { | 171 | for (std::size_t i = 0; i < index; ++i) { |
| 172 | if (database.Get(i).IsSpecial()) { | 172 | if (database.Get(i).IsSpecial()) { |
| 173 | continue; | 173 | continue; |
| 174 | } | 174 | } |
diff --git a/src/core/hle/service/mii/types/char_info.cpp b/src/core/hle/service/mii/types/char_info.cpp index c82186c73..e90124af4 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) { | |||
| 37 | eyebrow_aspect = store_data.GetEyebrowAspect(); | 37 | eyebrow_aspect = store_data.GetEyebrowAspect(); |
| 38 | eyebrow_rotate = store_data.GetEyebrowRotate(); | 38 | eyebrow_rotate = store_data.GetEyebrowRotate(); |
| 39 | eyebrow_x = store_data.GetEyebrowX(); | 39 | eyebrow_x = store_data.GetEyebrowX(); |
| 40 | eyebrow_y = store_data.GetEyebrowY(); | 40 | eyebrow_y = store_data.GetEyebrowY() + 3; |
| 41 | nose_type = store_data.GetNoseType(); | 41 | nose_type = store_data.GetNoseType(); |
| 42 | nose_scale = store_data.GetNoseScale(); | 42 | nose_scale = store_data.GetNoseScale(); |
| 43 | nose_y = store_data.GetNoseY(); | 43 | 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 1068031e3..970c748ca 100644 --- a/src/core/hle/service/mii/types/core_data.cpp +++ b/src/core/hle/service/mii/types/core_data.cpp | |||
| @@ -113,7 +113,7 @@ void CoreData::BuildRandom(Age age, Gender gender, Race race) { | |||
| 113 | .values[MiiUtil::GetRandomValue<std::size_t>(eyebrow_type_info.values_count)]); | 113 | .values[MiiUtil::GetRandomValue<std::size_t>(eyebrow_type_info.values_count)]); |
| 114 | 114 | ||
| 115 | const auto eyebrow_rotate_1{race == Race::Asian ? 6 : 0}; | 115 | const auto eyebrow_rotate_1{race == Race::Asian ? 6 : 0}; |
| 116 | const auto eyebrow_y{race == Race::Asian ? 9 : 10}; | 116 | const auto eyebrow_y{race == Race::Asian ? 6 : 7}; |
| 117 | const auto eyebrow_rotate_offset{32 - RawData::EyebrowRotateLookup[eyebrow_rotate_1] + 6}; | 117 | const auto eyebrow_rotate_offset{32 - RawData::EyebrowRotateLookup[eyebrow_rotate_1] + 6}; |
| 118 | const auto eyebrow_rotate{ | 118 | const auto eyebrow_rotate{ |
| 119 | 32 - RawData::EyebrowRotateLookup[static_cast<std::size_t>(data.eyebrow_type.Value())]}; | 119 | 32 - RawData::EyebrowRotateLookup[static_cast<std::size_t>(data.eyebrow_type.Value())]}; |
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index 05951d8cb..68c407f81 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp | |||
| @@ -1374,7 +1374,7 @@ NFP::AmiiboName NfcDevice::GetAmiiboName(const NFP::AmiiboSettings& settings) co | |||
| 1374 | 1374 | ||
| 1375 | // Convert from utf16 to utf8 | 1375 | // Convert from utf16 to utf8 |
| 1376 | const auto amiibo_name_utf8 = Common::UTF16ToUTF8(settings_amiibo_name.data()); | 1376 | const auto amiibo_name_utf8 = Common::UTF16ToUTF8(settings_amiibo_name.data()); |
| 1377 | memcpy(amiibo_name.data(), amiibo_name_utf8.data(), amiibo_name_utf8.size() - 1); | 1377 | memcpy(amiibo_name.data(), amiibo_name_utf8.data(), amiibo_name_utf8.size()); |
| 1378 | 1378 | ||
| 1379 | return amiibo_name; | 1379 | return amiibo_name; |
| 1380 | } | 1380 | } |
diff --git a/src/video_core/host_shaders/convert_msaa_to_non_msaa.comp b/src/video_core/host_shaders/convert_msaa_to_non_msaa.comp index fc3854d18..66f2ad483 100644 --- a/src/video_core/host_shaders/convert_msaa_to_non_msaa.comp +++ b/src/video_core/host_shaders/convert_msaa_to_non_msaa.comp | |||
| @@ -15,11 +15,14 @@ void main() { | |||
| 15 | 15 | ||
| 16 | // TODO: Specialization constants for num_samples? | 16 | // TODO: Specialization constants for num_samples? |
| 17 | const int num_samples = imageSamples(msaa_in); | 17 | const int num_samples = imageSamples(msaa_in); |
| 18 | const ivec3 msaa_size = imageSize(msaa_in); | ||
| 19 | const ivec3 out_size = imageSize(output_img); | ||
| 20 | const ivec3 scale = out_size / msaa_size; | ||
| 18 | for (int curr_sample = 0; curr_sample < num_samples; ++curr_sample) { | 21 | for (int curr_sample = 0; curr_sample < num_samples; ++curr_sample) { |
| 19 | const vec4 pixel = imageLoad(msaa_in, coords, curr_sample); | 22 | const vec4 pixel = imageLoad(msaa_in, coords, curr_sample); |
| 20 | 23 | ||
| 21 | const int single_sample_x = 2 * coords.x + (curr_sample & 1); | 24 | const int single_sample_x = scale.x * coords.x + (curr_sample & 1); |
| 22 | const int single_sample_y = 2 * coords.y + ((curr_sample / 2) & 1); | 25 | const int single_sample_y = scale.y * coords.y + ((curr_sample / 2) & 1); |
| 23 | const ivec3 dest_coords = ivec3(single_sample_x, single_sample_y, coords.z); | 26 | const ivec3 dest_coords = ivec3(single_sample_x, single_sample_y, coords.z); |
| 24 | 27 | ||
| 25 | if (any(greaterThanEqual(dest_coords, imageSize(output_img)))) { | 28 | if (any(greaterThanEqual(dest_coords, imageSize(output_img)))) { |
diff --git a/src/video_core/host_shaders/convert_non_msaa_to_msaa.comp b/src/video_core/host_shaders/convert_non_msaa_to_msaa.comp index dedd962f1..c7ce38efa 100644 --- a/src/video_core/host_shaders/convert_non_msaa_to_msaa.comp +++ b/src/video_core/host_shaders/convert_non_msaa_to_msaa.comp | |||
| @@ -15,9 +15,12 @@ void main() { | |||
| 15 | 15 | ||
| 16 | // TODO: Specialization constants for num_samples? | 16 | // TODO: Specialization constants for num_samples? |
| 17 | const int num_samples = imageSamples(output_msaa); | 17 | const int num_samples = imageSamples(output_msaa); |
| 18 | const ivec3 msaa_size = imageSize(output_msaa); | ||
| 19 | const ivec3 out_size = imageSize(img_in); | ||
| 20 | const ivec3 scale = out_size / msaa_size; | ||
| 18 | for (int curr_sample = 0; curr_sample < num_samples; ++curr_sample) { | 21 | for (int curr_sample = 0; curr_sample < num_samples; ++curr_sample) { |
| 19 | const int single_sample_x = 2 * coords.x + (curr_sample & 1); | 22 | const int single_sample_x = scale.x * coords.x + (curr_sample & 1); |
| 20 | const int single_sample_y = 2 * coords.y + ((curr_sample / 2) & 1); | 23 | const int single_sample_y = scale.y * coords.y + ((curr_sample / 2) & 1); |
| 21 | const ivec3 single_coords = ivec3(single_sample_x, single_sample_y, coords.z); | 24 | const ivec3 single_coords = ivec3(single_sample_x, single_sample_y, coords.z); |
| 22 | 25 | ||
| 23 | if (any(greaterThanEqual(single_coords, imageSize(img_in)))) { | 26 | if (any(greaterThanEqual(single_coords, imageSize(img_in)))) { |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index 289d5b25c..617f92910 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <array> | 4 | #include <array> |
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | #include <numeric> | ||
| 6 | #include <optional> | 7 | #include <optional> |
| 7 | #include <utility> | 8 | #include <utility> |
| 8 | 9 | ||
| @@ -11,7 +12,10 @@ | |||
| 11 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 12 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 13 | #include "common/div_ceil.h" | 14 | #include "common/div_ceil.h" |
| 15 | #include "common/vector_math.h" | ||
| 14 | #include "video_core/host_shaders/astc_decoder_comp_spv.h" | 16 | #include "video_core/host_shaders/astc_decoder_comp_spv.h" |
| 17 | #include "video_core/host_shaders/convert_msaa_to_non_msaa_comp_spv.h" | ||
| 18 | #include "video_core/host_shaders/convert_non_msaa_to_msaa_comp_spv.h" | ||
| 15 | #include "video_core/host_shaders/queries_prefix_scan_sum_comp_spv.h" | 19 | #include "video_core/host_shaders/queries_prefix_scan_sum_comp_spv.h" |
| 16 | #include "video_core/host_shaders/queries_prefix_scan_sum_nosubgroups_comp_spv.h" | 20 | #include "video_core/host_shaders/queries_prefix_scan_sum_nosubgroups_comp_spv.h" |
| 17 | #include "video_core/host_shaders/resolve_conditional_render_comp_spv.h" | 21 | #include "video_core/host_shaders/resolve_conditional_render_comp_spv.h" |
| @@ -131,6 +135,33 @@ constexpr DescriptorBankInfo ASTC_BANK_INFO{ | |||
| 131 | .score = 2, | 135 | .score = 2, |
| 132 | }; | 136 | }; |
| 133 | 137 | ||
| 138 | constexpr std::array<VkDescriptorSetLayoutBinding, ASTC_NUM_BINDINGS> MSAA_DESCRIPTOR_SET_BINDINGS{{ | ||
| 139 | { | ||
| 140 | .binding = 0, | ||
| 141 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | ||
| 142 | .descriptorCount = 1, | ||
| 143 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 144 | .pImmutableSamplers = nullptr, | ||
| 145 | }, | ||
| 146 | { | ||
| 147 | .binding = 1, | ||
| 148 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | ||
| 149 | .descriptorCount = 1, | ||
| 150 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 151 | .pImmutableSamplers = nullptr, | ||
| 152 | }, | ||
| 153 | }}; | ||
| 154 | |||
| 155 | constexpr DescriptorBankInfo MSAA_BANK_INFO{ | ||
| 156 | .uniform_buffers = 0, | ||
| 157 | .storage_buffers = 0, | ||
| 158 | .texture_buffers = 0, | ||
| 159 | .image_buffers = 0, | ||
| 160 | .textures = 0, | ||
| 161 | .images = 2, | ||
| 162 | .score = 2, | ||
| 163 | }; | ||
| 164 | |||
| 134 | constexpr VkDescriptorUpdateTemplateEntry INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE{ | 165 | constexpr VkDescriptorUpdateTemplateEntry INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE{ |
| 135 | .dstBinding = 0, | 166 | .dstBinding = 0, |
| 136 | .dstArrayElement = 0, | 167 | .dstArrayElement = 0, |
| @@ -149,6 +180,15 @@ constexpr VkDescriptorUpdateTemplateEntry QUERIES_SCAN_DESCRIPTOR_UPDATE_TEMPLAT | |||
| 149 | .stride = sizeof(DescriptorUpdateEntry), | 180 | .stride = sizeof(DescriptorUpdateEntry), |
| 150 | }; | 181 | }; |
| 151 | 182 | ||
| 183 | constexpr VkDescriptorUpdateTemplateEntry MSAA_DESCRIPTOR_UPDATE_TEMPLATE{ | ||
| 184 | .dstBinding = 0, | ||
| 185 | .dstArrayElement = 0, | ||
| 186 | .descriptorCount = 2, | ||
| 187 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | ||
| 188 | .offset = 0, | ||
| 189 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 190 | }; | ||
| 191 | |||
| 152 | constexpr std::array<VkDescriptorUpdateTemplateEntry, ASTC_NUM_BINDINGS> | 192 | constexpr std::array<VkDescriptorUpdateTemplateEntry, ASTC_NUM_BINDINGS> |
| 153 | ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY{{ | 193 | ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY{{ |
| 154 | { | 194 | { |
| @@ -224,6 +264,9 @@ ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool, | |||
| 224 | }); | 264 | }); |
| 225 | descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, bank_info); | 265 | descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, bank_info); |
| 226 | } | 266 | } |
| 267 | if (code.empty()) { | ||
| 268 | return; | ||
| 269 | } | ||
| 227 | module = device.GetLogical().CreateShaderModule({ | 270 | module = device.GetLogical().CreateShaderModule({ |
| 228 | .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, | 271 | .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, |
| 229 | .pNext = nullptr, | 272 | .pNext = nullptr, |
| @@ -590,4 +633,100 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map, | |||
| 590 | scheduler.Finish(); | 633 | scheduler.Finish(); |
| 591 | } | 634 | } |
| 592 | 635 | ||
| 636 | MSAACopyPass::MSAACopyPass(const Device& device_, Scheduler& scheduler_, | ||
| 637 | DescriptorPool& descriptor_pool_, | ||
| 638 | StagingBufferPool& staging_buffer_pool_, | ||
| 639 | ComputePassDescriptorQueue& compute_pass_descriptor_queue_) | ||
| 640 | : ComputePass(device_, descriptor_pool_, MSAA_DESCRIPTOR_SET_BINDINGS, | ||
| 641 | MSAA_DESCRIPTOR_UPDATE_TEMPLATE, MSAA_BANK_INFO, {}, | ||
| 642 | CONVERT_NON_MSAA_TO_MSAA_COMP_SPV), | ||
| 643 | scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, | ||
| 644 | compute_pass_descriptor_queue{compute_pass_descriptor_queue_} { | ||
| 645 | const auto make_msaa_pipeline = [this](size_t i, std::span<const u32> code) { | ||
| 646 | modules[i] = device.GetLogical().CreateShaderModule({ | ||
| 647 | .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, | ||
| 648 | .pNext = nullptr, | ||
| 649 | .flags = 0, | ||
| 650 | .codeSize = static_cast<u32>(code.size_bytes()), | ||
| 651 | .pCode = code.data(), | ||
| 652 | }); | ||
| 653 | pipelines[i] = device.GetLogical().CreateComputePipeline({ | ||
| 654 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, | ||
| 655 | .pNext = nullptr, | ||
| 656 | .flags = 0, | ||
| 657 | .stage{ | ||
| 658 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | ||
| 659 | .pNext = nullptr, | ||
| 660 | .flags = 0, | ||
| 661 | .stage = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 662 | .module = *modules[i], | ||
| 663 | .pName = "main", | ||
| 664 | .pSpecializationInfo = nullptr, | ||
| 665 | }, | ||
| 666 | .layout = *layout, | ||
| 667 | .basePipelineHandle = nullptr, | ||
| 668 | .basePipelineIndex = 0, | ||
| 669 | }); | ||
| 670 | }; | ||
| 671 | make_msaa_pipeline(0, CONVERT_NON_MSAA_TO_MSAA_COMP_SPV); | ||
| 672 | make_msaa_pipeline(1, CONVERT_MSAA_TO_NON_MSAA_COMP_SPV); | ||
| 673 | } | ||
| 674 | |||
| 675 | MSAACopyPass::~MSAACopyPass() = default; | ||
| 676 | |||
| 677 | void MSAACopyPass::CopyImage(Image& dst_image, Image& src_image, | ||
| 678 | std::span<const VideoCommon::ImageCopy> copies, | ||
| 679 | bool msaa_to_non_msaa) { | ||
| 680 | const VkPipeline msaa_pipeline = *pipelines[msaa_to_non_msaa ? 1 : 0]; | ||
| 681 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 682 | for (const VideoCommon::ImageCopy& copy : copies) { | ||
| 683 | ASSERT(copy.src_subresource.base_layer == 0); | ||
| 684 | ASSERT(copy.src_subresource.num_layers == 1); | ||
| 685 | ASSERT(copy.dst_subresource.base_layer == 0); | ||
| 686 | ASSERT(copy.dst_subresource.num_layers == 1); | ||
| 687 | |||
| 688 | compute_pass_descriptor_queue.Acquire(); | ||
| 689 | compute_pass_descriptor_queue.AddImage( | ||
| 690 | src_image.StorageImageView(copy.src_subresource.base_level)); | ||
| 691 | compute_pass_descriptor_queue.AddImage( | ||
| 692 | dst_image.StorageImageView(copy.dst_subresource.base_level)); | ||
| 693 | const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()}; | ||
| 694 | |||
| 695 | const Common::Vec3<u32> num_dispatches = { | ||
| 696 | Common::DivCeil(copy.extent.width, 8U), | ||
| 697 | Common::DivCeil(copy.extent.height, 8U), | ||
| 698 | copy.extent.depth, | ||
| 699 | }; | ||
| 700 | |||
| 701 | scheduler.Record([this, dst = dst_image.Handle(), msaa_pipeline, num_dispatches, | ||
| 702 | descriptor_data](vk::CommandBuffer cmdbuf) { | ||
| 703 | const VkDescriptorSet set = descriptor_allocator.Commit(); | ||
| 704 | device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data); | ||
| 705 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, msaa_pipeline); | ||
| 706 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {}); | ||
| 707 | cmdbuf.Dispatch(num_dispatches.x, num_dispatches.y, num_dispatches.z); | ||
| 708 | const VkImageMemoryBarrier write_barrier{ | ||
| 709 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 710 | .pNext = nullptr, | ||
| 711 | .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, | ||
| 712 | .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, | ||
| 713 | .oldLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 714 | .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 715 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 716 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 717 | .image = dst, | ||
| 718 | .subresourceRange{ | ||
| 719 | .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | ||
| 720 | .baseMipLevel = 0, | ||
| 721 | .levelCount = VK_REMAINING_MIP_LEVELS, | ||
| 722 | .baseArrayLayer = 0, | ||
| 723 | .layerCount = VK_REMAINING_ARRAY_LAYERS, | ||
| 724 | }, | ||
| 725 | }; | ||
| 726 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, | ||
| 727 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, write_barrier); | ||
| 728 | }); | ||
| 729 | } | ||
| 730 | } | ||
| 731 | |||
| 593 | } // namespace Vulkan | 732 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h index 3ff935639..7b8f938c1 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.h +++ b/src/video_core/renderer_vulkan/vk_compute_pass.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "video_core/engines/maxwell_3d.h" | 11 | #include "video_core/engines/maxwell_3d.h" |
| 12 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 12 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 13 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 13 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 14 | #include "video_core/texture_cache/types.h" | ||
| 14 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | 15 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" |
| 15 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 16 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 16 | 17 | ||
| @@ -130,4 +131,22 @@ private: | |||
| 130 | MemoryAllocator& memory_allocator; | 131 | MemoryAllocator& memory_allocator; |
| 131 | }; | 132 | }; |
| 132 | 133 | ||
| 134 | class MSAACopyPass final : public ComputePass { | ||
| 135 | public: | ||
| 136 | explicit MSAACopyPass(const Device& device_, Scheduler& scheduler_, | ||
| 137 | DescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_, | ||
| 138 | ComputePassDescriptorQueue& compute_pass_descriptor_queue_); | ||
| 139 | ~MSAACopyPass(); | ||
| 140 | |||
| 141 | void CopyImage(Image& dst_image, Image& src_image, | ||
| 142 | std::span<const VideoCommon::ImageCopy> copies, bool msaa_to_non_msaa); | ||
| 143 | |||
| 144 | private: | ||
| 145 | Scheduler& scheduler; | ||
| 146 | StagingBufferPool& staging_buffer_pool; | ||
| 147 | ComputePassDescriptorQueue& compute_pass_descriptor_queue; | ||
| 148 | std::array<vk::ShaderModule, 2> modules; | ||
| 149 | std::array<vk::Pipeline, 2> pipelines; | ||
| 150 | }; | ||
| 151 | |||
| 133 | } // namespace Vulkan | 152 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index c7ce7c312..1628d76d6 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -1014,15 +1014,37 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) { | |||
| 1014 | regs.zeta.format == Tegra::DepthFormat::X8Z24_UNORM || | 1014 | regs.zeta.format == Tegra::DepthFormat::X8Z24_UNORM || |
| 1015 | regs.zeta.format == Tegra::DepthFormat::S8Z24_UNORM || | 1015 | regs.zeta.format == Tegra::DepthFormat::S8Z24_UNORM || |
| 1016 | regs.zeta.format == Tegra::DepthFormat::V8Z24_UNORM; | 1016 | regs.zeta.format == Tegra::DepthFormat::V8Z24_UNORM; |
| 1017 | if (is_d24 && !device.SupportsD24DepthBuffer()) { | 1017 | bool force_unorm = ([&] { |
| 1018 | if (!is_d24 || device.SupportsD24DepthBuffer()) { | ||
| 1019 | return false; | ||
| 1020 | } | ||
| 1021 | if (device.IsExtDepthBiasControlSupported()) { | ||
| 1022 | return true; | ||
| 1023 | } | ||
| 1024 | if (!Settings::values.renderer_amdvlk_depth_bias_workaround) { | ||
| 1025 | return false; | ||
| 1026 | } | ||
| 1018 | // the base formulas can be obtained from here: | 1027 | // the base formulas can be obtained from here: |
| 1019 | // https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias | 1028 | // https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias |
| 1020 | const double rescale_factor = | 1029 | const double rescale_factor = |
| 1021 | static_cast<double>(1ULL << (32 - 24)) / (static_cast<double>(0x1.ep+127)); | 1030 | static_cast<double>(1ULL << (32 - 24)) / (static_cast<double>(0x1.ep+127)); |
| 1022 | units = static_cast<float>(static_cast<double>(units) * rescale_factor); | 1031 | units = static_cast<float>(static_cast<double>(units) * rescale_factor); |
| 1023 | } | 1032 | return false; |
| 1033 | })(); | ||
| 1024 | scheduler.Record([constant = units, clamp = regs.depth_bias_clamp, | 1034 | scheduler.Record([constant = units, clamp = regs.depth_bias_clamp, |
| 1025 | factor = regs.slope_scale_depth_bias](vk::CommandBuffer cmdbuf) { | 1035 | factor = regs.slope_scale_depth_bias, force_unorm, |
| 1036 | precise = device.HasExactDepthBiasControl()](vk::CommandBuffer cmdbuf) { | ||
| 1037 | if (force_unorm) { | ||
| 1038 | VkDepthBiasRepresentationInfoEXT info{ | ||
| 1039 | .sType = VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT, | ||
| 1040 | .pNext = nullptr, | ||
| 1041 | .depthBiasRepresentation = | ||
| 1042 | VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT, | ||
| 1043 | .depthBiasExact = precise ? VK_TRUE : VK_FALSE, | ||
| 1044 | }; | ||
| 1045 | cmdbuf.SetDepthBias(constant, clamp, factor, &info); | ||
| 1046 | return; | ||
| 1047 | } | ||
| 1026 | cmdbuf.SetDepthBias(constant, clamp, factor); | 1048 | cmdbuf.SetDepthBias(constant, clamp, factor); |
| 1027 | }); | 1049 | }); |
| 1028 | } | 1050 | } |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 1f9e7acaa..71fdec809 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -176,6 +176,36 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 176 | return allocator.CreateImage(image_ci); | 176 | return allocator.CreateImage(image_ci); |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | [[nodiscard]] vk::ImageView MakeStorageView(const vk::Device& device, u32 level, VkImage image, | ||
| 180 | VkFormat format) { | ||
| 181 | static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{ | ||
| 182 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, | ||
| 183 | .pNext = nullptr, | ||
| 184 | .usage = VK_IMAGE_USAGE_STORAGE_BIT, | ||
| 185 | }; | ||
| 186 | return device.CreateImageView(VkImageViewCreateInfo{ | ||
| 187 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | ||
| 188 | .pNext = &storage_image_view_usage_create_info, | ||
| 189 | .flags = 0, | ||
| 190 | .image = image, | ||
| 191 | .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY, | ||
| 192 | .format = format, | ||
| 193 | .components{ | ||
| 194 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 195 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 196 | .b = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 197 | .a = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 198 | }, | ||
| 199 | .subresourceRange{ | ||
| 200 | .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | ||
| 201 | .baseMipLevel = level, | ||
| 202 | .levelCount = 1, | ||
| 203 | .baseArrayLayer = 0, | ||
| 204 | .layerCount = VK_REMAINING_ARRAY_LAYERS, | ||
| 205 | }, | ||
| 206 | }); | ||
| 207 | } | ||
| 208 | |||
| 179 | [[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) { | 209 | [[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) { |
| 180 | switch (VideoCore::Surface::GetFormatType(format)) { | 210 | switch (VideoCore::Surface::GetFormatType(format)) { |
| 181 | case VideoCore::Surface::SurfaceType::ColorTexture: | 211 | case VideoCore::Surface::SurfaceType::ColorTexture: |
| @@ -817,6 +847,10 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched | |||
| 817 | astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, | 847 | astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, |
| 818 | compute_pass_descriptor_queue, memory_allocator); | 848 | compute_pass_descriptor_queue, memory_allocator); |
| 819 | } | 849 | } |
| 850 | if (device.IsStorageImageMultisampleSupported()) { | ||
| 851 | msaa_copy_pass = std::make_unique<MSAACopyPass>( | ||
| 852 | device, scheduler, descriptor_pool, staging_buffer_pool, compute_pass_descriptor_queue); | ||
| 853 | } | ||
| 820 | if (!device.IsKhrImageFormatListSupported()) { | 854 | if (!device.IsKhrImageFormatListSupported()) { |
| 821 | return; | 855 | return; |
| 822 | } | 856 | } |
| @@ -1285,7 +1319,11 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src, | |||
| 1285 | 1319 | ||
| 1286 | void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src, | 1320 | void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src, |
| 1287 | std::span<const VideoCommon::ImageCopy> copies) { | 1321 | std::span<const VideoCommon::ImageCopy> copies) { |
| 1288 | UNIMPLEMENTED_MSG("Copying images with different samples is not implemented in Vulkan."); | 1322 | const bool msaa_to_non_msaa = src.info.num_samples > 1 && dst.info.num_samples == 1; |
| 1323 | if (msaa_copy_pass) { | ||
| 1324 | return msaa_copy_pass->CopyImage(dst, src, copies, msaa_to_non_msaa); | ||
| 1325 | } | ||
| 1326 | UNIMPLEMENTED_MSG("Copying images with different samples is not supported."); | ||
| 1289 | } | 1327 | } |
| 1290 | 1328 | ||
| 1291 | u64 TextureCacheRuntime::GetDeviceLocalMemory() const { | 1329 | u64 TextureCacheRuntime::GetDeviceLocalMemory() const { |
| @@ -1333,39 +1371,15 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu | |||
| 1333 | if (runtime->device.HasDebuggingToolAttached()) { | 1371 | if (runtime->device.HasDebuggingToolAttached()) { |
| 1334 | original_image.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); | 1372 | original_image.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); |
| 1335 | } | 1373 | } |
| 1336 | static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{ | ||
| 1337 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, | ||
| 1338 | .pNext = nullptr, | ||
| 1339 | .usage = VK_IMAGE_USAGE_STORAGE_BIT, | ||
| 1340 | }; | ||
| 1341 | current_image = *original_image; | 1374 | current_image = *original_image; |
| 1375 | storage_image_views.resize(info.resources.levels); | ||
| 1342 | if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported() && | 1376 | if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported() && |
| 1343 | Settings::values.astc_recompression.GetValue() == | 1377 | Settings::values.astc_recompression.GetValue() == |
| 1344 | Settings::AstcRecompression::Uncompressed) { | 1378 | Settings::AstcRecompression::Uncompressed) { |
| 1345 | const auto& device = runtime->device.GetLogical(); | 1379 | const auto& device = runtime->device.GetLogical(); |
| 1346 | storage_image_views.reserve(info.resources.levels); | ||
| 1347 | for (s32 level = 0; level < info.resources.levels; ++level) { | 1380 | for (s32 level = 0; level < info.resources.levels; ++level) { |
| 1348 | storage_image_views.push_back(device.CreateImageView(VkImageViewCreateInfo{ | 1381 | storage_image_views[level] = |
| 1349 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | 1382 | MakeStorageView(device, level, *original_image, VK_FORMAT_A8B8G8R8_UNORM_PACK32); |
| 1350 | .pNext = &storage_image_view_usage_create_info, | ||
| 1351 | .flags = 0, | ||
| 1352 | .image = *original_image, | ||
| 1353 | .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY, | ||
| 1354 | .format = VK_FORMAT_A8B8G8R8_UNORM_PACK32, | ||
| 1355 | .components{ | ||
| 1356 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 1357 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 1358 | .b = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 1359 | .a = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 1360 | }, | ||
| 1361 | .subresourceRange{ | ||
| 1362 | .aspectMask = aspect_mask, | ||
| 1363 | .baseMipLevel = static_cast<u32>(level), | ||
| 1364 | .levelCount = 1, | ||
| 1365 | .baseArrayLayer = 0, | ||
| 1366 | .layerCount = VK_REMAINING_ARRAY_LAYERS, | ||
| 1367 | }, | ||
| 1368 | })); | ||
| 1369 | } | 1383 | } |
| 1370 | } | 1384 | } |
| 1371 | } | 1385 | } |
| @@ -1496,6 +1510,17 @@ void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferIm | |||
| 1496 | DownloadMemory(buffers, offsets, copies); | 1510 | DownloadMemory(buffers, offsets, copies); |
| 1497 | } | 1511 | } |
| 1498 | 1512 | ||
| 1513 | VkImageView Image::StorageImageView(s32 level) noexcept { | ||
| 1514 | auto& view = storage_image_views[level]; | ||
| 1515 | if (!view) { | ||
| 1516 | const auto format_info = | ||
| 1517 | MaxwellToVK::SurfaceFormat(runtime->device, FormatType::Optimal, true, info.format); | ||
| 1518 | view = | ||
| 1519 | MakeStorageView(runtime->device.GetLogical(), level, current_image, format_info.format); | ||
| 1520 | } | ||
| 1521 | return *view; | ||
| 1522 | } | ||
| 1523 | |||
| 1499 | bool Image::IsRescaled() const noexcept { | 1524 | bool Image::IsRescaled() const noexcept { |
| 1500 | return True(flags & ImageFlagBits::Rescaled); | 1525 | return True(flags & ImageFlagBits::Rescaled); |
| 1501 | } | 1526 | } |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 565ce19a9..d6c5a15cc 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -117,6 +117,7 @@ public: | |||
| 117 | BlitImageHelper& blit_image_helper; | 117 | BlitImageHelper& blit_image_helper; |
| 118 | RenderPassCache& render_pass_cache; | 118 | RenderPassCache& render_pass_cache; |
| 119 | std::optional<ASTCDecoderPass> astc_decoder_pass; | 119 | std::optional<ASTCDecoderPass> astc_decoder_pass; |
| 120 | std::unique_ptr<MSAACopyPass> msaa_copy_pass; | ||
| 120 | const Settings::ResolutionScalingInfo& resolution; | 121 | const Settings::ResolutionScalingInfo& resolution; |
| 121 | std::array<std::vector<VkFormat>, VideoCore::Surface::MaxPixelFormat> view_formats; | 122 | std::array<std::vector<VkFormat>, VideoCore::Surface::MaxPixelFormat> view_formats; |
| 122 | 123 | ||
| @@ -161,15 +162,13 @@ public: | |||
| 161 | return aspect_mask; | 162 | return aspect_mask; |
| 162 | } | 163 | } |
| 163 | 164 | ||
| 164 | [[nodiscard]] VkImageView StorageImageView(s32 level) const noexcept { | ||
| 165 | return *storage_image_views[level]; | ||
| 166 | } | ||
| 167 | |||
| 168 | /// Returns true when the image is already initialized and mark it as initialized | 165 | /// Returns true when the image is already initialized and mark it as initialized |
| 169 | [[nodiscard]] bool ExchangeInitialization() noexcept { | 166 | [[nodiscard]] bool ExchangeInitialization() noexcept { |
| 170 | return std::exchange(initialized, true); | 167 | return std::exchange(initialized, true); |
| 171 | } | 168 | } |
| 172 | 169 | ||
| 170 | VkImageView StorageImageView(s32 level) noexcept; | ||
| 171 | |||
| 173 | bool IsRescaled() const noexcept; | 172 | bool IsRescaled() const noexcept; |
| 174 | 173 | ||
| 175 | bool ScaleUp(bool ignore = false); | 174 | bool ScaleUp(bool ignore = false); |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 18185610f..3960b135a 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -1059,6 +1059,13 @@ void Device::RemoveUnsuitableExtensions() { | |||
| 1059 | RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color, | 1059 | RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color, |
| 1060 | VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); | 1060 | VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); |
| 1061 | 1061 | ||
| 1062 | // VK_EXT_depth_bias_control | ||
| 1063 | extensions.depth_bias_control = | ||
| 1064 | features.depth_bias_control.depthBiasControl && | ||
| 1065 | features.depth_bias_control.leastRepresentableValueForceUnormRepresentation; | ||
| 1066 | RemoveExtensionFeatureIfUnsuitable(extensions.depth_bias_control, features.depth_bias_control, | ||
| 1067 | VK_EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME); | ||
| 1068 | |||
| 1062 | // VK_EXT_depth_clip_control | 1069 | // VK_EXT_depth_clip_control |
| 1063 | extensions.depth_clip_control = features.depth_clip_control.depthClipControl; | 1070 | extensions.depth_clip_control = features.depth_clip_control.depthClipControl; |
| 1064 | RemoveExtensionFeatureIfUnsuitable(extensions.depth_clip_control, features.depth_clip_control, | 1071 | RemoveExtensionFeatureIfUnsuitable(extensions.depth_clip_control, features.depth_clip_control, |
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 94f41266d..9be612392 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -41,6 +41,7 @@ VK_DEFINE_HANDLE(VmaAllocator) | |||
| 41 | // Define all features which may be used by the implementation and require an extension here. | 41 | // Define all features which may be used by the implementation and require an extension here. |
| 42 | #define FOR_EACH_VK_FEATURE_EXT(FEATURE) \ | 42 | #define FOR_EACH_VK_FEATURE_EXT(FEATURE) \ |
| 43 | FEATURE(EXT, CustomBorderColor, CUSTOM_BORDER_COLOR, custom_border_color) \ | 43 | FEATURE(EXT, CustomBorderColor, CUSTOM_BORDER_COLOR, custom_border_color) \ |
| 44 | FEATURE(EXT, DepthBiasControl, DEPTH_BIAS_CONTROL, depth_bias_control) \ | ||
| 44 | FEATURE(EXT, DepthClipControl, DEPTH_CLIP_CONTROL, depth_clip_control) \ | 45 | FEATURE(EXT, DepthClipControl, DEPTH_CLIP_CONTROL, depth_clip_control) \ |
| 45 | FEATURE(EXT, ExtendedDynamicState, EXTENDED_DYNAMIC_STATE, extended_dynamic_state) \ | 46 | FEATURE(EXT, ExtendedDynamicState, EXTENDED_DYNAMIC_STATE, extended_dynamic_state) \ |
| 46 | FEATURE(EXT, ExtendedDynamicState2, EXTENDED_DYNAMIC_STATE_2, extended_dynamic_state2) \ | 47 | FEATURE(EXT, ExtendedDynamicState2, EXTENDED_DYNAMIC_STATE_2, extended_dynamic_state2) \ |
| @@ -96,6 +97,7 @@ VK_DEFINE_HANDLE(VmaAllocator) | |||
| 96 | #define FOR_EACH_VK_RECOMMENDED_EXTENSION(EXTENSION_NAME) \ | 97 | #define FOR_EACH_VK_RECOMMENDED_EXTENSION(EXTENSION_NAME) \ |
| 97 | EXTENSION_NAME(VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME) \ | 98 | EXTENSION_NAME(VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME) \ |
| 98 | EXTENSION_NAME(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME) \ | 99 | EXTENSION_NAME(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME) \ |
| 100 | EXTENSION_NAME(VK_EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME) \ | ||
| 99 | EXTENSION_NAME(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME) \ | 101 | EXTENSION_NAME(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME) \ |
| 100 | EXTENSION_NAME(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) \ | 102 | EXTENSION_NAME(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) \ |
| 101 | EXTENSION_NAME(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME) \ | 103 | EXTENSION_NAME(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME) \ |
| @@ -147,6 +149,9 @@ VK_DEFINE_HANDLE(VmaAllocator) | |||
| 147 | // Define features where the absence of the feature may result in a degraded experience. | 149 | // Define features where the absence of the feature may result in a degraded experience. |
| 148 | #define FOR_EACH_VK_RECOMMENDED_FEATURE(FEATURE_NAME) \ | 150 | #define FOR_EACH_VK_RECOMMENDED_FEATURE(FEATURE_NAME) \ |
| 149 | FEATURE_NAME(custom_border_color, customBorderColors) \ | 151 | FEATURE_NAME(custom_border_color, customBorderColors) \ |
| 152 | FEATURE_NAME(depth_bias_control, depthBiasControl) \ | ||
| 153 | FEATURE_NAME(depth_bias_control, leastRepresentableValueForceUnormRepresentation) \ | ||
| 154 | FEATURE_NAME(depth_bias_control, depthBiasExact) \ | ||
| 150 | FEATURE_NAME(extended_dynamic_state, extendedDynamicState) \ | 155 | FEATURE_NAME(extended_dynamic_state, extendedDynamicState) \ |
| 151 | FEATURE_NAME(format_a4b4g4r4, formatA4B4G4R4) \ | 156 | FEATURE_NAME(format_a4b4g4r4, formatA4B4G4R4) \ |
| 152 | FEATURE_NAME(index_type_uint8, indexTypeUint8) \ | 157 | FEATURE_NAME(index_type_uint8, indexTypeUint8) \ |
| @@ -324,6 +329,11 @@ public: | |||
| 324 | return features.shader_float16_int8.shaderInt8; | 329 | return features.shader_float16_int8.shaderInt8; |
| 325 | } | 330 | } |
| 326 | 331 | ||
| 332 | /// Returns true if the device supports binding multisample images as storage images. | ||
| 333 | bool IsStorageImageMultisampleSupported() const { | ||
| 334 | return features.features.shaderStorageImageMultisample; | ||
| 335 | } | ||
| 336 | |||
| 327 | /// Returns true if the device warp size can potentially be bigger than guest's warp size. | 337 | /// Returns true if the device warp size can potentially be bigger than guest's warp size. |
| 328 | bool IsWarpSizePotentiallyBiggerThanGuest() const { | 338 | bool IsWarpSizePotentiallyBiggerThanGuest() const { |
| 329 | return is_warp_potentially_bigger; | 339 | return is_warp_potentially_bigger; |
| @@ -459,6 +469,11 @@ public: | |||
| 459 | return extensions.depth_clip_control; | 469 | return extensions.depth_clip_control; |
| 460 | } | 470 | } |
| 461 | 471 | ||
| 472 | /// Returns true if the device supports VK_EXT_depth_bias_control. | ||
| 473 | bool IsExtDepthBiasControlSupported() const { | ||
| 474 | return extensions.depth_bias_control; | ||
| 475 | } | ||
| 476 | |||
| 462 | /// Returns true if the device supports VK_EXT_shader_viewport_index_layer. | 477 | /// Returns true if the device supports VK_EXT_shader_viewport_index_layer. |
| 463 | bool IsExtShaderViewportIndexLayerSupported() const { | 478 | bool IsExtShaderViewportIndexLayerSupported() const { |
| 464 | return extensions.shader_viewport_index_layer; | 479 | return extensions.shader_viewport_index_layer; |
| @@ -619,6 +634,10 @@ public: | |||
| 619 | return features.robustness2.nullDescriptor; | 634 | return features.robustness2.nullDescriptor; |
| 620 | } | 635 | } |
| 621 | 636 | ||
| 637 | bool HasExactDepthBiasControl() const { | ||
| 638 | return features.depth_bias_control.depthBiasExact; | ||
| 639 | } | ||
| 640 | |||
| 622 | u32 GetMaxVertexInputAttributes() const { | 641 | u32 GetMaxVertexInputAttributes() const { |
| 623 | return properties.properties.limits.maxVertexInputAttributes; | 642 | return properties.properties.limits.maxVertexInputAttributes; |
| 624 | } | 643 | } |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 5afba365c..2f3254a97 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp | |||
| @@ -113,6 +113,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { | |||
| 113 | X(vkCmdPushDescriptorSetWithTemplateKHR); | 113 | X(vkCmdPushDescriptorSetWithTemplateKHR); |
| 114 | X(vkCmdSetBlendConstants); | 114 | X(vkCmdSetBlendConstants); |
| 115 | X(vkCmdSetDepthBias); | 115 | X(vkCmdSetDepthBias); |
| 116 | X(vkCmdSetDepthBias2EXT); | ||
| 116 | X(vkCmdSetDepthBounds); | 117 | X(vkCmdSetDepthBounds); |
| 117 | X(vkCmdSetEvent); | 118 | X(vkCmdSetEvent); |
| 118 | X(vkCmdSetScissor); | 119 | X(vkCmdSetScissor); |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 0d4bbe7f7..1e3c0fa64 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h | |||
| @@ -226,6 +226,7 @@ struct DeviceDispatch : InstanceDispatch { | |||
| 226 | PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants{}; | 226 | PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants{}; |
| 227 | PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT{}; | 227 | PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT{}; |
| 228 | PFN_vkCmdSetDepthBias vkCmdSetDepthBias{}; | 228 | PFN_vkCmdSetDepthBias vkCmdSetDepthBias{}; |
| 229 | PFN_vkCmdSetDepthBias2EXT vkCmdSetDepthBias2EXT{}; | ||
| 229 | PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds{}; | 230 | PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds{}; |
| 230 | PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT{}; | 231 | PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT{}; |
| 231 | PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT{}; | 232 | PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT{}; |
| @@ -1333,6 +1334,18 @@ public: | |||
| 1333 | dld->vkCmdSetDepthBias(handle, constant_factor, clamp, slope_factor); | 1334 | dld->vkCmdSetDepthBias(handle, constant_factor, clamp, slope_factor); |
| 1334 | } | 1335 | } |
| 1335 | 1336 | ||
| 1337 | void SetDepthBias(float constant_factor, float clamp, float slope_factor, | ||
| 1338 | VkDepthBiasRepresentationInfoEXT* extra) const noexcept { | ||
| 1339 | VkDepthBiasInfoEXT info{ | ||
| 1340 | .sType = VK_STRUCTURE_TYPE_DEPTH_BIAS_INFO_EXT, | ||
| 1341 | .pNext = extra, | ||
| 1342 | .depthBiasConstantFactor = constant_factor, | ||
| 1343 | .depthBiasClamp = clamp, | ||
| 1344 | .depthBiasSlopeFactor = slope_factor, | ||
| 1345 | }; | ||
| 1346 | dld->vkCmdSetDepthBias2EXT(handle, &info); | ||
| 1347 | } | ||
| 1348 | |||
| 1336 | void SetDepthBounds(float min_depth_bounds, float max_depth_bounds) const noexcept { | 1349 | void SetDepthBounds(float min_depth_bounds, float max_depth_bounds) const noexcept { |
| 1337 | dld->vkCmdSetDepthBounds(handle, min_depth_bounds, max_depth_bounds); | 1350 | dld->vkCmdSetDepthBounds(handle, min_depth_bounds, max_depth_bounds); |
| 1338 | } | 1351 | } |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index b1b6b9354..adb7b332f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -3113,10 +3113,9 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 3113 | QFuture<InstallResult> future; | 3113 | QFuture<InstallResult> future; |
| 3114 | InstallResult result; | 3114 | InstallResult result; |
| 3115 | 3115 | ||
| 3116 | if (file.endsWith(QStringLiteral("xci"), Qt::CaseInsensitive) || | 3116 | if (file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { |
| 3117 | file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { | ||
| 3118 | 3117 | ||
| 3119 | future = QtConcurrent::run([this, &file] { return InstallNSPXCI(file); }); | 3118 | future = QtConcurrent::run([this, &file] { return InstallNSP(file); }); |
| 3120 | 3119 | ||
| 3121 | while (!future.isFinished()) { | 3120 | while (!future.isFinished()) { |
| 3122 | QCoreApplication::processEvents(); | 3121 | QCoreApplication::processEvents(); |
| @@ -3175,7 +3174,7 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 3175 | ui->action_Install_File_NAND->setEnabled(true); | 3174 | ui->action_Install_File_NAND->setEnabled(true); |
| 3176 | } | 3175 | } |
| 3177 | 3176 | ||
| 3178 | InstallResult GMainWindow::InstallNSPXCI(const QString& filename) { | 3177 | InstallResult GMainWindow::InstallNSP(const QString& filename) { |
| 3179 | const auto qt_raw_copy = [this](const FileSys::VirtualFile& src, | 3178 | const auto qt_raw_copy = [this](const FileSys::VirtualFile& src, |
| 3180 | const FileSys::VirtualFile& dest, std::size_t block_size) { | 3179 | const FileSys::VirtualFile& dest, std::size_t block_size) { |
| 3181 | if (src == nullptr || dest == nullptr) { | 3180 | if (src == nullptr || dest == nullptr) { |
| @@ -3209,9 +3208,7 @@ InstallResult GMainWindow::InstallNSPXCI(const QString& filename) { | |||
| 3209 | return InstallResult::Failure; | 3208 | return InstallResult::Failure; |
| 3210 | } | 3209 | } |
| 3211 | } else { | 3210 | } else { |
| 3212 | const auto xci = std::make_shared<FileSys::XCI>( | 3211 | return InstallResult::Failure; |
| 3213 | vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); | ||
| 3214 | nsp = xci->GetSecurePartitionNSP(); | ||
| 3215 | } | 3212 | } |
| 3216 | 3213 | ||
| 3217 | if (nsp->GetStatus() != Loader::ResultStatus::Success) { | 3214 | if (nsp->GetStatus() != Loader::ResultStatus::Success) { |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 53bedfab3..ba318eb11 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -387,7 +387,7 @@ private: | |||
| 387 | void RemoveCacheStorage(u64 program_id); | 387 | void RemoveCacheStorage(u64 program_id); |
| 388 | bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id, | 388 | bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id, |
| 389 | u64* selected_title_id, u8* selected_content_record_type); | 389 | u64* selected_title_id, u8* selected_content_record_type); |
| 390 | InstallResult InstallNSPXCI(const QString& filename); | 390 | InstallResult InstallNSP(const QString& filename); |
| 391 | InstallResult InstallNCA(const QString& filename); | 391 | InstallResult InstallNCA(const QString& filename); |
| 392 | void MigrateConfigFiles(); | 392 | void MigrateConfigFiles(); |
| 393 | void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, | 393 | void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, |