diff options
| -rw-r--r-- | src/common/file_util.cpp | 20 | ||||
| -rw-r--r-- | src/common/file_util.h | 8 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_real.cpp | 6 | ||||
| -rw-r--r-- | src/core/loader/deconstructed_rom_directory.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 16 | ||||
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 11 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 28 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 138 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 47 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 102 | ||||
| -rw-r--r-- | src/yuzu/game_list.cpp | 2 |
11 files changed, 211 insertions, 169 deletions
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 819ffd6ff..a427372c9 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp | |||
| @@ -386,12 +386,12 @@ bool CreateEmptyFile(const std::string& filename) { | |||
| 386 | return true; | 386 | return true; |
| 387 | } | 387 | } |
| 388 | 388 | ||
| 389 | bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string& directory, | 389 | bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory, |
| 390 | DirectoryEntryCallable callback) { | 390 | DirectoryEntryCallable callback) { |
| 391 | LOG_TRACE(Common_Filesystem, "directory {}", directory); | 391 | LOG_TRACE(Common_Filesystem, "directory {}", directory); |
| 392 | 392 | ||
| 393 | // How many files + directories we found | 393 | // How many files + directories we found |
| 394 | unsigned found_entries = 0; | 394 | u64 found_entries = 0; |
| 395 | 395 | ||
| 396 | // Save the status of callback function | 396 | // Save the status of callback function |
| 397 | bool callback_error = false; | 397 | bool callback_error = false; |
| @@ -421,7 +421,7 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string& directo | |||
| 421 | if (virtual_name == "." || virtual_name == "..") | 421 | if (virtual_name == "." || virtual_name == "..") |
| 422 | continue; | 422 | continue; |
| 423 | 423 | ||
| 424 | unsigned ret_entries = 0; | 424 | u64 ret_entries = 0; |
| 425 | if (!callback(&ret_entries, directory, virtual_name)) { | 425 | if (!callback(&ret_entries, directory, virtual_name)) { |
| 426 | callback_error = true; | 426 | callback_error = true; |
| 427 | break; | 427 | break; |
| @@ -445,9 +445,9 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string& directo | |||
| 445 | return true; | 445 | return true; |
| 446 | } | 446 | } |
| 447 | 447 | ||
| 448 | unsigned ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry, | 448 | u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry, |
| 449 | unsigned int recursion) { | 449 | unsigned int recursion) { |
| 450 | const auto callback = [recursion, &parent_entry](unsigned* num_entries_out, | 450 | const auto callback = [recursion, &parent_entry](u64* num_entries_out, |
| 451 | const std::string& directory, | 451 | const std::string& directory, |
| 452 | const std::string& virtual_name) -> bool { | 452 | const std::string& virtual_name) -> bool { |
| 453 | FSTEntry entry; | 453 | FSTEntry entry; |
| @@ -459,7 +459,7 @@ unsigned ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry, | |||
| 459 | // is a directory, lets go inside if we didn't recurse to often | 459 | // is a directory, lets go inside if we didn't recurse to often |
| 460 | if (recursion > 0) { | 460 | if (recursion > 0) { |
| 461 | entry.size = ScanDirectoryTree(entry.physicalName, entry, recursion - 1); | 461 | entry.size = ScanDirectoryTree(entry.physicalName, entry, recursion - 1); |
| 462 | *num_entries_out += (int)entry.size; | 462 | *num_entries_out += entry.size; |
| 463 | } else { | 463 | } else { |
| 464 | entry.size = 0; | 464 | entry.size = 0; |
| 465 | } | 465 | } |
| @@ -470,16 +470,16 @@ unsigned ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry, | |||
| 470 | (*num_entries_out)++; | 470 | (*num_entries_out)++; |
| 471 | 471 | ||
| 472 | // Push into the tree | 472 | // Push into the tree |
| 473 | parent_entry.children.push_back(entry); | 473 | parent_entry.children.push_back(std::move(entry)); |
| 474 | return true; | 474 | return true; |
| 475 | }; | 475 | }; |
| 476 | 476 | ||
| 477 | unsigned num_entries; | 477 | u64 num_entries; |
| 478 | return ForeachDirectoryEntry(&num_entries, directory, callback) ? num_entries : 0; | 478 | return ForeachDirectoryEntry(&num_entries, directory, callback) ? num_entries : 0; |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | bool DeleteDirRecursively(const std::string& directory, unsigned int recursion) { | 481 | bool DeleteDirRecursively(const std::string& directory, unsigned int recursion) { |
| 482 | const auto callback = [recursion](unsigned* num_entries_out, const std::string& directory, | 482 | const auto callback = [recursion](u64* num_entries_out, const std::string& directory, |
| 483 | const std::string& virtual_name) -> bool { | 483 | const std::string& virtual_name) -> bool { |
| 484 | std::string new_path = directory + DIR_SEP_CHR + virtual_name; | 484 | std::string new_path = directory + DIR_SEP_CHR + virtual_name; |
| 485 | 485 | ||
diff --git a/src/common/file_util.h b/src/common/file_util.h index ff01bf0ff..090907c03 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h | |||
| @@ -84,7 +84,7 @@ bool CreateEmptyFile(const std::string& filename); | |||
| 84 | * @return whether handling the entry succeeded | 84 | * @return whether handling the entry succeeded |
| 85 | */ | 85 | */ |
| 86 | using DirectoryEntryCallable = std::function<bool( | 86 | using DirectoryEntryCallable = std::function<bool( |
| 87 | unsigned* num_entries_out, const std::string& directory, const std::string& virtual_name)>; | 87 | u64* num_entries_out, const std::string& directory, const std::string& virtual_name)>; |
| 88 | 88 | ||
| 89 | /** | 89 | /** |
| 90 | * Scans a directory, calling the callback for each file/directory contained within. | 90 | * Scans a directory, calling the callback for each file/directory contained within. |
| @@ -95,7 +95,7 @@ using DirectoryEntryCallable = std::function<bool( | |||
| 95 | * @param callback The callback which will be called for each entry | 95 | * @param callback The callback which will be called for each entry |
| 96 | * @return whether scanning the directory succeeded | 96 | * @return whether scanning the directory succeeded |
| 97 | */ | 97 | */ |
| 98 | bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string& directory, | 98 | bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory, |
| 99 | DirectoryEntryCallable callback); | 99 | DirectoryEntryCallable callback); |
| 100 | 100 | ||
| 101 | /** | 101 | /** |
| @@ -105,8 +105,8 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string& directo | |||
| 105 | * @param recursion Number of children directories to read before giving up. | 105 | * @param recursion Number of children directories to read before giving up. |
| 106 | * @return the total number of files/directories found | 106 | * @return the total number of files/directories found |
| 107 | */ | 107 | */ |
| 108 | unsigned ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry, | 108 | u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry, |
| 109 | unsigned int recursion = 0); | 109 | unsigned int recursion = 0); |
| 110 | 110 | ||
| 111 | // deletes the given directory and anything under it. Returns true on success. | 111 | // deletes the given directory and anything under it. Returns true on success. |
| 112 | bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256); | 112 | bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256); |
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index f27fb1f2a..27fd464ae 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp | |||
| @@ -92,13 +92,13 @@ RealVfsDirectory::RealVfsDirectory(const std::string& path_, Mode perms_) | |||
| 92 | perms(perms_) { | 92 | perms(perms_) { |
| 93 | if (!FileUtil::Exists(path) && (perms == Mode::Write || perms == Mode::Append)) | 93 | if (!FileUtil::Exists(path) && (perms == Mode::Write || perms == Mode::Append)) |
| 94 | FileUtil::CreateDir(path); | 94 | FileUtil::CreateDir(path); |
| 95 | unsigned size; | 95 | |
| 96 | if (perms == Mode::Append) | 96 | if (perms == Mode::Append) |
| 97 | return; | 97 | return; |
| 98 | 98 | ||
| 99 | FileUtil::ForeachDirectoryEntry( | 99 | FileUtil::ForeachDirectoryEntry( |
| 100 | &size, path, | 100 | nullptr, path, |
| 101 | [this](unsigned* entries_out, const std::string& directory, const std::string& filename) { | 101 | [this](u64* entries_out, const std::string& directory, const std::string& filename) { |
| 102 | std::string full_path = directory + DIR_SEP + filename; | 102 | std::string full_path = directory + DIR_SEP + filename; |
| 103 | if (FileUtil::IsDirectory(full_path)) | 103 | if (FileUtil::IsDirectory(full_path)) |
| 104 | subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(full_path, perms)); | 104 | subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(full_path, perms)); |
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 394963a69..18bd62a08 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp | |||
| @@ -20,7 +20,7 @@ namespace Loader { | |||
| 20 | 20 | ||
| 21 | static std::string FindRomFS(const std::string& directory) { | 21 | static std::string FindRomFS(const std::string& directory) { |
| 22 | std::string filepath_romfs; | 22 | std::string filepath_romfs; |
| 23 | const auto callback = [&filepath_romfs](unsigned*, const std::string& directory, | 23 | const auto callback = [&filepath_romfs](u64*, const std::string& directory, |
| 24 | const std::string& virtual_name) -> bool { | 24 | const std::string& virtual_name) -> bool { |
| 25 | const std::string physical_name = directory + virtual_name; | 25 | const std::string physical_name = directory + virtual_name; |
| 26 | if (FileUtil::IsDirectory(physical_name)) { | 26 | if (FileUtil::IsDirectory(physical_name)) { |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index dbd106c53..3c32f1067 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -487,7 +487,12 @@ public: | |||
| 487 | }; | 487 | }; |
| 488 | } rt_control; | 488 | } rt_control; |
| 489 | 489 | ||
| 490 | INSERT_PADDING_WORDS(0x2B); | 490 | INSERT_PADDING_WORDS(0x2); |
| 491 | |||
| 492 | u32 zeta_width; | ||
| 493 | u32 zeta_height; | ||
| 494 | |||
| 495 | INSERT_PADDING_WORDS(0x27); | ||
| 491 | 496 | ||
| 492 | u32 depth_test_enable; | 497 | u32 depth_test_enable; |
| 493 | 498 | ||
| @@ -540,7 +545,11 @@ public: | |||
| 540 | 545 | ||
| 541 | u32 vb_element_base; | 546 | u32 vb_element_base; |
| 542 | 547 | ||
| 543 | INSERT_PADDING_WORDS(0x49); | 548 | INSERT_PADDING_WORDS(0x40); |
| 549 | |||
| 550 | u32 zeta_enable; | ||
| 551 | |||
| 552 | INSERT_PADDING_WORDS(0x8); | ||
| 544 | 553 | ||
| 545 | struct { | 554 | struct { |
| 546 | u32 tsc_address_high; | 555 | u32 tsc_address_high; |
| @@ -865,6 +874,8 @@ ASSERT_REG_POSITION(clear_depth, 0x364); | |||
| 865 | ASSERT_REG_POSITION(zeta, 0x3F8); | 874 | ASSERT_REG_POSITION(zeta, 0x3F8); |
| 866 | ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458); | 875 | ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458); |
| 867 | ASSERT_REG_POSITION(rt_control, 0x487); | 876 | ASSERT_REG_POSITION(rt_control, 0x487); |
| 877 | ASSERT_REG_POSITION(zeta_width, 0x48a); | ||
| 878 | ASSERT_REG_POSITION(zeta_height, 0x48b); | ||
| 868 | ASSERT_REG_POSITION(depth_test_enable, 0x4B3); | 879 | ASSERT_REG_POSITION(depth_test_enable, 0x4B3); |
| 869 | ASSERT_REG_POSITION(independent_blend_enable, 0x4B9); | 880 | ASSERT_REG_POSITION(independent_blend_enable, 0x4B9); |
| 870 | ASSERT_REG_POSITION(depth_write_enabled, 0x4BA); | 881 | ASSERT_REG_POSITION(depth_write_enabled, 0x4BA); |
| @@ -874,6 +885,7 @@ ASSERT_REG_POSITION(blend, 0x4CF); | |||
| 874 | ASSERT_REG_POSITION(stencil, 0x4E0); | 885 | ASSERT_REG_POSITION(stencil, 0x4E0); |
| 875 | ASSERT_REG_POSITION(screen_y_control, 0x4EB); | 886 | ASSERT_REG_POSITION(screen_y_control, 0x4EB); |
| 876 | ASSERT_REG_POSITION(vb_element_base, 0x50D); | 887 | ASSERT_REG_POSITION(vb_element_base, 0x50D); |
| 888 | ASSERT_REG_POSITION(zeta_enable, 0x54E); | ||
| 877 | ASSERT_REG_POSITION(tsc, 0x557); | 889 | ASSERT_REG_POSITION(tsc, 0x557); |
| 878 | ASSERT_REG_POSITION(tic, 0x55D); | 890 | ASSERT_REG_POSITION(tic, 0x55D); |
| 879 | ASSERT_REG_POSITION(stencil_two_side, 0x565); | 891 | ASSERT_REG_POSITION(stencil_two_side, 0x565); |
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 939a71022..f495b623b 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -290,6 +290,11 @@ union Instruction { | |||
| 290 | 290 | ||
| 291 | union { | 291 | union { |
| 292 | BitField<39, 3, u64> pred; | 292 | BitField<39, 3, u64> pred; |
| 293 | BitField<42, 1, u64> neg_pred; | ||
| 294 | } sel; | ||
| 295 | |||
| 296 | union { | ||
| 297 | BitField<39, 3, u64> pred; | ||
| 293 | BitField<42, 1, u64> negate_pred; | 298 | BitField<42, 1, u64> negate_pred; |
| 294 | BitField<43, 2, IMinMaxExchange> exchange; | 299 | BitField<43, 2, IMinMaxExchange> exchange; |
| 295 | BitField<48, 1, u64> is_signed; | 300 | BitField<48, 1, u64> is_signed; |
| @@ -513,6 +518,9 @@ public: | |||
| 513 | ISCADD_C, // Scale and Add | 518 | ISCADD_C, // Scale and Add |
| 514 | ISCADD_R, | 519 | ISCADD_R, |
| 515 | ISCADD_IMM, | 520 | ISCADD_IMM, |
| 521 | SEL_C, | ||
| 522 | SEL_R, | ||
| 523 | SEL_IMM, | ||
| 516 | MUFU, // Multi-Function Operator | 524 | MUFU, // Multi-Function Operator |
| 517 | RRO_C, // Range Reduction Operator | 525 | RRO_C, // Range Reduction Operator |
| 518 | RRO_R, | 526 | RRO_R, |
| @@ -713,6 +721,9 @@ private: | |||
| 713 | INST("0100110000011---", Id::ISCADD_C, Type::ArithmeticInteger, "ISCADD_C"), | 721 | INST("0100110000011---", Id::ISCADD_C, Type::ArithmeticInteger, "ISCADD_C"), |
| 714 | INST("0101110000011---", Id::ISCADD_R, Type::ArithmeticInteger, "ISCADD_R"), | 722 | INST("0101110000011---", Id::ISCADD_R, Type::ArithmeticInteger, "ISCADD_R"), |
| 715 | INST("0011100-00011---", Id::ISCADD_IMM, Type::ArithmeticInteger, "ISCADD_IMM"), | 723 | INST("0011100-00011---", Id::ISCADD_IMM, Type::ArithmeticInteger, "ISCADD_IMM"), |
| 724 | INST("0100110010100---", Id::SEL_C, Type::ArithmeticInteger, "SEL_C"), | ||
| 725 | INST("0101110010100---", Id::SEL_R, Type::ArithmeticInteger, "SEL_R"), | ||
| 726 | INST("0011100010100---", Id::SEL_IMM, Type::ArithmeticInteger, "SEL_IMM"), | ||
| 716 | INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), | 727 | INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), |
| 717 | INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), | 728 | INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), |
| 718 | INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), | 729 | INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 65a2fd5e8..56d9c575b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -387,7 +387,7 @@ void RasterizerOpenGL::Clear() { | |||
| 387 | } | 387 | } |
| 388 | if (regs.clear_buffers.Z) { | 388 | if (regs.clear_buffers.Z) { |
| 389 | clear_mask |= GL_DEPTH_BUFFER_BIT; | 389 | clear_mask |= GL_DEPTH_BUFFER_BIT; |
| 390 | use_depth_fb = true; | 390 | use_depth_fb = regs.zeta_enable != 0; |
| 391 | 391 | ||
| 392 | // Always enable the depth write when clearing the depth buffer. The depth write mask is | 392 | // Always enable the depth write when clearing the depth buffer. The depth write mask is |
| 393 | // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true. | 393 | // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true. |
| @@ -413,11 +413,13 @@ void RasterizerOpenGL::Clear() { | |||
| 413 | glClear(clear_mask); | 413 | glClear(clear_mask); |
| 414 | 414 | ||
| 415 | // Mark framebuffer surfaces as dirty | 415 | // Mark framebuffer surfaces as dirty |
| 416 | if (dirty_color_surface != nullptr) { | 416 | if (Settings::values.use_accurate_framebuffers) { |
| 417 | res_cache.MarkSurfaceAsDirty(dirty_color_surface); | 417 | if (dirty_color_surface != nullptr) { |
| 418 | } | 418 | res_cache.FlushSurface(dirty_color_surface); |
| 419 | if (dirty_depth_surface != nullptr) { | 419 | } |
| 420 | res_cache.MarkSurfaceAsDirty(dirty_depth_surface); | 420 | if (dirty_depth_surface != nullptr) { |
| 421 | res_cache.FlushSurface(dirty_depth_surface); | ||
| 422 | } | ||
| 421 | } | 423 | } |
| 422 | } | 424 | } |
| 423 | 425 | ||
| @@ -431,7 +433,7 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 431 | ScopeAcquireGLContext acquire_context; | 433 | ScopeAcquireGLContext acquire_context; |
| 432 | 434 | ||
| 433 | auto [dirty_color_surface, dirty_depth_surface] = | 435 | auto [dirty_color_surface, dirty_depth_surface] = |
| 434 | ConfigureFramebuffers(true, regs.zeta.Address() != 0); | 436 | ConfigureFramebuffers(true, regs.zeta.Address() != 0 && regs.zeta_enable != 0); |
| 435 | 437 | ||
| 436 | SyncDepthTestState(); | 438 | SyncDepthTestState(); |
| 437 | SyncBlendState(); | 439 | SyncBlendState(); |
| @@ -520,11 +522,13 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 520 | state.Apply(); | 522 | state.Apply(); |
| 521 | 523 | ||
| 522 | // Mark framebuffer surfaces as dirty | 524 | // Mark framebuffer surfaces as dirty |
| 523 | if (dirty_color_surface != nullptr) { | 525 | if (Settings::values.use_accurate_framebuffers) { |
| 524 | res_cache.MarkSurfaceAsDirty(dirty_color_surface); | 526 | if (dirty_color_surface != nullptr) { |
| 525 | } | 527 | res_cache.FlushSurface(dirty_color_surface); |
| 526 | if (dirty_depth_surface != nullptr) { | 528 | } |
| 527 | res_cache.MarkSurfaceAsDirty(dirty_depth_surface); | 529 | if (dirty_depth_surface != nullptr) { |
| 530 | res_cache.FlushSurface(dirty_depth_surface); | ||
| 531 | } | ||
| 528 | } | 532 | } |
| 529 | } | 533 | } |
| 530 | 534 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 2c43982b0..28f0bc379 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -65,9 +65,9 @@ struct FormatTuple { | |||
| 65 | return params; | 65 | return params; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | /*static*/ SurfaceParams SurfaceParams::CreateForDepthBuffer( | 68 | /*static*/ SurfaceParams SurfaceParams::CreateForDepthBuffer(u32 zeta_width, u32 zeta_height, |
| 69 | const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config, Tegra::GPUVAddr zeta_address, | 69 | Tegra::GPUVAddr zeta_address, |
| 70 | Tegra::DepthFormat format) { | 70 | Tegra::DepthFormat format) { |
| 71 | 71 | ||
| 72 | SurfaceParams params{}; | 72 | SurfaceParams params{}; |
| 73 | params.addr = zeta_address; | 73 | params.addr = zeta_address; |
| @@ -77,9 +77,9 @@ struct FormatTuple { | |||
| 77 | params.component_type = ComponentTypeFromDepthFormat(format); | 77 | params.component_type = ComponentTypeFromDepthFormat(format); |
| 78 | params.type = GetFormatType(params.pixel_format); | 78 | params.type = GetFormatType(params.pixel_format); |
| 79 | params.size_in_bytes = params.SizeInBytes(); | 79 | params.size_in_bytes = params.SizeInBytes(); |
| 80 | params.width = config.width; | 80 | params.width = zeta_width; |
| 81 | params.height = config.height; | 81 | params.height = zeta_height; |
| 82 | params.unaligned_height = config.height; | 82 | params.unaligned_height = zeta_height; |
| 83 | params.size_in_bytes = params.SizeInBytes(); | 83 | params.size_in_bytes = params.SizeInBytes(); |
| 84 | return params; | 84 | return params; |
| 85 | } | 85 | } |
| @@ -254,6 +254,60 @@ static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tup | |||
| 254 | cur_state.Apply(); | 254 | cur_state.Apply(); |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex, | ||
| 258 | const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type, | ||
| 259 | GLuint read_fb_handle, GLuint draw_fb_handle) { | ||
| 260 | OpenGLState prev_state{OpenGLState::GetCurState()}; | ||
| 261 | SCOPE_EXIT({ prev_state.Apply(); }); | ||
| 262 | |||
| 263 | OpenGLState state; | ||
| 264 | state.draw.read_framebuffer = read_fb_handle; | ||
| 265 | state.draw.draw_framebuffer = draw_fb_handle; | ||
| 266 | state.Apply(); | ||
| 267 | |||
| 268 | u32 buffers{}; | ||
| 269 | |||
| 270 | if (type == SurfaceType::ColorTexture) { | ||
| 271 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex, | ||
| 272 | 0); | ||
| 273 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | ||
| 274 | 0); | ||
| 275 | |||
| 276 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_tex, | ||
| 277 | 0); | ||
| 278 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | ||
| 279 | 0); | ||
| 280 | |||
| 281 | buffers = GL_COLOR_BUFFER_BIT; | ||
| 282 | } else if (type == SurfaceType::Depth) { | ||
| 283 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | ||
| 284 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, src_tex, 0); | ||
| 285 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | ||
| 286 | |||
| 287 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | ||
| 288 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, dst_tex, 0); | ||
| 289 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | ||
| 290 | |||
| 291 | buffers = GL_DEPTH_BUFFER_BIT; | ||
| 292 | } else if (type == SurfaceType::DepthStencil) { | ||
| 293 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | ||
| 294 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 295 | src_tex, 0); | ||
| 296 | |||
| 297 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | ||
| 298 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 299 | dst_tex, 0); | ||
| 300 | |||
| 301 | buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; | ||
| 302 | } | ||
| 303 | |||
| 304 | glBlitFramebuffer(src_rect.left, src_rect.bottom, src_rect.right, src_rect.top, dst_rect.left, | ||
| 305 | dst_rect.bottom, dst_rect.right, dst_rect.top, buffers, | ||
| 306 | buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); | ||
| 307 | |||
| 308 | return true; | ||
| 309 | } | ||
| 310 | |||
| 257 | CachedSurface::CachedSurface(const SurfaceParams& params) : params(params) { | 311 | CachedSurface::CachedSurface(const SurfaceParams& params) : params(params) { |
| 258 | texture.Create(); | 312 | texture.Create(); |
| 259 | const auto& rect{params.GetRect()}; | 313 | const auto& rect{params.GetRect()}; |
| @@ -519,8 +573,8 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | |||
| 519 | } | 573 | } |
| 520 | 574 | ||
| 521 | if (using_depth_fb) { | 575 | if (using_depth_fb) { |
| 522 | depth_params = | 576 | depth_params = SurfaceParams::CreateForDepthBuffer(regs.zeta_width, regs.zeta_height, |
| 523 | SurfaceParams::CreateForDepthBuffer(regs.rt[0], regs.zeta.Address(), regs.zeta.format); | 577 | regs.zeta.Address(), regs.zeta.format); |
| 524 | } | 578 | } |
| 525 | 579 | ||
| 526 | MathUtil::Rectangle<u32> color_rect{}; | 580 | MathUtil::Rectangle<u32> color_rect{}; |
| @@ -565,17 +619,9 @@ void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) { | |||
| 565 | surface->UploadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); | 619 | surface->UploadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); |
| 566 | } | 620 | } |
| 567 | 621 | ||
| 568 | void RasterizerCacheOpenGL::MarkSurfaceAsDirty(const Surface& surface) { | 622 | void RasterizerCacheOpenGL::FlushSurface(const Surface& surface) { |
| 569 | if (Settings::values.use_accurate_framebuffers) { | 623 | surface->DownloadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); |
| 570 | // If enabled, always flush dirty surfaces | 624 | surface->FlushGLBuffer(); |
| 571 | surface->DownloadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); | ||
| 572 | surface->FlushGLBuffer(); | ||
| 573 | } else { | ||
| 574 | // Otherwise, don't mark surfaces that we write to as cached, because the resulting loads | ||
| 575 | // and flushes are very slow and do not seem to improve accuracy | ||
| 576 | const auto& params{surface->GetSurfaceParams()}; | ||
| 577 | Memory::RasterizerMarkRegionCached(params.addr, params.size_in_bytes, false); | ||
| 578 | } | ||
| 579 | } | 625 | } |
| 580 | 626 | ||
| 581 | Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { | 627 | Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { |
| @@ -588,25 +634,53 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { | |||
| 588 | if (gpu.memory_manager->GpuToCpuAddress(params.addr) == boost::none) | 634 | if (gpu.memory_manager->GpuToCpuAddress(params.addr) == boost::none) |
| 589 | return {}; | 635 | return {}; |
| 590 | 636 | ||
| 591 | // Check for an exact match in existing surfaces | 637 | // Look up surface in the cache based on address |
| 592 | const auto& surface_key{SurfaceKey::Create(params)}; | 638 | const auto& search{surface_cache.find(params.addr)}; |
| 593 | const auto& search{surface_cache.find(surface_key)}; | ||
| 594 | Surface surface; | 639 | Surface surface; |
| 595 | if (search != surface_cache.end()) { | 640 | if (search != surface_cache.end()) { |
| 596 | surface = search->second; | 641 | surface = search->second; |
| 597 | if (Settings::values.use_accurate_framebuffers) { | 642 | if (Settings::values.use_accurate_framebuffers) { |
| 598 | // Reload the surface from Switch memory | 643 | // If use_accurate_framebuffers is enabled, always load from memory |
| 599 | LoadSurface(surface); | 644 | FlushSurface(surface); |
| 645 | UnregisterSurface(surface); | ||
| 646 | } else if (surface->GetSurfaceParams() != params) { | ||
| 647 | // If surface parameters changed, recreate the surface from the old one | ||
| 648 | return RecreateSurface(surface, params); | ||
| 649 | } else { | ||
| 650 | // Use the cached surface as-is | ||
| 651 | return surface; | ||
| 600 | } | 652 | } |
| 601 | } else { | ||
| 602 | surface = std::make_shared<CachedSurface>(params); | ||
| 603 | RegisterSurface(surface); | ||
| 604 | LoadSurface(surface); | ||
| 605 | } | 653 | } |
| 606 | 654 | ||
| 655 | // No surface found - create a new one | ||
| 656 | surface = std::make_shared<CachedSurface>(params); | ||
| 657 | RegisterSurface(surface); | ||
| 658 | LoadSurface(surface); | ||
| 659 | |||
| 607 | return surface; | 660 | return surface; |
| 608 | } | 661 | } |
| 609 | 662 | ||
| 663 | Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface, | ||
| 664 | const SurfaceParams& new_params) { | ||
| 665 | // Verify surface is compatible for blitting | ||
| 666 | const auto& params{surface->GetSurfaceParams()}; | ||
| 667 | ASSERT(params.type == new_params.type); | ||
| 668 | ASSERT(params.pixel_format == new_params.pixel_format); | ||
| 669 | ASSERT(params.component_type == new_params.component_type); | ||
| 670 | |||
| 671 | // Create a new surface with the new parameters, and blit the previous surface to it | ||
| 672 | Surface new_surface{std::make_shared<CachedSurface>(new_params)}; | ||
| 673 | BlitTextures(surface->Texture().handle, params.GetRect(), new_surface->Texture().handle, | ||
| 674 | new_surface->GetSurfaceParams().GetRect(), params.type, read_framebuffer.handle, | ||
| 675 | draw_framebuffer.handle); | ||
| 676 | |||
| 677 | // Update cache accordingly | ||
| 678 | UnregisterSurface(surface); | ||
| 679 | RegisterSurface(new_surface); | ||
| 680 | |||
| 681 | return new_surface; | ||
| 682 | } | ||
| 683 | |||
| 610 | Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr cpu_addr) const { | 684 | Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr cpu_addr) const { |
| 611 | // Tries to find the GPU address of a framebuffer based on the CPU address. This is because | 685 | // Tries to find the GPU address of a framebuffer based on the CPU address. This is because |
| 612 | // final output framebuffers are specified by CPU address, but internally our GPU cache uses | 686 | // final output framebuffers are specified by CPU address, but internally our GPU cache uses |
| @@ -652,22 +726,20 @@ void RasterizerCacheOpenGL::InvalidateRegion(Tegra::GPUVAddr addr, size_t size) | |||
| 652 | 726 | ||
| 653 | void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) { | 727 | void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) { |
| 654 | const auto& params{surface->GetSurfaceParams()}; | 728 | const auto& params{surface->GetSurfaceParams()}; |
| 655 | const auto& surface_key{SurfaceKey::Create(params)}; | 729 | const auto& search{surface_cache.find(params.addr)}; |
| 656 | const auto& search{surface_cache.find(surface_key)}; | ||
| 657 | 730 | ||
| 658 | if (search != surface_cache.end()) { | 731 | if (search != surface_cache.end()) { |
| 659 | // Registered already | 732 | // Registered already |
| 660 | return; | 733 | return; |
| 661 | } | 734 | } |
| 662 | 735 | ||
| 663 | surface_cache[surface_key] = surface; | 736 | surface_cache[params.addr] = surface; |
| 664 | UpdatePagesCachedCount(params.addr, params.size_in_bytes, 1); | 737 | UpdatePagesCachedCount(params.addr, params.size_in_bytes, 1); |
| 665 | } | 738 | } |
| 666 | 739 | ||
| 667 | void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) { | 740 | void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) { |
| 668 | const auto& params{surface->GetSurfaceParams()}; | 741 | const auto& params{surface->GetSurfaceParams()}; |
| 669 | const auto& surface_key{SurfaceKey::Create(params)}; | 742 | const auto& search{surface_cache.find(params.addr)}; |
| 670 | const auto& search{surface_cache.find(surface_key)}; | ||
| 671 | 743 | ||
| 672 | if (search == surface_cache.end()) { | 744 | if (search == surface_cache.end()) { |
| 673 | // Unregistered already | 745 | // Unregistered already |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 718c45ce1..b084c4db4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include <vector> | 10 | #include <vector> |
| 11 | #include <boost/icl/interval_map.hpp> | 11 | #include <boost/icl/interval_map.hpp> |
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "common/hash.h" | ||
| 14 | #include "common/math_util.h" | 13 | #include "common/math_util.h" |
| 15 | #include "video_core/engines/maxwell_3d.h" | 14 | #include "video_core/engines/maxwell_3d.h" |
| 16 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 15 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| @@ -137,6 +136,7 @@ struct SurfaceParams { | |||
| 137 | ASSERT(static_cast<size_t>(format) < bpp_table.size()); | 136 | ASSERT(static_cast<size_t>(format) < bpp_table.size()); |
| 138 | return bpp_table[static_cast<size_t>(format)]; | 137 | return bpp_table[static_cast<size_t>(format)]; |
| 139 | } | 138 | } |
| 139 | |||
| 140 | u32 GetFormatBpp() const { | 140 | u32 GetFormatBpp() const { |
| 141 | return GetFormatBpp(pixel_format); | 141 | return GetFormatBpp(pixel_format); |
| 142 | } | 142 | } |
| @@ -365,9 +365,21 @@ struct SurfaceParams { | |||
| 365 | const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config); | 365 | const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config); |
| 366 | 366 | ||
| 367 | /// Creates SurfaceParams for a depth buffer configuration | 367 | /// Creates SurfaceParams for a depth buffer configuration |
| 368 | static SurfaceParams CreateForDepthBuffer( | 368 | static SurfaceParams CreateForDepthBuffer(u32 zeta_width, u32 zeta_height, |
| 369 | const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config, | 369 | Tegra::GPUVAddr zeta_address, |
| 370 | Tegra::GPUVAddr zeta_address, Tegra::DepthFormat format); | 370 | Tegra::DepthFormat format); |
| 371 | |||
| 372 | bool operator==(const SurfaceParams& other) const { | ||
| 373 | return std::tie(addr, is_tiled, block_height, pixel_format, component_type, type, width, | ||
| 374 | height, unaligned_height, size_in_bytes) == | ||
| 375 | std::tie(other.addr, other.is_tiled, other.block_height, other.pixel_format, | ||
| 376 | other.component_type, other.type, other.width, other.height, | ||
| 377 | other.unaligned_height, other.size_in_bytes); | ||
| 378 | } | ||
| 379 | |||
| 380 | bool operator!=(const SurfaceParams& other) const { | ||
| 381 | return !operator==(other); | ||
| 382 | } | ||
| 371 | 383 | ||
| 372 | Tegra::GPUVAddr addr; | 384 | Tegra::GPUVAddr addr; |
| 373 | bool is_tiled; | 385 | bool is_tiled; |
| @@ -381,24 +393,6 @@ struct SurfaceParams { | |||
| 381 | size_t size_in_bytes; | 393 | size_t size_in_bytes; |
| 382 | }; | 394 | }; |
| 383 | 395 | ||
| 384 | /// Hashable variation of SurfaceParams, used for a key in the surface cache | ||
| 385 | struct SurfaceKey : Common::HashableStruct<SurfaceParams> { | ||
| 386 | static SurfaceKey Create(const SurfaceParams& params) { | ||
| 387 | SurfaceKey res; | ||
| 388 | res.state = params; | ||
| 389 | return res; | ||
| 390 | } | ||
| 391 | }; | ||
| 392 | |||
| 393 | namespace std { | ||
| 394 | template <> | ||
| 395 | struct hash<SurfaceKey> { | ||
| 396 | size_t operator()(const SurfaceKey& k) const { | ||
| 397 | return k.Hash(); | ||
| 398 | } | ||
| 399 | }; | ||
| 400 | } // namespace std | ||
| 401 | |||
| 402 | class CachedSurface final { | 396 | class CachedSurface final { |
| 403 | public: | 397 | public: |
| 404 | CachedSurface(const SurfaceParams& params); | 398 | CachedSurface(const SurfaceParams& params); |
| @@ -444,8 +438,8 @@ public: | |||
| 444 | SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, | 438 | SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, |
| 445 | const MathUtil::Rectangle<s32>& viewport); | 439 | const MathUtil::Rectangle<s32>& viewport); |
| 446 | 440 | ||
| 447 | /// Marks the specified surface as "dirty", in that it is out of sync with Switch memory | 441 | /// Flushes the surface to Switch memory |
| 448 | void MarkSurfaceAsDirty(const Surface& surface); | 442 | void FlushSurface(const Surface& surface); |
| 449 | 443 | ||
| 450 | /// Tries to find a framebuffer GPU address based on the provided CPU address | 444 | /// Tries to find a framebuffer GPU address based on the provided CPU address |
| 451 | Surface TryFindFramebufferSurface(VAddr cpu_addr) const; | 445 | Surface TryFindFramebufferSurface(VAddr cpu_addr) const; |
| @@ -460,6 +454,9 @@ private: | |||
| 460 | void LoadSurface(const Surface& surface); | 454 | void LoadSurface(const Surface& surface); |
| 461 | Surface GetSurface(const SurfaceParams& params); | 455 | Surface GetSurface(const SurfaceParams& params); |
| 462 | 456 | ||
| 457 | /// Recreates a surface with new parameters | ||
| 458 | Surface RecreateSurface(const Surface& surface, const SurfaceParams& new_params); | ||
| 459 | |||
| 463 | /// Register surface into the cache | 460 | /// Register surface into the cache |
| 464 | void RegisterSurface(const Surface& surface); | 461 | void RegisterSurface(const Surface& surface); |
| 465 | 462 | ||
| @@ -469,7 +466,7 @@ private: | |||
| 469 | /// Increase/decrease the number of surface in pages touching the specified region | 466 | /// Increase/decrease the number of surface in pages touching the specified region |
| 470 | void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta); | 467 | void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta); |
| 471 | 468 | ||
| 472 | std::unordered_map<SurfaceKey, Surface> surface_cache; | 469 | std::unordered_map<Tegra::GPUVAddr, Surface> surface_cache; |
| 473 | PageMap cached_pages; | 470 | PageMap cached_pages; |
| 474 | 471 | ||
| 475 | OGLFramebuffer read_framebuffer; | 472 | OGLFramebuffer read_framebuffer; |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index b48d30466..f47fd217d 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -191,48 +191,21 @@ public: | |||
| 191 | UnsignedInteger, | 191 | UnsignedInteger, |
| 192 | }; | 192 | }; |
| 193 | 193 | ||
| 194 | GLSLRegister(size_t index, ShaderWriter& shader, const std::string& suffix) | 194 | GLSLRegister(size_t index, const std::string& suffix) : index{index}, suffix{suffix} {} |
| 195 | : index{index}, shader{shader}, suffix{suffix} {} | ||
| 196 | 195 | ||
| 197 | /// Gets the GLSL type string for a register | 196 | /// Gets the GLSL type string for a register |
| 198 | static std::string GetTypeString(Type type) { | 197 | static std::string GetTypeString() { |
| 199 | switch (type) { | 198 | return "float"; |
| 200 | case Type::Float: | ||
| 201 | return "float"; | ||
| 202 | case Type::Integer: | ||
| 203 | return "int"; | ||
| 204 | case Type::UnsignedInteger: | ||
| 205 | return "uint"; | ||
| 206 | } | ||
| 207 | |||
| 208 | UNREACHABLE(); | ||
| 209 | return {}; | ||
| 210 | } | 199 | } |
| 211 | 200 | ||
| 212 | /// Gets the GLSL register prefix string, used for declarations and referencing | 201 | /// Gets the GLSL register prefix string, used for declarations and referencing |
| 213 | static std::string GetPrefixString(Type type) { | 202 | static std::string GetPrefixString() { |
| 214 | return "reg_" + GetTypeString(type) + '_'; | 203 | return "reg_"; |
| 215 | } | 204 | } |
| 216 | 205 | ||
| 217 | /// Returns a GLSL string representing the current state of the register | 206 | /// Returns a GLSL string representing the current state of the register |
| 218 | std::string GetActiveString() { | 207 | std::string GetString() const { |
| 219 | declr_type.insert(active_type); | 208 | return GetPrefixString() + std::to_string(index) + '_' + suffix; |
| 220 | return GetPrefixString(active_type) + std::to_string(index) + '_' + suffix; | ||
| 221 | } | ||
| 222 | |||
| 223 | /// Returns true if the active type is a float | ||
| 224 | bool IsFloat() const { | ||
| 225 | return active_type == Type::Float; | ||
| 226 | } | ||
| 227 | |||
| 228 | /// Returns true if the active type is an integer | ||
| 229 | bool IsInteger() const { | ||
| 230 | return active_type == Type::Integer; | ||
| 231 | } | ||
| 232 | |||
| 233 | /// Returns the current active type of the register | ||
| 234 | Type GetActiveType() const { | ||
| 235 | return active_type; | ||
| 236 | } | 209 | } |
| 237 | 210 | ||
| 238 | /// Returns the index of the register | 211 | /// Returns the index of the register |
| @@ -240,18 +213,8 @@ public: | |||
| 240 | return index; | 213 | return index; |
| 241 | } | 214 | } |
| 242 | 215 | ||
| 243 | /// Returns a set of the declared types of the register | ||
| 244 | const std::set<Type>& DeclaredTypes() const { | ||
| 245 | return declr_type; | ||
| 246 | } | ||
| 247 | |||
| 248 | private: | 216 | private: |
| 249 | const size_t index; | 217 | const size_t index; |
| 250 | const std::string float_str; | ||
| 251 | const std::string integer_str; | ||
| 252 | ShaderWriter& shader; | ||
| 253 | Type active_type{Type::Float}; | ||
| 254 | std::set<Type> declr_type; | ||
| 255 | const std::string& suffix; | 218 | const std::string& suffix; |
| 256 | }; | 219 | }; |
| 257 | 220 | ||
| @@ -297,7 +260,6 @@ public: | |||
| 297 | * @returns GLSL string corresponding to the register as a float. | 260 | * @returns GLSL string corresponding to the register as a float. |
| 298 | */ | 261 | */ |
| 299 | std::string GetRegisterAsFloat(const Register& reg, unsigned elem = 0) { | 262 | std::string GetRegisterAsFloat(const Register& reg, unsigned elem = 0) { |
| 300 | ASSERT(regs[reg].IsFloat()); | ||
| 301 | return GetRegister(reg, elem); | 263 | return GetRegister(reg, elem); |
| 302 | } | 264 | } |
| 303 | 265 | ||
| @@ -311,12 +273,8 @@ public: | |||
| 311 | */ | 273 | */ |
| 312 | std::string GetRegisterAsInteger(const Register& reg, unsigned elem = 0, bool is_signed = true, | 274 | std::string GetRegisterAsInteger(const Register& reg, unsigned elem = 0, bool is_signed = true, |
| 313 | Register::Size size = Register::Size::Word) { | 275 | Register::Size size = Register::Size::Word) { |
| 314 | const std::string func = GetGLSLConversionFunc( | 276 | const std::string func{is_signed ? "floatBitsToInt" : "floatBitsToUint"}; |
| 315 | GLSLRegister::Type::Float, | 277 | const std::string value{func + '(' + GetRegister(reg, elem) + ')'}; |
| 316 | is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger); | ||
| 317 | |||
| 318 | std::string value = func + '(' + GetRegister(reg, elem) + ')'; | ||
| 319 | |||
| 320 | return ConvertIntegerSize(value, size); | 278 | return ConvertIntegerSize(value, size); |
| 321 | } | 279 | } |
| 322 | 280 | ||
| @@ -355,9 +313,7 @@ public: | |||
| 355 | u64 dest_elem = 0, Register::Size size = Register::Size::Word) { | 313 | u64 dest_elem = 0, Register::Size size = Register::Size::Word) { |
| 356 | ASSERT_MSG(!is_saturated, "Unimplemented"); | 314 | ASSERT_MSG(!is_saturated, "Unimplemented"); |
| 357 | 315 | ||
| 358 | const std::string func = GetGLSLConversionFunc( | 316 | const std::string func{is_signed ? "intBitsToFloat" : "uintBitsToFloat"}; |
| 359 | is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger, | ||
| 360 | GLSLRegister::Type::Float); | ||
| 361 | 317 | ||
| 362 | SetRegister(reg, elem, func + '(' + ConvertIntegerSize(value, size) + ')', | 318 | SetRegister(reg, elem, func + '(' + ConvertIntegerSize(value, size) + ')', |
| 363 | dest_num_components, value_num_components, dest_elem); | 319 | dest_num_components, value_num_components, dest_elem); |
| @@ -373,14 +329,7 @@ public: | |||
| 373 | void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute) { | 329 | void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute) { |
| 374 | std::string dest = GetRegisterAsFloat(reg); | 330 | std::string dest = GetRegisterAsFloat(reg); |
| 375 | std::string src = GetInputAttribute(attribute) + GetSwizzle(elem); | 331 | std::string src = GetInputAttribute(attribute) + GetSwizzle(elem); |
| 376 | 332 | shader.AddLine(dest + " = " + src + ';'); | |
| 377 | if (regs[reg].IsFloat()) { | ||
| 378 | shader.AddLine(dest + " = " + src + ';'); | ||
| 379 | } else if (regs[reg].IsInteger()) { | ||
| 380 | shader.AddLine(dest + " = floatBitsToInt(" + src + ");"); | ||
| 381 | } else { | ||
| 382 | UNREACHABLE(); | ||
| 383 | } | ||
| 384 | } | 333 | } |
| 385 | 334 | ||
| 386 | /** | 335 | /** |
| @@ -393,7 +342,6 @@ public: | |||
| 393 | void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) { | 342 | void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) { |
| 394 | std::string dest = GetOutputAttribute(attribute) + GetSwizzle(elem); | 343 | std::string dest = GetOutputAttribute(attribute) + GetSwizzle(elem); |
| 395 | std::string src = GetRegisterAsFloat(reg); | 344 | std::string src = GetRegisterAsFloat(reg); |
| 396 | ASSERT_MSG(regs[reg].IsFloat(), "Output attributes must be set to a float"); | ||
| 397 | shader.AddLine(dest + " = " + src + ';'); | 345 | shader.AddLine(dest + " = " + src + ';'); |
| 398 | } | 346 | } |
| 399 | 347 | ||
| @@ -434,11 +382,8 @@ public: | |||
| 434 | /// Add declarations for registers | 382 | /// Add declarations for registers |
| 435 | void GenerateDeclarations(const std::string& suffix) { | 383 | void GenerateDeclarations(const std::string& suffix) { |
| 436 | for (const auto& reg : regs) { | 384 | for (const auto& reg : regs) { |
| 437 | for (const auto& type : reg.DeclaredTypes()) { | 385 | declarations.AddLine(GLSLRegister::GetTypeString() + ' ' + reg.GetPrefixString() + |
| 438 | declarations.AddLine(GLSLRegister::GetTypeString(type) + ' ' + | 386 | std::to_string(reg.GetIndex()) + '_' + suffix + " = 0;"); |
| 439 | reg.GetPrefixString(type) + std::to_string(reg.GetIndex()) + | ||
| 440 | '_' + suffix + " = 0;"); | ||
| 441 | } | ||
| 442 | } | 387 | } |
| 443 | declarations.AddNewLine(); | 388 | declarations.AddNewLine(); |
| 444 | 389 | ||
| @@ -516,21 +461,13 @@ public: | |||
| 516 | } | 461 | } |
| 517 | 462 | ||
| 518 | private: | 463 | private: |
| 519 | /// Build GLSL conversion function, e.g. floatBitsToInt, intBitsToFloat, etc. | ||
| 520 | std::string GetGLSLConversionFunc(GLSLRegister::Type src, GLSLRegister::Type dest) const { | ||
| 521 | const std::string src_type = GLSLRegister::GetTypeString(src); | ||
| 522 | std::string dest_type = GLSLRegister::GetTypeString(dest); | ||
| 523 | dest_type[0] = toupper(dest_type[0]); | ||
| 524 | return src_type + "BitsTo" + dest_type; | ||
| 525 | } | ||
| 526 | |||
| 527 | /// Generates code representing a temporary (GPR) register. | 464 | /// Generates code representing a temporary (GPR) register. |
| 528 | std::string GetRegister(const Register& reg, unsigned elem) { | 465 | std::string GetRegister(const Register& reg, unsigned elem) { |
| 529 | if (reg == Register::ZeroIndex) { | 466 | if (reg == Register::ZeroIndex) { |
| 530 | return "0"; | 467 | return "0"; |
| 531 | } | 468 | } |
| 532 | 469 | ||
| 533 | return regs[reg.GetSwizzledIndex(elem)].GetActiveString(); | 470 | return regs[reg.GetSwizzledIndex(elem)].GetString(); |
| 534 | } | 471 | } |
| 535 | 472 | ||
| 536 | /** | 473 | /** |
| @@ -560,7 +497,7 @@ private: | |||
| 560 | /// Build the GLSL register list. | 497 | /// Build the GLSL register list. |
| 561 | void BuildRegisterList() { | 498 | void BuildRegisterList() { |
| 562 | for (size_t index = 0; index < Register::NumRegisters; ++index) { | 499 | for (size_t index = 0; index < Register::NumRegisters; ++index) { |
| 563 | regs.emplace_back(index, shader, suffix); | 500 | regs.emplace_back(index, suffix); |
| 564 | } | 501 | } |
| 565 | } | 502 | } |
| 566 | 503 | ||
| @@ -1139,6 +1076,15 @@ private: | |||
| 1139 | "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1); | 1076 | "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1); |
| 1140 | break; | 1077 | break; |
| 1141 | } | 1078 | } |
| 1079 | case OpCode::Id::SEL_C: | ||
| 1080 | case OpCode::Id::SEL_R: | ||
| 1081 | case OpCode::Id::SEL_IMM: { | ||
| 1082 | std::string condition = | ||
| 1083 | GetPredicateCondition(instr.sel.pred, instr.sel.neg_pred != 0); | ||
| 1084 | regs.SetRegisterToInteger(instr.gpr0, true, 0, | ||
| 1085 | '(' + condition + ") ? " + op_a + " : " + op_b, 1, 1); | ||
| 1086 | break; | ||
| 1087 | } | ||
| 1142 | case OpCode::Id::LOP_C: | 1088 | case OpCode::Id::LOP_C: |
| 1143 | case OpCode::Id::LOP_R: | 1089 | case OpCode::Id::LOP_R: |
| 1144 | case OpCode::Id::LOP_IMM: { | 1090 | case OpCode::Id::LOP_IMM: { |
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index e1ca0e77b..99e6634a1 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -394,7 +394,7 @@ void GameList::RefreshGameDirectory() { | |||
| 394 | } | 394 | } |
| 395 | 395 | ||
| 396 | void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) { | 396 | void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) { |
| 397 | const auto callback = [this, recursion](unsigned* num_entries_out, const std::string& directory, | 397 | const auto callback = [this, recursion](u64* num_entries_out, const std::string& directory, |
| 398 | const std::string& virtual_name) -> bool { | 398 | const std::string& virtual_name) -> bool { |
| 399 | std::string physical_name = directory + DIR_SEP + virtual_name; | 399 | std::string physical_name = directory + DIR_SEP + virtual_name; |
| 400 | 400 | ||