diff options
31 files changed, 765 insertions, 78 deletions
diff --git a/.ci/scripts/merge/apply-patches-by-label-private.py b/.ci/scripts/merge/apply-patches-by-label-private.py index fe0acd510..16b45043e 100644 --- a/.ci/scripts/merge/apply-patches-by-label-private.py +++ b/.ci/scripts/merge/apply-patches-by-label-private.py | |||
| @@ -25,7 +25,7 @@ def check_individual(repo_id, pr_id): | |||
| 25 | 25 | ||
| 26 | def merge_pr(pn, ref): | 26 | def merge_pr(pn, ref): |
| 27 | print("Matched PR# %s" % pn) | 27 | print("Matched PR# %s" % pn) |
| 28 | print(subprocess.check_output(["git", "fetch", "https://%sdev.azure.com/%s/_git/%s" % (user, org, repo), ref, "-f"])) | 28 | print(subprocess.check_output(["git", "fetch", "https://%sdev.azure.com/%s/_git/%s" % (user, org, repo), ref, "-f", "--no-recurse-submodules"])) |
| 29 | print(subprocess.check_output(["git", "merge", "--squash", 'origin/' + ref.replace('refs/heads/','')])) | 29 | print(subprocess.check_output(["git", "merge", "--squash", 'origin/' + ref.replace('refs/heads/','')])) |
| 30 | print(subprocess.check_output(["git", "commit", "-m\"Merge %s PR %s\"" % (tagline, pn)])) | 30 | print(subprocess.check_output(["git", "commit", "-m\"Merge %s PR %s\"" % (tagline, pn)])) |
| 31 | 31 | ||
diff --git a/.ci/scripts/merge/apply-patches-by-label.py b/.ci/scripts/merge/apply-patches-by-label.py index b2e430ac7..c288a70a1 100644 --- a/.ci/scripts/merge/apply-patches-by-label.py +++ b/.ci/scripts/merge/apply-patches-by-label.py | |||
| @@ -25,7 +25,7 @@ def do_page(page): | |||
| 25 | if (check_individual(pr["labels"])): | 25 | if (check_individual(pr["labels"])): |
| 26 | pn = pr["number"] | 26 | pn = pr["number"] |
| 27 | print("Matched PR# %s" % pn) | 27 | print("Matched PR# %s" % pn) |
| 28 | print(subprocess.check_output(["git", "fetch", "https://github.com/yuzu-emu/yuzu.git", "pull/%s/head:pr-%s" % (pn, pn), "-f"])) | 28 | print(subprocess.check_output(["git", "fetch", "https://github.com/yuzu-emu/yuzu.git", "pull/%s/head:pr-%s" % (pn, pn), "-f", "--no-recurse-submodules"])) |
| 29 | print(subprocess.check_output(["git", "merge", "--squash", "pr-%s" % pn])) | 29 | print(subprocess.check_output(["git", "merge", "--squash", "pr-%s" % pn])) |
| 30 | print(subprocess.check_output(["git", "commit", "-m\"Merge %s PR %s\"" % (tagline, pn)])) | 30 | print(subprocess.check_output(["git", "commit", "-m\"Merge %s PR %s\"" % (tagline, pn)])) |
| 31 | 31 | ||
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6044e311a..2c044c1ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -57,7 +57,7 @@ function(check_submodules_present) | |||
| 57 | string(REGEX REPLACE "path *= *" "" module ${module}) | 57 | string(REGEX REPLACE "path *= *" "" module ${module}) |
| 58 | if (NOT EXISTS "${PROJECT_SOURCE_DIR}/${module}/.git") | 58 | if (NOT EXISTS "${PROJECT_SOURCE_DIR}/${module}/.git") |
| 59 | message(FATAL_ERROR "Git submodule ${module} not found. " | 59 | message(FATAL_ERROR "Git submodule ${module} not found. " |
| 60 | "Please run: git submodule update --init --recursive") | 60 | "Please run: \ngit submodule update --init --recursive") |
| 61 | endif() | 61 | endif() |
| 62 | endforeach() | 62 | endforeach() |
| 63 | endfunction() | 63 | endfunction() |
diff --git a/src/common/bit_util.h b/src/common/bit_util.h index 64520ca4e..eef8c1c5a 100644 --- a/src/common/bit_util.h +++ b/src/common/bit_util.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <bit> | 7 | #include <bit> |
| 8 | #include <climits> | 8 | #include <climits> |
| 9 | #include <cstddef> | 9 | #include <cstddef> |
| 10 | #include <type_traits> | ||
| 10 | 11 | ||
| 11 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 12 | 13 | ||
| @@ -44,4 +45,10 @@ template <typename T> | |||
| 44 | return static_cast<u32>(log2_f + static_cast<u64>((value ^ (1ULL << log2_f)) != 0ULL)); | 45 | return static_cast<u32>(log2_f + static_cast<u64>((value ^ (1ULL << log2_f)) != 0ULL)); |
| 45 | } | 46 | } |
| 46 | 47 | ||
| 48 | template <typename T> | ||
| 49 | requires std::is_integral_v<T> | ||
| 50 | [[nodiscard]] T NextPow2(T value) { | ||
| 51 | return static_cast<T>(1ULL << ((8U * sizeof(T)) - std::countl_zero(value - 1U))); | ||
| 52 | } | ||
| 53 | |||
| 47 | } // namespace Common | 54 | } // namespace Common |
diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index 88fc5b5cc..277abc17a 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp | |||
| @@ -13,7 +13,12 @@ namespace Service::PM { | |||
| 13 | 13 | ||
| 14 | namespace { | 14 | namespace { |
| 15 | 15 | ||
| 16 | constexpr ResultCode ERROR_PROCESS_NOT_FOUND{ErrorModule::PM, 1}; | 16 | constexpr ResultCode ResultProcessNotFound{ErrorModule::PM, 1}; |
| 17 | [[maybe_unused]] constexpr ResultCode ResultAlreadyStarted{ErrorModule::PM, 2}; | ||
| 18 | [[maybe_unused]] constexpr ResultCode ResultNotTerminated{ErrorModule::PM, 3}; | ||
| 19 | [[maybe_unused]] constexpr ResultCode ResultDebugHookInUse{ErrorModule::PM, 4}; | ||
| 20 | [[maybe_unused]] constexpr ResultCode ResultApplicationRunning{ErrorModule::PM, 5}; | ||
| 21 | [[maybe_unused]] constexpr ResultCode ResultInvalidSize{ErrorModule::PM, 6}; | ||
| 17 | 22 | ||
| 18 | constexpr u64 NO_PROCESS_FOUND_PID{0}; | 23 | constexpr u64 NO_PROCESS_FOUND_PID{0}; |
| 19 | 24 | ||
| @@ -95,18 +100,18 @@ public: | |||
| 95 | private: | 100 | private: |
| 96 | void GetProcessId(Kernel::HLERequestContext& ctx) { | 101 | void GetProcessId(Kernel::HLERequestContext& ctx) { |
| 97 | IPC::RequestParser rp{ctx}; | 102 | IPC::RequestParser rp{ctx}; |
| 98 | const auto title_id = rp.PopRaw<u64>(); | 103 | const auto program_id = rp.PopRaw<u64>(); |
| 99 | 104 | ||
| 100 | LOG_DEBUG(Service_PM, "called, title_id={:016X}", title_id); | 105 | LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); |
| 101 | 106 | ||
| 102 | const auto process = | 107 | const auto process = |
| 103 | SearchProcessList(kernel.GetProcessList(), [title_id](const auto& proc) { | 108 | SearchProcessList(kernel.GetProcessList(), [program_id](const auto& proc) { |
| 104 | return proc->GetProgramID() == title_id; | 109 | return proc->GetProgramID() == program_id; |
| 105 | }); | 110 | }); |
| 106 | 111 | ||
| 107 | if (!process.has_value()) { | 112 | if (!process.has_value()) { |
| 108 | IPC::ResponseBuilder rb{ctx, 2}; | 113 | IPC::ResponseBuilder rb{ctx, 2}; |
| 109 | rb.Push(ERROR_PROCESS_NOT_FOUND); | 114 | rb.Push(ResultProcessNotFound); |
| 110 | return; | 115 | return; |
| 111 | } | 116 | } |
| 112 | 117 | ||
| @@ -128,13 +133,16 @@ public: | |||
| 128 | explicit Info(Core::System& system_, const std::vector<Kernel::KProcess*>& process_list_) | 133 | explicit Info(Core::System& system_, const std::vector<Kernel::KProcess*>& process_list_) |
| 129 | : ServiceFramework{system_, "pm:info"}, process_list{process_list_} { | 134 | : ServiceFramework{system_, "pm:info"}, process_list{process_list_} { |
| 130 | static const FunctionInfo functions[] = { | 135 | static const FunctionInfo functions[] = { |
| 131 | {0, &Info::GetTitleId, "GetTitleId"}, | 136 | {0, &Info::GetProgramId, "GetProgramId"}, |
| 137 | {65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"}, | ||
| 138 | {65001, nullptr, "AtmosphereHasLaunchedProgram"}, | ||
| 139 | {65002, nullptr, "AtmosphereGetProcessInfo"}, | ||
| 132 | }; | 140 | }; |
| 133 | RegisterHandlers(functions); | 141 | RegisterHandlers(functions); |
| 134 | } | 142 | } |
| 135 | 143 | ||
| 136 | private: | 144 | private: |
| 137 | void GetTitleId(Kernel::HLERequestContext& ctx) { | 145 | void GetProgramId(Kernel::HLERequestContext& ctx) { |
| 138 | IPC::RequestParser rp{ctx}; | 146 | IPC::RequestParser rp{ctx}; |
| 139 | const auto process_id = rp.PopRaw<u64>(); | 147 | const auto process_id = rp.PopRaw<u64>(); |
| 140 | 148 | ||
| @@ -146,7 +154,7 @@ private: | |||
| 146 | 154 | ||
| 147 | if (!process.has_value()) { | 155 | if (!process.has_value()) { |
| 148 | IPC::ResponseBuilder rb{ctx, 2}; | 156 | IPC::ResponseBuilder rb{ctx, 2}; |
| 149 | rb.Push(ERROR_PROCESS_NOT_FOUND); | 157 | rb.Push(ResultProcessNotFound); |
| 150 | return; | 158 | return; |
| 151 | } | 159 | } |
| 152 | 160 | ||
| @@ -155,6 +163,27 @@ private: | |||
| 155 | rb.Push((*process)->GetProgramID()); | 163 | rb.Push((*process)->GetProgramID()); |
| 156 | } | 164 | } |
| 157 | 165 | ||
| 166 | void AtmosphereGetProcessId(Kernel::HLERequestContext& ctx) { | ||
| 167 | IPC::RequestParser rp{ctx}; | ||
| 168 | const auto program_id = rp.PopRaw<u64>(); | ||
| 169 | |||
| 170 | LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); | ||
| 171 | |||
| 172 | const auto process = SearchProcessList(process_list, [program_id](const auto& proc) { | ||
| 173 | return proc->GetProgramID() == program_id; | ||
| 174 | }); | ||
| 175 | |||
| 176 | if (!process.has_value()) { | ||
| 177 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 178 | rb.Push(ResultProcessNotFound); | ||
| 179 | return; | ||
| 180 | } | ||
| 181 | |||
| 182 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 183 | rb.Push(ResultSuccess); | ||
| 184 | rb.Push((*process)->GetProcessID()); | ||
| 185 | } | ||
| 186 | |||
| 158 | const std::vector<Kernel::KProcess*>& process_list; | 187 | const std::vector<Kernel::KProcess*>& process_list; |
| 159 | }; | 188 | }; |
| 160 | 189 | ||
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 05e5c94f3..c89a5d693 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -83,6 +83,7 @@ enum class DepthFormat : u32 { | |||
| 83 | S8_UINT_Z24_UNORM = 0x14, | 83 | S8_UINT_Z24_UNORM = 0x14, |
| 84 | D24X8_UNORM = 0x15, | 84 | D24X8_UNORM = 0x15, |
| 85 | D24S8_UNORM = 0x16, | 85 | D24S8_UNORM = 0x16, |
| 86 | S8_UINT = 0x17, | ||
| 86 | D24C8_UNORM = 0x18, | 87 | D24C8_UNORM = 0x18, |
| 87 | D32_FLOAT_S8X24_UINT = 0x19, | 88 | D32_FLOAT_S8X24_UINT = 0x19, |
| 88 | }; | 89 | }; |
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index d779a967a..1c91999d7 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt | |||
| @@ -10,8 +10,14 @@ set(SHADER_FILES | |||
| 10 | astc_decoder.comp | 10 | astc_decoder.comp |
| 11 | block_linear_unswizzle_2d.comp | 11 | block_linear_unswizzle_2d.comp |
| 12 | block_linear_unswizzle_3d.comp | 12 | block_linear_unswizzle_3d.comp |
| 13 | convert_abgr8_to_d24s8.frag | ||
| 14 | convert_b10g11r11_to_d24s8.frag | ||
| 15 | convert_d24s8_to_abgr8.frag | ||
| 16 | convert_d24s8_to_b10g11r11.frag | ||
| 17 | convert_d24s8_to_r16g16.frag | ||
| 13 | convert_depth_to_float.frag | 18 | convert_depth_to_float.frag |
| 14 | convert_float_to_depth.frag | 19 | convert_float_to_depth.frag |
| 20 | convert_r16g16_to_d24s8.frag | ||
| 15 | full_screen_triangle.vert | 21 | full_screen_triangle.vert |
| 16 | fxaa.frag | 22 | fxaa.frag |
| 17 | fxaa.vert | 23 | fxaa.vert |
diff --git a/src/video_core/host_shaders/convert_abgr8_to_d24s8.frag b/src/video_core/host_shaders/convert_abgr8_to_d24s8.frag new file mode 100644 index 000000000..4e4ab6a26 --- /dev/null +++ b/src/video_core/host_shaders/convert_abgr8_to_d24s8.frag | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | #extension GL_ARB_shader_stencil_export : require | ||
| 7 | |||
| 8 | layout(binding = 0) uniform sampler2D color_texture; | ||
| 9 | |||
| 10 | void main() { | ||
| 11 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 12 | uvec4 color = uvec4(texelFetch(color_texture, coord, 0).rgba * (exp2(8) - 1.0f)); | ||
| 13 | uint depth_unorm = (color.r << 16) | (color.g << 8) | color.b; | ||
| 14 | |||
| 15 | gl_FragDepth = float(depth_unorm) / (exp2(24.0) - 1.0f); | ||
| 16 | gl_FragStencilRefARB = int(color.a); | ||
| 17 | } | ||
diff --git a/src/video_core/host_shaders/convert_b10g11r11_to_d24s8.frag b/src/video_core/host_shaders/convert_b10g11r11_to_d24s8.frag new file mode 100644 index 000000000..2999a84cf --- /dev/null +++ b/src/video_core/host_shaders/convert_b10g11r11_to_d24s8.frag | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | #extension GL_ARB_shader_stencil_export : require | ||
| 7 | |||
| 8 | layout(binding = 0) uniform sampler2D color_texture; | ||
| 9 | |||
| 10 | void main() { | ||
| 11 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 12 | vec4 color = texelFetch(color_texture, coord, 0).rgba; | ||
| 13 | uint depth_stencil_unorm = (uint(color.b * (exp2(10) - 1.0f)) << 22) | ||
| 14 | | (uint(color.g * (exp2(11) - 1.0f)) << 11) | ||
| 15 | | (uint(color.r * (exp2(11) - 1.0f))); | ||
| 16 | |||
| 17 | gl_FragDepth = float(depth_stencil_unorm >> 8) / (exp2(24.0) - 1.0f); | ||
| 18 | gl_FragStencilRefARB = int(depth_stencil_unorm & 0x00FF); | ||
| 19 | } | ||
diff --git a/src/video_core/host_shaders/convert_d24s8_to_abgr8.frag b/src/video_core/host_shaders/convert_d24s8_to_abgr8.frag new file mode 100644 index 000000000..ff3bf8209 --- /dev/null +++ b/src/video_core/host_shaders/convert_d24s8_to_abgr8.frag | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | |||
| 7 | layout(binding = 0) uniform sampler2D depth_tex; | ||
| 8 | layout(binding = 1) uniform isampler2D stencil_tex; | ||
| 9 | |||
| 10 | layout(location = 0) out vec4 color; | ||
| 11 | |||
| 12 | void main() { | ||
| 13 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 14 | uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f)); | ||
| 15 | uint stencil = uint(textureLod(stencil_tex, coord, 0).r); | ||
| 16 | |||
| 17 | color.r = float(depth >> 16) / (exp2(8) - 1.0); | ||
| 18 | color.g = float((depth >> 8) & 0x00FF) / (exp2(8) - 1.0); | ||
| 19 | color.b = float(depth & 0x00FF) / (exp2(8) - 1.0); | ||
| 20 | color.a = float(stencil) / (exp2(8) - 1.0); | ||
| 21 | } | ||
diff --git a/src/video_core/host_shaders/convert_d24s8_to_b10g11r11.frag b/src/video_core/host_shaders/convert_d24s8_to_b10g11r11.frag new file mode 100644 index 000000000..c743d3a13 --- /dev/null +++ b/src/video_core/host_shaders/convert_d24s8_to_b10g11r11.frag | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | |||
| 7 | layout(binding = 0) uniform sampler2D depth_tex; | ||
| 8 | layout(binding = 1) uniform isampler2D stencil_tex; | ||
| 9 | |||
| 10 | layout(location = 0) out vec4 color; | ||
| 11 | |||
| 12 | void main() { | ||
| 13 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 14 | uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f)); | ||
| 15 | uint stencil = uint(textureLod(stencil_tex, coord, 0).r); | ||
| 16 | |||
| 17 | color.b = float(depth >> 22) / (exp2(10) - 1.0); | ||
| 18 | color.g = float((depth >> 11) & 0x00FF) / (exp2(11) - 1.0); | ||
| 19 | color.r = float(depth & 0x00FF) / (exp2(11) - 1.0); | ||
| 20 | color.a = 1.0f; | ||
| 21 | } | ||
diff --git a/src/video_core/host_shaders/convert_d24s8_to_r16g16.frag b/src/video_core/host_shaders/convert_d24s8_to_r16g16.frag new file mode 100644 index 000000000..2a9443d3d --- /dev/null +++ b/src/video_core/host_shaders/convert_d24s8_to_r16g16.frag | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | |||
| 7 | layout(binding = 0) uniform sampler2D depth_tex; | ||
| 8 | layout(binding = 1) uniform isampler2D stencil_tex; | ||
| 9 | |||
| 10 | layout(location = 0) out vec4 color; | ||
| 11 | |||
| 12 | void main() { | ||
| 13 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 14 | uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f)); | ||
| 15 | uint stencil = uint(textureLod(stencil_tex, coord, 0).r); | ||
| 16 | |||
| 17 | color.r = float(depth >> 16) / (exp2(16) - 1.0); | ||
| 18 | color.g = float((depth >> 16) & 0x00FF) / (exp2(16) - 1.0); | ||
| 19 | color.b = 0.0f; | ||
| 20 | color.a = 1.0f; | ||
| 21 | } | ||
diff --git a/src/video_core/host_shaders/convert_r16g16_to_d24s8.frag b/src/video_core/host_shaders/convert_r16g16_to_d24s8.frag new file mode 100644 index 000000000..3df70575e --- /dev/null +++ b/src/video_core/host_shaders/convert_r16g16_to_d24s8.frag | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | #extension GL_ARB_shader_stencil_export : require | ||
| 7 | |||
| 8 | layout(binding = 0) uniform sampler2D color_texture; | ||
| 9 | |||
| 10 | void main() { | ||
| 11 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 12 | vec4 color = texelFetch(color_texture, coord, 0).rgba; | ||
| 13 | uint depth_stencil_unorm = (uint(color.r * (exp2(16) - 1.0f)) << 16) | ||
| 14 | | (uint(color.g * (exp2(16) - 1.0f)) << 16); | ||
| 15 | |||
| 16 | gl_FragDepth = float(depth_stencil_unorm >> 8) / (exp2(24.0) - 1.0f); | ||
| 17 | gl_FragStencilRefARB = int(depth_stencil_unorm & 0x00FF); | ||
| 18 | } | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 2f7d98d8b..14e6522f2 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include <glad/glad.h> | 10 | #include <glad/glad.h> |
| 11 | 11 | ||
| 12 | #include "common/bit_util.h" | ||
| 12 | #include "common/literals.h" | 13 | #include "common/literals.h" |
| 13 | #include "common/settings.h" | 14 | #include "common/settings.h" |
| 14 | #include "video_core/renderer_opengl/gl_device.h" | 15 | #include "video_core/renderer_opengl/gl_device.h" |
| @@ -148,6 +149,8 @@ GLenum AttachmentType(PixelFormat format) { | |||
| 148 | switch (const SurfaceType type = VideoCore::Surface::GetFormatType(format); type) { | 149 | switch (const SurfaceType type = VideoCore::Surface::GetFormatType(format); type) { |
| 149 | case SurfaceType::Depth: | 150 | case SurfaceType::Depth: |
| 150 | return GL_DEPTH_ATTACHMENT; | 151 | return GL_DEPTH_ATTACHMENT; |
| 152 | case SurfaceType::Stencil: | ||
| 153 | return GL_STENCIL_ATTACHMENT; | ||
| 151 | case SurfaceType::DepthStencil: | 154 | case SurfaceType::DepthStencil: |
| 152 | return GL_DEPTH_STENCIL_ATTACHMENT; | 155 | return GL_DEPTH_STENCIL_ATTACHMENT; |
| 153 | default: | 156 | default: |
| @@ -317,13 +320,12 @@ void AttachTexture(GLuint fbo, GLenum attachment, const ImageView* image_view) { | |||
| 317 | } | 320 | } |
| 318 | } | 321 | } |
| 319 | 322 | ||
| 320 | OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_format) { | 323 | OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_format, |
| 324 | GLsizei gl_num_levels) { | ||
| 321 | const GLenum target = ImageTarget(info); | 325 | const GLenum target = ImageTarget(info); |
| 322 | const GLsizei width = info.size.width; | 326 | const GLsizei width = info.size.width; |
| 323 | const GLsizei height = info.size.height; | 327 | const GLsizei height = info.size.height; |
| 324 | const GLsizei depth = info.size.depth; | 328 | const GLsizei depth = info.size.depth; |
| 325 | const int max_host_mip_levels = std::bit_width(info.size.width); | ||
| 326 | const GLsizei num_levels = std::min(info.resources.levels, max_host_mip_levels); | ||
| 327 | const GLsizei num_layers = info.resources.layers; | 329 | const GLsizei num_layers = info.resources.layers; |
| 328 | const GLsizei num_samples = info.num_samples; | 330 | const GLsizei num_samples = info.num_samples; |
| 329 | 331 | ||
| @@ -335,10 +337,10 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form | |||
| 335 | } | 337 | } |
| 336 | switch (target) { | 338 | switch (target) { |
| 337 | case GL_TEXTURE_1D_ARRAY: | 339 | case GL_TEXTURE_1D_ARRAY: |
| 338 | glTextureStorage2D(handle, num_levels, gl_internal_format, width, num_layers); | 340 | glTextureStorage2D(handle, gl_num_levels, gl_internal_format, width, num_layers); |
| 339 | break; | 341 | break; |
| 340 | case GL_TEXTURE_2D_ARRAY: | 342 | case GL_TEXTURE_2D_ARRAY: |
| 341 | glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, num_layers); | 343 | glTextureStorage3D(handle, gl_num_levels, gl_internal_format, width, height, num_layers); |
| 342 | break; | 344 | break; |
| 343 | case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: { | 345 | case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: { |
| 344 | // TODO: Where should 'fixedsamplelocations' come from? | 346 | // TODO: Where should 'fixedsamplelocations' come from? |
| @@ -348,10 +350,10 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form | |||
| 348 | break; | 350 | break; |
| 349 | } | 351 | } |
| 350 | case GL_TEXTURE_RECTANGLE: | 352 | case GL_TEXTURE_RECTANGLE: |
| 351 | glTextureStorage2D(handle, num_levels, gl_internal_format, width, height); | 353 | glTextureStorage2D(handle, gl_num_levels, gl_internal_format, width, height); |
| 352 | break; | 354 | break; |
| 353 | case GL_TEXTURE_3D: | 355 | case GL_TEXTURE_3D: |
| 354 | glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, depth); | 356 | glTextureStorage3D(handle, gl_num_levels, gl_internal_format, width, height, depth); |
| 355 | break; | 357 | break; |
| 356 | case GL_TEXTURE_BUFFER: | 358 | case GL_TEXTURE_BUFFER: |
| 357 | UNREACHABLE(); | 359 | UNREACHABLE(); |
| @@ -396,6 +398,7 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form | |||
| 396 | UNREACHABLE_MSG("Invalid image format={}", format); | 398 | UNREACHABLE_MSG("Invalid image format={}", format); |
| 397 | return GL_R32UI; | 399 | return GL_R32UI; |
| 398 | } | 400 | } |
| 401 | |||
| 399 | } // Anonymous namespace | 402 | } // Anonymous namespace |
| 400 | 403 | ||
| 401 | ImageBufferMap::~ImageBufferMap() { | 404 | ImageBufferMap::~ImageBufferMap() { |
| @@ -522,6 +525,12 @@ void TextureCacheRuntime::CopyImage(Image& dst_image, Image& src_image, | |||
| 522 | } | 525 | } |
| 523 | } | 526 | } |
| 524 | 527 | ||
| 528 | void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, | ||
| 529 | std::span<const VideoCommon::ImageCopy> copies) { | ||
| 530 | LOG_DEBUG(Render_OpenGL, "Converting {} to {}", src.info.format, dst.info.format); | ||
| 531 | format_conversion_pass.ConvertImage(dst, src, copies); | ||
| 532 | } | ||
| 533 | |||
| 525 | bool TextureCacheRuntime::CanImageBeCopied(const Image& dst, const Image& src) { | 534 | bool TextureCacheRuntime::CanImageBeCopied(const Image& dst, const Image& src) { |
| 526 | if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) { | 535 | if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) { |
| 527 | return false; | 536 | return false; |
| @@ -538,7 +547,7 @@ void TextureCacheRuntime::EmulateCopyImage(Image& dst, Image& src, | |||
| 538 | ASSERT(src.info.type == ImageType::e3D); | 547 | ASSERT(src.info.type == ImageType::e3D); |
| 539 | util_shaders.CopyBC4(dst, src, copies); | 548 | util_shaders.CopyBC4(dst, src, copies); |
| 540 | } else if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) { | 549 | } else if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) { |
| 541 | bgr_copy_pass.CopyBGR(dst, src, copies); | 550 | format_conversion_pass.ConvertImage(dst, src, copies); |
| 542 | } else { | 551 | } else { |
| 543 | UNREACHABLE(); | 552 | UNREACHABLE(); |
| 544 | } | 553 | } |
| @@ -686,7 +695,9 @@ Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, | |||
| 686 | gl_format = tuple.format; | 695 | gl_format = tuple.format; |
| 687 | gl_type = tuple.type; | 696 | gl_type = tuple.type; |
| 688 | } | 697 | } |
| 689 | texture = MakeImage(info, gl_internal_format); | 698 | const int max_host_mip_levels = std::bit_width(info.size.width); |
| 699 | gl_num_levels = std::min(info.resources.levels, max_host_mip_levels); | ||
| 700 | texture = MakeImage(info, gl_internal_format, gl_num_levels); | ||
| 690 | current_texture = texture.handle; | 701 | current_texture = texture.handle; |
| 691 | if (runtime->device.HasDebuggingToolAttached()) { | 702 | if (runtime->device.HasDebuggingToolAttached()) { |
| 692 | const std::string name = VideoCommon::Name(*this); | 703 | const std::string name = VideoCommon::Name(*this); |
| @@ -714,6 +725,9 @@ void Image::UploadMemory(const ImageBufferMap& map, | |||
| 714 | u32 current_image_height = std::numeric_limits<u32>::max(); | 725 | u32 current_image_height = std::numeric_limits<u32>::max(); |
| 715 | 726 | ||
| 716 | for (const VideoCommon::BufferImageCopy& copy : copies) { | 727 | for (const VideoCommon::BufferImageCopy& copy : copies) { |
| 728 | if (copy.image_subresource.base_level >= gl_num_levels) { | ||
| 729 | continue; | ||
| 730 | } | ||
| 717 | if (current_row_length != copy.buffer_row_length) { | 731 | if (current_row_length != copy.buffer_row_length) { |
| 718 | current_row_length = copy.buffer_row_length; | 732 | current_row_length = copy.buffer_row_length; |
| 719 | glPixelStorei(GL_UNPACK_ROW_LENGTH, current_row_length); | 733 | glPixelStorei(GL_UNPACK_ROW_LENGTH, current_row_length); |
| @@ -743,6 +757,9 @@ void Image::DownloadMemory(ImageBufferMap& map, | |||
| 743 | u32 current_image_height = std::numeric_limits<u32>::max(); | 757 | u32 current_image_height = std::numeric_limits<u32>::max(); |
| 744 | 758 | ||
| 745 | for (const VideoCommon::BufferImageCopy& copy : copies) { | 759 | for (const VideoCommon::BufferImageCopy& copy : copies) { |
| 760 | if (copy.image_subresource.base_level >= gl_num_levels) { | ||
| 761 | continue; | ||
| 762 | } | ||
| 746 | if (current_row_length != copy.buffer_row_length) { | 763 | if (current_row_length != copy.buffer_row_length) { |
| 747 | current_row_length = copy.buffer_row_length; | 764 | current_row_length = copy.buffer_row_length; |
| 748 | glPixelStorei(GL_PACK_ROW_LENGTH, current_row_length); | 765 | glPixelStorei(GL_PACK_ROW_LENGTH, current_row_length); |
| @@ -782,7 +799,7 @@ GLuint Image::StorageHandle() noexcept { | |||
| 782 | } | 799 | } |
| 783 | store_view.Create(); | 800 | store_view.Create(); |
| 784 | glTextureView(store_view.handle, ImageTarget(info), current_texture, GL_RGBA8, 0, | 801 | glTextureView(store_view.handle, ImageTarget(info), current_texture, GL_RGBA8, 0, |
| 785 | info.resources.levels, 0, info.resources.layers); | 802 | gl_num_levels, 0, info.resources.layers); |
| 786 | return store_view.handle; | 803 | return store_view.handle; |
| 787 | default: | 804 | default: |
| 788 | return current_texture; | 805 | return current_texture; |
| @@ -897,6 +914,8 @@ void Image::Scale(bool up_scale) { | |||
| 897 | return GL_COLOR_ATTACHMENT0; | 914 | return GL_COLOR_ATTACHMENT0; |
| 898 | case SurfaceType::Depth: | 915 | case SurfaceType::Depth: |
| 899 | return GL_DEPTH_ATTACHMENT; | 916 | return GL_DEPTH_ATTACHMENT; |
| 917 | case SurfaceType::Stencil: | ||
| 918 | return GL_STENCIL_ATTACHMENT; | ||
| 900 | case SurfaceType::DepthStencil: | 919 | case SurfaceType::DepthStencil: |
| 901 | return GL_DEPTH_STENCIL_ATTACHMENT; | 920 | return GL_DEPTH_STENCIL_ATTACHMENT; |
| 902 | default: | 921 | default: |
| @@ -910,8 +929,10 @@ void Image::Scale(bool up_scale) { | |||
| 910 | return GL_COLOR_BUFFER_BIT; | 929 | return GL_COLOR_BUFFER_BIT; |
| 911 | case SurfaceType::Depth: | 930 | case SurfaceType::Depth: |
| 912 | return GL_DEPTH_BUFFER_BIT; | 931 | return GL_DEPTH_BUFFER_BIT; |
| 932 | case SurfaceType::Stencil: | ||
| 933 | return GL_STENCIL_BUFFER_BIT; | ||
| 913 | case SurfaceType::DepthStencil: | 934 | case SurfaceType::DepthStencil: |
| 914 | return GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; | 935 | return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; |
| 915 | default: | 936 | default: |
| 916 | UNREACHABLE(); | 937 | UNREACHABLE(); |
| 917 | return GL_COLOR_BUFFER_BIT; | 938 | return GL_COLOR_BUFFER_BIT; |
| @@ -923,8 +944,10 @@ void Image::Scale(bool up_scale) { | |||
| 923 | return 0; | 944 | return 0; |
| 924 | case SurfaceType::Depth: | 945 | case SurfaceType::Depth: |
| 925 | return 1; | 946 | return 1; |
| 926 | case SurfaceType::DepthStencil: | 947 | case SurfaceType::Stencil: |
| 927 | return 2; | 948 | return 2; |
| 949 | case SurfaceType::DepthStencil: | ||
| 950 | return 3; | ||
| 928 | default: | 951 | default: |
| 929 | UNREACHABLE(); | 952 | UNREACHABLE(); |
| 930 | return 0; | 953 | return 0; |
| @@ -946,7 +969,7 @@ void Image::Scale(bool up_scale) { | |||
| 946 | auto dst_info = info; | 969 | auto dst_info = info; |
| 947 | dst_info.size.width = scaled_width; | 970 | dst_info.size.width = scaled_width; |
| 948 | dst_info.size.height = scaled_height; | 971 | dst_info.size.height = scaled_height; |
| 949 | upscaled_backup = MakeImage(dst_info, gl_internal_format); | 972 | upscaled_backup = MakeImage(dst_info, gl_internal_format, gl_num_levels); |
| 950 | } | 973 | } |
| 951 | const u32 src_width = up_scale ? original_width : scaled_width; | 974 | const u32 src_width = up_scale ? original_width : scaled_width; |
| 952 | const u32 src_height = up_scale ? original_height : scaled_height; | 975 | const u32 src_height = up_scale ? original_height : scaled_height; |
| @@ -1254,10 +1277,20 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM | |||
| 1254 | } | 1277 | } |
| 1255 | 1278 | ||
| 1256 | if (const ImageView* const image_view = depth_buffer; image_view) { | 1279 | if (const ImageView* const image_view = depth_buffer; image_view) { |
| 1257 | if (GetFormatType(image_view->format) == SurfaceType::DepthStencil) { | 1280 | switch (GetFormatType(image_view->format)) { |
| 1281 | case SurfaceType::Depth: | ||
| 1282 | buffer_bits |= GL_DEPTH_BUFFER_BIT; | ||
| 1283 | break; | ||
| 1284 | case SurfaceType::Stencil: | ||
| 1285 | buffer_bits |= GL_STENCIL_BUFFER_BIT; | ||
| 1286 | break; | ||
| 1287 | case SurfaceType::DepthStencil: | ||
| 1258 | buffer_bits |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; | 1288 | buffer_bits |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; |
| 1259 | } else { | 1289 | break; |
| 1290 | default: | ||
| 1291 | UNREACHABLE(); | ||
| 1260 | buffer_bits |= GL_DEPTH_BUFFER_BIT; | 1292 | buffer_bits |= GL_DEPTH_BUFFER_BIT; |
| 1293 | break; | ||
| 1261 | } | 1294 | } |
| 1262 | const GLenum attachment = AttachmentType(image_view->format); | 1295 | const GLenum attachment = AttachmentType(image_view->format); |
| 1263 | AttachTexture(handle, attachment, image_view); | 1296 | AttachTexture(handle, attachment, image_view); |
| @@ -1286,35 +1319,37 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM | |||
| 1286 | 1319 | ||
| 1287 | Framebuffer::~Framebuffer() = default; | 1320 | Framebuffer::~Framebuffer() = default; |
| 1288 | 1321 | ||
| 1289 | void BGRCopyPass::CopyBGR(Image& dst_image, Image& src_image, | 1322 | void FormatConversionPass::ConvertImage(Image& dst_image, Image& src_image, |
| 1290 | std::span<const VideoCommon::ImageCopy> copies) { | 1323 | std::span<const VideoCommon::ImageCopy> copies) { |
| 1291 | static constexpr VideoCommon::Offset3D zero_offset{0, 0, 0}; | 1324 | const GLenum dst_target = ImageTarget(dst_image.info); |
| 1325 | const GLenum src_target = ImageTarget(src_image.info); | ||
| 1292 | const u32 img_bpp = BytesPerBlock(src_image.info.format); | 1326 | const u32 img_bpp = BytesPerBlock(src_image.info.format); |
| 1293 | for (const ImageCopy& copy : copies) { | 1327 | for (const ImageCopy& copy : copies) { |
| 1294 | ASSERT(copy.src_offset == zero_offset); | 1328 | const auto src_origin = MakeCopyOrigin(copy.src_offset, copy.src_subresource, src_target); |
| 1295 | ASSERT(copy.dst_offset == zero_offset); | 1329 | const auto dst_origin = MakeCopyOrigin(copy.dst_offset, copy.dst_subresource, dst_target); |
| 1296 | const u32 num_src_layers = static_cast<u32>(copy.src_subresource.num_layers); | 1330 | const auto region = MakeCopyRegion(copy.extent, copy.dst_subresource, dst_target); |
| 1297 | const u32 copy_size = copy.extent.width * copy.extent.height * num_src_layers * img_bpp; | 1331 | const u32 copy_size = region.width * region.height * region.depth * img_bpp; |
| 1298 | if (bgr_pbo_size < copy_size) { | 1332 | if (pbo_size < copy_size) { |
| 1299 | bgr_pbo.Create(); | 1333 | intermediate_pbo.Create(); |
| 1300 | bgr_pbo_size = copy_size; | 1334 | pbo_size = Common::NextPow2(copy_size); |
| 1301 | glNamedBufferData(bgr_pbo.handle, bgr_pbo_size, nullptr, GL_STREAM_COPY); | 1335 | glNamedBufferData(intermediate_pbo.handle, pbo_size, nullptr, GL_STREAM_COPY); |
| 1302 | } | 1336 | } |
| 1303 | // Copy from source to PBO | 1337 | // Copy from source to PBO |
| 1304 | glPixelStorei(GL_PACK_ALIGNMENT, 1); | 1338 | glPixelStorei(GL_PACK_ALIGNMENT, 1); |
| 1305 | glPixelStorei(GL_PACK_ROW_LENGTH, copy.extent.width); | 1339 | glPixelStorei(GL_PACK_ROW_LENGTH, copy.extent.width); |
| 1306 | glBindBuffer(GL_PIXEL_PACK_BUFFER, bgr_pbo.handle); | 1340 | glBindBuffer(GL_PIXEL_PACK_BUFFER, intermediate_pbo.handle); |
| 1307 | glGetTextureSubImage(src_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height, | 1341 | glGetTextureSubImage(src_image.Handle(), src_origin.level, src_origin.x, src_origin.y, |
| 1308 | num_src_layers, src_image.GlFormat(), src_image.GlType(), | 1342 | src_origin.z, region.width, region.height, region.depth, |
| 1309 | static_cast<GLsizei>(bgr_pbo_size), nullptr); | 1343 | src_image.GlFormat(), src_image.GlType(), |
| 1344 | static_cast<GLsizei>(pbo_size), nullptr); | ||
| 1310 | 1345 | ||
| 1311 | // Copy from PBO to destination in desired GL format | 1346 | // Copy from PBO to destination in desired GL format |
| 1312 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | 1347 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
| 1313 | glPixelStorei(GL_UNPACK_ROW_LENGTH, copy.extent.width); | 1348 | glPixelStorei(GL_UNPACK_ROW_LENGTH, copy.extent.width); |
| 1314 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bgr_pbo.handle); | 1349 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, intermediate_pbo.handle); |
| 1315 | glTextureSubImage3D(dst_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height, | 1350 | glTextureSubImage3D(dst_image.Handle(), dst_origin.level, dst_origin.x, dst_origin.y, |
| 1316 | copy.dst_subresource.num_layers, dst_image.GlFormat(), | 1351 | dst_origin.z, region.width, region.height, region.depth, |
| 1317 | dst_image.GlType(), nullptr); | 1352 | dst_image.GlFormat(), dst_image.GlType(), nullptr); |
| 1318 | } | 1353 | } |
| 1319 | } | 1354 | } |
| 1320 | 1355 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 1bb762568..37d5e6a6b 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -52,17 +52,17 @@ struct FormatProperties { | |||
| 52 | bool is_compressed; | 52 | bool is_compressed; |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | class BGRCopyPass { | 55 | class FormatConversionPass { |
| 56 | public: | 56 | public: |
| 57 | BGRCopyPass() = default; | 57 | FormatConversionPass() = default; |
| 58 | ~BGRCopyPass() = default; | 58 | ~FormatConversionPass() = default; |
| 59 | 59 | ||
| 60 | void CopyBGR(Image& dst_image, Image& src_image, | 60 | void ConvertImage(Image& dst_image, Image& src_image, |
| 61 | std::span<const VideoCommon::ImageCopy> copies); | 61 | std::span<const VideoCommon::ImageCopy> copies); |
| 62 | 62 | ||
| 63 | private: | 63 | private: |
| 64 | OGLBuffer bgr_pbo; | 64 | OGLBuffer intermediate_pbo; |
| 65 | size_t bgr_pbo_size{}; | 65 | size_t pbo_size{}; |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | class TextureCacheRuntime { | 68 | class TextureCacheRuntime { |
| @@ -84,8 +84,14 @@ public: | |||
| 84 | 84 | ||
| 85 | u64 GetDeviceLocalMemory() const; | 85 | u64 GetDeviceLocalMemory() const; |
| 86 | 86 | ||
| 87 | bool ShouldReinterpret([[maybe_unused]] Image& dst, [[maybe_unused]] Image& src) { | ||
| 88 | return true; | ||
| 89 | } | ||
| 90 | |||
| 87 | void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | 91 | void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); |
| 88 | 92 | ||
| 93 | void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | ||
| 94 | |||
| 89 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) { | 95 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) { |
| 90 | UNIMPLEMENTED(); | 96 | UNIMPLEMENTED(); |
| 91 | } | 97 | } |
| @@ -144,7 +150,7 @@ private: | |||
| 144 | const Device& device; | 150 | const Device& device; |
| 145 | StateTracker& state_tracker; | 151 | StateTracker& state_tracker; |
| 146 | UtilShaders util_shaders; | 152 | UtilShaders util_shaders; |
| 147 | BGRCopyPass bgr_copy_pass; | 153 | FormatConversionPass format_conversion_pass; |
| 148 | 154 | ||
| 149 | std::array<std::unordered_map<GLenum, FormatProperties>, 3> format_properties; | 155 | std::array<std::unordered_map<GLenum, FormatProperties>, 3> format_properties; |
| 150 | bool has_broken_texture_view_formats = false; | 156 | bool has_broken_texture_view_formats = false; |
| @@ -162,8 +168,8 @@ private: | |||
| 162 | 168 | ||
| 163 | std::array<GLuint, Shader::NUM_TEXTURE_TYPES> null_image_views{}; | 169 | std::array<GLuint, Shader::NUM_TEXTURE_TYPES> null_image_views{}; |
| 164 | 170 | ||
| 165 | std::array<OGLFramebuffer, 3> rescale_draw_fbos; | 171 | std::array<OGLFramebuffer, 4> rescale_draw_fbos; |
| 166 | std::array<OGLFramebuffer, 3> rescale_read_fbos; | 172 | std::array<OGLFramebuffer, 4> rescale_read_fbos; |
| 167 | const Settings::ResolutionScalingInfo& resolution; | 173 | const Settings::ResolutionScalingInfo& resolution; |
| 168 | }; | 174 | }; |
| 169 | 175 | ||
| @@ -219,6 +225,7 @@ private: | |||
| 219 | GLenum gl_internal_format = GL_NONE; | 225 | GLenum gl_internal_format = GL_NONE; |
| 220 | GLenum gl_format = GL_NONE; | 226 | GLenum gl_format = GL_NONE; |
| 221 | GLenum gl_type = GL_NONE; | 227 | GLenum gl_type = GL_NONE; |
| 228 | GLsizei gl_num_levels{}; | ||
| 222 | TextureCacheRuntime* runtime{}; | 229 | TextureCacheRuntime* runtime{}; |
| 223 | GLuint current_texture{}; | 230 | GLuint current_texture{}; |
| 224 | }; | 231 | }; |
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index 39158aa3e..daba42ed9 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h | |||
| @@ -108,6 +108,7 @@ constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> FORMAT_TAB | |||
| 108 | {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9_FLOAT | 108 | {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9_FLOAT |
| 109 | {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // D32_FLOAT | 109 | {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // D32_FLOAT |
| 110 | {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16_UNORM | 110 | {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16_UNORM |
| 111 | {GL_STENCIL_INDEX8, GL_STENCIL, GL_UNSIGNED_BYTE}, // S8_UINT | ||
| 111 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24_UNORM_S8_UINT | 112 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24_UNORM_S8_UINT |
| 112 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8_UINT_D24_UNORM | 113 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8_UINT_D24_UNORM |
| 113 | {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, | 114 | {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, |
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index b3884a4f5..28b631f73 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -4,8 +4,14 @@ | |||
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | 6 | ||
| 7 | #include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h" | ||
| 8 | #include "video_core/host_shaders/convert_b10g11r11_to_d24s8_frag_spv.h" | ||
| 9 | #include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h" | ||
| 10 | #include "video_core/host_shaders/convert_d24s8_to_b10g11r11_frag_spv.h" | ||
| 11 | #include "video_core/host_shaders/convert_d24s8_to_r16g16_frag_spv.h" | ||
| 7 | #include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" | 12 | #include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" |
| 8 | #include "video_core/host_shaders/convert_float_to_depth_frag_spv.h" | 13 | #include "video_core/host_shaders/convert_float_to_depth_frag_spv.h" |
| 14 | #include "video_core/host_shaders/convert_r16g16_to_d24s8_frag_spv.h" | ||
| 9 | #include "video_core/host_shaders/full_screen_triangle_vert_spv.h" | 15 | #include "video_core/host_shaders/full_screen_triangle_vert_spv.h" |
| 10 | #include "video_core/host_shaders/vulkan_blit_color_float_frag_spv.h" | 16 | #include "video_core/host_shaders/vulkan_blit_color_float_frag_spv.h" |
| 11 | #include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h" | 17 | #include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h" |
| @@ -354,6 +360,12 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, | |||
| 354 | blit_color_to_color_frag(BuildShader(device, VULKAN_BLIT_COLOR_FLOAT_FRAG_SPV)), | 360 | blit_color_to_color_frag(BuildShader(device, VULKAN_BLIT_COLOR_FLOAT_FRAG_SPV)), |
| 355 | convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), | 361 | convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), |
| 356 | convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), | 362 | convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), |
| 363 | convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)), | ||
| 364 | convert_b10g11r11_to_d24s8_frag(BuildShader(device, CONVERT_B10G11R11_TO_D24S8_FRAG_SPV)), | ||
| 365 | convert_r16g16_to_d24s8_frag(BuildShader(device, CONVERT_R16G16_TO_D24S8_FRAG_SPV)), | ||
| 366 | convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)), | ||
| 367 | convert_d24s8_to_b10g11r11_frag(BuildShader(device, CONVERT_D24S8_TO_B10G11R11_FRAG_SPV)), | ||
| 368 | convert_d24s8_to_r16g16_frag(BuildShader(device, CONVERT_D24S8_TO_R16G16_FRAG_SPV)), | ||
| 357 | linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)), | 369 | linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)), |
| 358 | nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) { | 370 | nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) { |
| 359 | if (device.IsExtShaderStencilExportSupported()) { | 371 | if (device.IsExtShaderStencilExportSupported()) { |
| @@ -448,6 +460,59 @@ void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer, | |||
| 448 | Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); | 460 | Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); |
| 449 | } | 461 | } |
| 450 | 462 | ||
| 463 | void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, | ||
| 464 | const ImageView& src_image_view, u32 up_scale, | ||
| 465 | u32 down_shift) { | ||
| 466 | ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(), | ||
| 467 | convert_abgr8_to_d24s8_frag, true); | ||
| 468 | Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale, | ||
| 469 | down_shift); | ||
| 470 | } | ||
| 471 | |||
| 472 | void BlitImageHelper::ConvertB10G11R11ToD24S8(const Framebuffer* dst_framebuffer, | ||
| 473 | const ImageView& src_image_view, u32 up_scale, | ||
| 474 | u32 down_shift) { | ||
| 475 | ConvertPipelineDepthTargetEx(convert_b10g11r11_to_d24s8_pipeline, dst_framebuffer->RenderPass(), | ||
| 476 | convert_b10g11r11_to_d24s8_frag, true); | ||
| 477 | Convert(*convert_b10g11r11_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale, | ||
| 478 | down_shift); | ||
| 479 | } | ||
| 480 | |||
| 481 | void BlitImageHelper::ConvertR16G16ToD24S8(const Framebuffer* dst_framebuffer, | ||
| 482 | const ImageView& src_image_view, u32 up_scale, | ||
| 483 | u32 down_shift) { | ||
| 484 | ConvertPipelineDepthTargetEx(convert_r16g16_to_d24s8_pipeline, dst_framebuffer->RenderPass(), | ||
| 485 | convert_r16g16_to_d24s8_frag, true); | ||
| 486 | Convert(*convert_r16g16_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale, | ||
| 487 | down_shift); | ||
| 488 | } | ||
| 489 | |||
| 490 | void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, | ||
| 491 | ImageView& src_image_view, u32 up_scale, u32 down_shift) { | ||
| 492 | ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(), | ||
| 493 | convert_d24s8_to_abgr8_frag, false); | ||
| 494 | ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view, up_scale, | ||
| 495 | down_shift); | ||
| 496 | } | ||
| 497 | |||
| 498 | void BlitImageHelper::ConvertD24S8ToB10G11R11(const Framebuffer* dst_framebuffer, | ||
| 499 | ImageView& src_image_view, u32 up_scale, | ||
| 500 | u32 down_shift) { | ||
| 501 | ConvertPipelineColorTargetEx(convert_d24s8_to_b10g11r11_pipeline, dst_framebuffer->RenderPass(), | ||
| 502 | convert_d24s8_to_b10g11r11_frag, false); | ||
| 503 | ConvertDepthStencil(*convert_d24s8_to_b10g11r11_pipeline, dst_framebuffer, src_image_view, | ||
| 504 | up_scale, down_shift); | ||
| 505 | } | ||
| 506 | |||
| 507 | void BlitImageHelper::ConvertD24S8ToR16G16(const Framebuffer* dst_framebuffer, | ||
| 508 | ImageView& src_image_view, u32 up_scale, | ||
| 509 | u32 down_shift) { | ||
| 510 | ConvertPipelineColorTargetEx(convert_d24s8_to_r16g16_pipeline, dst_framebuffer->RenderPass(), | ||
| 511 | convert_d24s8_to_r16g16_frag, false); | ||
| 512 | ConvertDepthStencil(*convert_d24s8_to_r16g16_pipeline, dst_framebuffer, src_image_view, | ||
| 513 | up_scale, down_shift); | ||
| 514 | } | ||
| 515 | |||
| 451 | void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | 516 | void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, |
| 452 | const ImageView& src_image_view, u32 up_scale, u32 down_shift) { | 517 | const ImageView& src_image_view, u32 up_scale, u32 down_shift) { |
| 453 | const VkPipelineLayout layout = *one_texture_pipeline_layout; | 518 | const VkPipelineLayout layout = *one_texture_pipeline_layout; |
| @@ -495,6 +560,54 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb | |||
| 495 | scheduler.InvalidateState(); | 560 | scheduler.InvalidateState(); |
| 496 | } | 561 | } |
| 497 | 562 | ||
| 563 | void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | ||
| 564 | ImageView& src_image_view, u32 up_scale, u32 down_shift) { | ||
| 565 | const VkPipelineLayout layout = *two_textures_pipeline_layout; | ||
| 566 | const VkImageView src_depth_view = src_image_view.DepthView(); | ||
| 567 | const VkImageView src_stencil_view = src_image_view.StencilView(); | ||
| 568 | const VkSampler sampler = *nearest_sampler; | ||
| 569 | const VkExtent2D extent{ | ||
| 570 | .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U), | ||
| 571 | .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U), | ||
| 572 | }; | ||
| 573 | scheduler.RequestRenderpass(dst_framebuffer); | ||
| 574 | scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent, up_scale, | ||
| 575 | down_shift, this](vk::CommandBuffer cmdbuf) { | ||
| 576 | const VkOffset2D offset{ | ||
| 577 | .x = 0, | ||
| 578 | .y = 0, | ||
| 579 | }; | ||
| 580 | const VkViewport viewport{ | ||
| 581 | .x = 0.0f, | ||
| 582 | .y = 0.0f, | ||
| 583 | .width = static_cast<float>(extent.width), | ||
| 584 | .height = static_cast<float>(extent.height), | ||
| 585 | .minDepth = 0.0f, | ||
| 586 | .maxDepth = 0.0f, | ||
| 587 | }; | ||
| 588 | const VkRect2D scissor{ | ||
| 589 | .offset = offset, | ||
| 590 | .extent = extent, | ||
| 591 | }; | ||
| 592 | const PushConstants push_constants{ | ||
| 593 | .tex_scale = {viewport.width, viewport.height}, | ||
| 594 | .tex_offset = {0.0f, 0.0f}, | ||
| 595 | }; | ||
| 596 | const VkDescriptorSet descriptor_set = two_textures_descriptor_allocator.Commit(); | ||
| 597 | UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_depth_view, | ||
| 598 | src_stencil_view); | ||
| 599 | // TODO: Barriers | ||
| 600 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); | ||
| 601 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, | ||
| 602 | nullptr); | ||
| 603 | cmdbuf.SetViewport(0, viewport); | ||
| 604 | cmdbuf.SetScissor(0, scissor); | ||
| 605 | cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants); | ||
| 606 | cmdbuf.Draw(3, 1, 0, 0); | ||
| 607 | }); | ||
| 608 | scheduler.InvalidateState(); | ||
| 609 | } | ||
| 610 | |||
| 498 | VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key) { | 611 | VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key) { |
| 499 | const auto it = std::ranges::find(blit_color_keys, key); | 612 | const auto it = std::ranges::find(blit_color_keys, key); |
| 500 | if (it != blit_color_keys.end()) { | 613 | if (it != blit_color_keys.end()) { |
| @@ -636,4 +749,62 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend | |||
| 636 | }); | 749 | }); |
| 637 | } | 750 | } |
| 638 | 751 | ||
| 752 | void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | ||
| 753 | vk::ShaderModule& module, bool single_texture) { | ||
| 754 | if (pipeline) { | ||
| 755 | return; | ||
| 756 | } | ||
| 757 | const std::array stages = MakeStages(*full_screen_vert, *module); | ||
| 758 | pipeline = device.GetLogical().CreateGraphicsPipeline({ | ||
| 759 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | ||
| 760 | .pNext = nullptr, | ||
| 761 | .flags = 0, | ||
| 762 | .stageCount = static_cast<u32>(stages.size()), | ||
| 763 | .pStages = stages.data(), | ||
| 764 | .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, | ||
| 765 | .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, | ||
| 766 | .pTessellationState = nullptr, | ||
| 767 | .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, | ||
| 768 | .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, | ||
| 769 | .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, | ||
| 770 | .pDepthStencilState = nullptr, | ||
| 771 | .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, | ||
| 772 | .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, | ||
| 773 | .layout = single_texture ? *one_texture_pipeline_layout : *two_textures_pipeline_layout, | ||
| 774 | .renderPass = renderpass, | ||
| 775 | .subpass = 0, | ||
| 776 | .basePipelineHandle = VK_NULL_HANDLE, | ||
| 777 | .basePipelineIndex = 0, | ||
| 778 | }); | ||
| 779 | } | ||
| 780 | |||
| 781 | void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | ||
| 782 | vk::ShaderModule& module, bool single_texture) { | ||
| 783 | if (pipeline) { | ||
| 784 | return; | ||
| 785 | } | ||
| 786 | const std::array stages = MakeStages(*full_screen_vert, *module); | ||
| 787 | pipeline = device.GetLogical().CreateGraphicsPipeline({ | ||
| 788 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | ||
| 789 | .pNext = nullptr, | ||
| 790 | .flags = 0, | ||
| 791 | .stageCount = static_cast<u32>(stages.size()), | ||
| 792 | .pStages = stages.data(), | ||
| 793 | .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, | ||
| 794 | .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, | ||
| 795 | .pTessellationState = nullptr, | ||
| 796 | .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, | ||
| 797 | .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, | ||
| 798 | .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, | ||
| 799 | .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, | ||
| 800 | .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO, | ||
| 801 | .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, | ||
| 802 | .layout = single_texture ? *one_texture_pipeline_layout : *two_textures_pipeline_layout, | ||
| 803 | .renderPass = renderpass, | ||
| 804 | .subpass = 0, | ||
| 805 | .basePipelineHandle = VK_NULL_HANDLE, | ||
| 806 | .basePipelineIndex = 0, | ||
| 807 | }); | ||
| 808 | } | ||
| 809 | |||
| 639 | } // namespace Vulkan | 810 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index d77f76678..cec095341 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h | |||
| @@ -56,10 +56,31 @@ public: | |||
| 56 | void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 56 | void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, |
| 57 | u32 up_scale, u32 down_shift); | 57 | u32 up_scale, u32 down_shift); |
| 58 | 58 | ||
| 59 | void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | ||
| 60 | u32 up_scale, u32 down_shift); | ||
| 61 | |||
| 62 | void ConvertB10G11R11ToD24S8(const Framebuffer* dst_framebuffer, | ||
| 63 | const ImageView& src_image_view, u32 up_scale, u32 down_shift); | ||
| 64 | |||
| 65 | void ConvertR16G16ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | ||
| 66 | u32 up_scale, u32 down_shift); | ||
| 67 | |||
| 68 | void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view, | ||
| 69 | u32 up_scale, u32 down_shift); | ||
| 70 | |||
| 71 | void ConvertD24S8ToB10G11R11(const Framebuffer* dst_framebuffer, ImageView& src_image_view, | ||
| 72 | u32 up_scale, u32 down_shift); | ||
| 73 | |||
| 74 | void ConvertD24S8ToR16G16(const Framebuffer* dst_framebuffer, ImageView& src_image_view, | ||
| 75 | u32 up_scale, u32 down_shift); | ||
| 76 | |||
| 59 | private: | 77 | private: |
| 60 | void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | 78 | void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, |
| 61 | const ImageView& src_image_view, u32 up_scale, u32 down_shift); | 79 | const ImageView& src_image_view, u32 up_scale, u32 down_shift); |
| 62 | 80 | ||
| 81 | void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | ||
| 82 | ImageView& src_image_view, u32 up_scale, u32 down_shift); | ||
| 83 | |||
| 63 | [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); | 84 | [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); |
| 64 | 85 | ||
| 65 | [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); | 86 | [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); |
| @@ -68,6 +89,12 @@ private: | |||
| 68 | 89 | ||
| 69 | void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); | 90 | void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); |
| 70 | 91 | ||
| 92 | void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | ||
| 93 | vk::ShaderModule& module, bool single_texture); | ||
| 94 | |||
| 95 | void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | ||
| 96 | vk::ShaderModule& module, bool single_texture); | ||
| 97 | |||
| 71 | const Device& device; | 98 | const Device& device; |
| 72 | VKScheduler& scheduler; | 99 | VKScheduler& scheduler; |
| 73 | StateTracker& state_tracker; | 100 | StateTracker& state_tracker; |
| @@ -83,6 +110,12 @@ private: | |||
| 83 | vk::ShaderModule blit_depth_stencil_frag; | 110 | vk::ShaderModule blit_depth_stencil_frag; |
| 84 | vk::ShaderModule convert_depth_to_float_frag; | 111 | vk::ShaderModule convert_depth_to_float_frag; |
| 85 | vk::ShaderModule convert_float_to_depth_frag; | 112 | vk::ShaderModule convert_float_to_depth_frag; |
| 113 | vk::ShaderModule convert_abgr8_to_d24s8_frag; | ||
| 114 | vk::ShaderModule convert_b10g11r11_to_d24s8_frag; | ||
| 115 | vk::ShaderModule convert_r16g16_to_d24s8_frag; | ||
| 116 | vk::ShaderModule convert_d24s8_to_abgr8_frag; | ||
| 117 | vk::ShaderModule convert_d24s8_to_b10g11r11_frag; | ||
| 118 | vk::ShaderModule convert_d24s8_to_r16g16_frag; | ||
| 86 | vk::Sampler linear_sampler; | 119 | vk::Sampler linear_sampler; |
| 87 | vk::Sampler nearest_sampler; | 120 | vk::Sampler nearest_sampler; |
| 88 | 121 | ||
| @@ -94,6 +127,12 @@ private: | |||
| 94 | vk::Pipeline convert_r32_to_d32_pipeline; | 127 | vk::Pipeline convert_r32_to_d32_pipeline; |
| 95 | vk::Pipeline convert_d16_to_r16_pipeline; | 128 | vk::Pipeline convert_d16_to_r16_pipeline; |
| 96 | vk::Pipeline convert_r16_to_d16_pipeline; | 129 | vk::Pipeline convert_r16_to_d16_pipeline; |
| 130 | vk::Pipeline convert_abgr8_to_d24s8_pipeline; | ||
| 131 | vk::Pipeline convert_b10g11r11_to_d24s8_pipeline; | ||
| 132 | vk::Pipeline convert_r16g16_to_d24s8_pipeline; | ||
| 133 | vk::Pipeline convert_d24s8_to_abgr8_pipeline; | ||
| 134 | vk::Pipeline convert_d24s8_to_b10g11r11_pipeline; | ||
| 135 | vk::Pipeline convert_d24s8_to_r16g16_pipeline; | ||
| 97 | }; | 136 | }; |
| 98 | 137 | ||
| 99 | } // namespace Vulkan | 138 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 68a23b602..31adada56 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -208,6 +208,9 @@ struct FormatTuple { | |||
| 208 | {VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT | 208 | {VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT |
| 209 | {VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM | 209 | {VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM |
| 210 | 210 | ||
| 211 | // Stencil formats | ||
| 212 | {VK_FORMAT_S8_UINT, Attachable}, // S8_UINT | ||
| 213 | |||
| 211 | // DepthStencil formats | 214 | // DepthStencil formats |
| 212 | {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // D24_UNORM_S8_UINT | 215 | {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // D24_UNORM_S8_UINT |
| 213 | {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // S8_UINT_D24_UNORM (emulated) | 216 | {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // S8_UINT_D24_UNORM (emulated) |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 407fd2a15..3964424af 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include "common/bit_cast.h" | 10 | #include "common/bit_cast.h" |
| 11 | #include "common/bit_util.h" | ||
| 11 | #include "common/settings.h" | 12 | #include "common/settings.h" |
| 12 | 13 | ||
| 13 | #include "video_core/engines/fermi_2d.h" | 14 | #include "video_core/engines/fermi_2d.h" |
| @@ -102,6 +103,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 102 | usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; | 103 | usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| 103 | break; | 104 | break; |
| 104 | case VideoCore::Surface::SurfaceType::Depth: | 105 | case VideoCore::Surface::SurfaceType::Depth: |
| 106 | case VideoCore::Surface::SurfaceType::Stencil: | ||
| 105 | case VideoCore::Surface::SurfaceType::DepthStencil: | 107 | case VideoCore::Surface::SurfaceType::DepthStencil: |
| 106 | usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; | 108 | usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; |
| 107 | break; | 109 | break; |
| @@ -173,6 +175,8 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 173 | return VK_IMAGE_ASPECT_COLOR_BIT; | 175 | return VK_IMAGE_ASPECT_COLOR_BIT; |
| 174 | case VideoCore::Surface::SurfaceType::Depth: | 176 | case VideoCore::Surface::SurfaceType::Depth: |
| 175 | return VK_IMAGE_ASPECT_DEPTH_BIT; | 177 | return VK_IMAGE_ASPECT_DEPTH_BIT; |
| 178 | case VideoCore::Surface::SurfaceType::Stencil: | ||
| 179 | return VK_IMAGE_ASPECT_STENCIL_BIT; | ||
| 176 | case VideoCore::Surface::SurfaceType::DepthStencil: | 180 | case VideoCore::Surface::SurfaceType::DepthStencil: |
| 177 | return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; | 181 | return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; |
| 178 | default: | 182 | default: |
| @@ -195,6 +199,8 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 195 | case PixelFormat::D16_UNORM: | 199 | case PixelFormat::D16_UNORM: |
| 196 | case PixelFormat::D32_FLOAT: | 200 | case PixelFormat::D32_FLOAT: |
| 197 | return VK_IMAGE_ASPECT_DEPTH_BIT; | 201 | return VK_IMAGE_ASPECT_DEPTH_BIT; |
| 202 | case PixelFormat::S8_UINT: | ||
| 203 | return VK_IMAGE_ASPECT_STENCIL_BIT; | ||
| 198 | default: | 204 | default: |
| 199 | return VK_IMAGE_ASPECT_COLOR_BIT; | 205 | return VK_IMAGE_ASPECT_COLOR_BIT; |
| 200 | } | 206 | } |
| @@ -308,6 +314,19 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 308 | }; | 314 | }; |
| 309 | } | 315 | } |
| 310 | 316 | ||
| 317 | [[nodiscard]] VkBufferImageCopy MakeBufferImageCopy(const VideoCommon::ImageCopy& copy, bool is_src, | ||
| 318 | VkImageAspectFlags aspect_mask) noexcept { | ||
| 319 | return VkBufferImageCopy{ | ||
| 320 | .bufferOffset = 0, | ||
| 321 | .bufferRowLength = 0, | ||
| 322 | .bufferImageHeight = 0, | ||
| 323 | .imageSubresource = MakeImageSubresourceLayers( | ||
| 324 | is_src ? copy.src_subresource : copy.dst_subresource, aspect_mask), | ||
| 325 | .imageOffset = MakeOffset3D(is_src ? copy.src_offset : copy.dst_offset), | ||
| 326 | .imageExtent = MakeExtent3D(copy.extent), | ||
| 327 | }; | ||
| 328 | } | ||
| 329 | |||
| 311 | [[maybe_unused]] [[nodiscard]] std::vector<VkBufferCopy> TransformBufferCopies( | 330 | [[maybe_unused]] [[nodiscard]] std::vector<VkBufferCopy> TransformBufferCopies( |
| 312 | std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) { | 331 | std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) { |
| 313 | std::vector<VkBufferCopy> result(copies.size()); | 332 | std::vector<VkBufferCopy> result(copies.size()); |
| @@ -754,6 +773,163 @@ StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size) { | |||
| 754 | return staging_buffer_pool.Request(size, MemoryUsage::Download); | 773 | return staging_buffer_pool.Request(size, MemoryUsage::Download); |
| 755 | } | 774 | } |
| 756 | 775 | ||
| 776 | bool TextureCacheRuntime::ShouldReinterpret(Image& dst, Image& src) { | ||
| 777 | if (VideoCore::Surface::GetFormatType(dst.info.format) == | ||
| 778 | VideoCore::Surface::SurfaceType::DepthStencil) { | ||
| 779 | return !device.IsExtShaderStencilExportSupported(); | ||
| 780 | } | ||
| 781 | return false; | ||
| 782 | } | ||
| 783 | |||
| 784 | VkBuffer TextureCacheRuntime::GetTemporaryBuffer(size_t needed_size) { | ||
| 785 | const auto level = (8 * sizeof(size_t)) - std::countl_zero(needed_size - 1ULL); | ||
| 786 | if (buffer_commits[level]) { | ||
| 787 | return *buffers[level]; | ||
| 788 | } | ||
| 789 | const auto new_size = Common::NextPow2(needed_size); | ||
| 790 | VkBufferUsageFlags flags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | | ||
| 791 | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | | ||
| 792 | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; | ||
| 793 | buffers[level] = device.GetLogical().CreateBuffer({ | ||
| 794 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | ||
| 795 | .pNext = nullptr, | ||
| 796 | .flags = 0, | ||
| 797 | .size = new_size, | ||
| 798 | .usage = flags, | ||
| 799 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||
| 800 | .queueFamilyIndexCount = 0, | ||
| 801 | .pQueueFamilyIndices = nullptr, | ||
| 802 | }); | ||
| 803 | buffer_commits[level] = std::make_unique<MemoryCommit>( | ||
| 804 | memory_allocator.Commit(buffers[level], MemoryUsage::DeviceLocal)); | ||
| 805 | return *buffers[level]; | ||
| 806 | } | ||
| 807 | |||
| 808 | void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, | ||
| 809 | std::span<const VideoCommon::ImageCopy> copies) { | ||
| 810 | std::vector<VkBufferImageCopy> vk_in_copies(copies.size()); | ||
| 811 | std::vector<VkBufferImageCopy> vk_out_copies(copies.size()); | ||
| 812 | const VkImageAspectFlags src_aspect_mask = src.AspectMask(); | ||
| 813 | const VkImageAspectFlags dst_aspect_mask = dst.AspectMask(); | ||
| 814 | |||
| 815 | std::ranges::transform(copies, vk_in_copies.begin(), [src_aspect_mask](const auto& copy) { | ||
| 816 | return MakeBufferImageCopy(copy, true, src_aspect_mask); | ||
| 817 | }); | ||
| 818 | std::ranges::transform(copies, vk_out_copies.begin(), [dst_aspect_mask](const auto& copy) { | ||
| 819 | return MakeBufferImageCopy(copy, false, dst_aspect_mask); | ||
| 820 | }); | ||
| 821 | const u32 img_bpp = BytesPerBlock(src.info.format); | ||
| 822 | size_t total_size = 0; | ||
| 823 | for (const auto& copy : copies) { | ||
| 824 | total_size += copy.extent.width * copy.extent.height * copy.extent.depth * img_bpp; | ||
| 825 | } | ||
| 826 | const VkBuffer copy_buffer = GetTemporaryBuffer(total_size); | ||
| 827 | const VkImage dst_image = dst.Handle(); | ||
| 828 | const VkImage src_image = src.Handle(); | ||
| 829 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 830 | scheduler.Record([dst_image, src_image, copy_buffer, src_aspect_mask, dst_aspect_mask, | ||
| 831 | vk_in_copies, vk_out_copies](vk::CommandBuffer cmdbuf) { | ||
| 832 | RangedBarrierRange dst_range; | ||
| 833 | RangedBarrierRange src_range; | ||
| 834 | for (const VkBufferImageCopy& copy : vk_in_copies) { | ||
| 835 | src_range.AddLayers(copy.imageSubresource); | ||
| 836 | } | ||
| 837 | for (const VkBufferImageCopy& copy : vk_out_copies) { | ||
| 838 | dst_range.AddLayers(copy.imageSubresource); | ||
| 839 | } | ||
| 840 | static constexpr VkMemoryBarrier READ_BARRIER{ | ||
| 841 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, | ||
| 842 | .pNext = nullptr, | ||
| 843 | .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, | ||
| 844 | .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 845 | }; | ||
| 846 | static constexpr VkMemoryBarrier WRITE_BARRIER{ | ||
| 847 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, | ||
| 848 | .pNext = nullptr, | ||
| 849 | .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 850 | .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, | ||
| 851 | }; | ||
| 852 | const std::array pre_barriers{ | ||
| 853 | VkImageMemoryBarrier{ | ||
| 854 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 855 | .pNext = nullptr, | ||
| 856 | .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | | ||
| 857 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | | ||
| 858 | VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 859 | .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, | ||
| 860 | .oldLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 861 | .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, | ||
| 862 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 863 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 864 | .image = src_image, | ||
| 865 | .subresourceRange = src_range.SubresourceRange(src_aspect_mask), | ||
| 866 | }, | ||
| 867 | }; | ||
| 868 | const std::array middle_in_barrier{ | ||
| 869 | VkImageMemoryBarrier{ | ||
| 870 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 871 | .pNext = nullptr, | ||
| 872 | .srcAccessMask = 0, | ||
| 873 | .dstAccessMask = 0, | ||
| 874 | .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, | ||
| 875 | .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 876 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 877 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 878 | .image = src_image, | ||
| 879 | .subresourceRange = src_range.SubresourceRange(src_aspect_mask), | ||
| 880 | }, | ||
| 881 | }; | ||
| 882 | const std::array middle_out_barrier{ | ||
| 883 | VkImageMemoryBarrier{ | ||
| 884 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 885 | .pNext = nullptr, | ||
| 886 | .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | | ||
| 887 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | | ||
| 888 | VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 889 | .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 890 | .oldLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 891 | .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | ||
| 892 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 893 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 894 | .image = dst_image, | ||
| 895 | .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask), | ||
| 896 | }, | ||
| 897 | }; | ||
| 898 | const std::array post_barriers{ | ||
| 899 | VkImageMemoryBarrier{ | ||
| 900 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 901 | .pNext = nullptr, | ||
| 902 | .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 903 | .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | | ||
| 904 | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | | ||
| 905 | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | | ||
| 906 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | | ||
| 907 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | | ||
| 908 | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 909 | .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | ||
| 910 | .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 911 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 912 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 913 | .image = dst_image, | ||
| 914 | .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask), | ||
| 915 | }, | ||
| 916 | }; | ||
| 917 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, | ||
| 918 | 0, {}, {}, pre_barriers); | ||
| 919 | |||
| 920 | cmdbuf.CopyImageToBuffer(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, copy_buffer, | ||
| 921 | vk_in_copies); | ||
| 922 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, | ||
| 923 | 0, WRITE_BARRIER, nullptr, middle_in_barrier); | ||
| 924 | |||
| 925 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, | ||
| 926 | 0, READ_BARRIER, {}, middle_out_barrier); | ||
| 927 | cmdbuf.CopyBufferToImage(copy_buffer, dst_image, VK_IMAGE_LAYOUT_GENERAL, vk_out_copies); | ||
| 928 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, | ||
| 929 | 0, {}, {}, post_barriers); | ||
| 930 | }); | ||
| 931 | } | ||
| 932 | |||
| 757 | void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, | 933 | void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, |
| 758 | const Region2D& dst_region, const Region2D& src_region, | 934 | const Region2D& dst_region, const Region2D& src_region, |
| 759 | Tegra::Engines::Fermi2D::Filter filter, | 935 | Tegra::Engines::Fermi2D::Filter filter, |
| @@ -881,6 +1057,22 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im | |||
| 881 | return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift); | 1057 | return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift); |
| 882 | } | 1058 | } |
| 883 | break; | 1059 | break; |
| 1060 | case PixelFormat::A8B8G8R8_UNORM: | ||
| 1061 | case PixelFormat::B8G8R8A8_UNORM: | ||
| 1062 | if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) { | ||
| 1063 | return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view, up_scale, down_shift); | ||
| 1064 | } | ||
| 1065 | break; | ||
| 1066 | case PixelFormat::B10G11R11_FLOAT: | ||
| 1067 | if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) { | ||
| 1068 | return blit_image_helper.ConvertD24S8ToB10G11R11(dst, src_view, up_scale, down_shift); | ||
| 1069 | } | ||
| 1070 | break; | ||
| 1071 | case PixelFormat::R16G16_UNORM: | ||
| 1072 | if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) { | ||
| 1073 | return blit_image_helper.ConvertD24S8ToR16G16(dst, src_view, up_scale, down_shift); | ||
| 1074 | } | ||
| 1075 | break; | ||
| 884 | case PixelFormat::R32_FLOAT: | 1076 | case PixelFormat::R32_FLOAT: |
| 885 | if (src_view.format == PixelFormat::D32_FLOAT) { | 1077 | if (src_view.format == PixelFormat::D32_FLOAT) { |
| 886 | return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift); | 1078 | return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift); |
| @@ -891,6 +1083,18 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im | |||
| 891 | return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift); | 1083 | return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift); |
| 892 | } | 1084 | } |
| 893 | break; | 1085 | break; |
| 1086 | case PixelFormat::S8_UINT_D24_UNORM: | ||
| 1087 | if (src_view.format == PixelFormat::A8B8G8R8_UNORM || | ||
| 1088 | src_view.format == PixelFormat::B8G8R8A8_UNORM) { | ||
| 1089 | return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view, up_scale, down_shift); | ||
| 1090 | } | ||
| 1091 | if (src_view.format == PixelFormat::B10G11R11_FLOAT) { | ||
| 1092 | return blit_image_helper.ConvertB10G11R11ToD24S8(dst, src_view, up_scale, down_shift); | ||
| 1093 | } | ||
| 1094 | if (src_view.format == PixelFormat::R16G16_UNORM) { | ||
| 1095 | return blit_image_helper.ConvertR16G16ToD24S8(dst, src_view, up_scale, down_shift); | ||
| 1096 | } | ||
| 1097 | break; | ||
| 894 | case PixelFormat::D32_FLOAT: | 1098 | case PixelFormat::D32_FLOAT: |
| 895 | if (src_view.format == PixelFormat::R32_FLOAT) { | 1099 | if (src_view.format == PixelFormat::R32_FLOAT) { |
| 896 | return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift); | 1100 | return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index ff28b4e96..44e9dcee4 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -61,6 +61,10 @@ public: | |||
| 61 | 61 | ||
| 62 | void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | 62 | void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); |
| 63 | 63 | ||
| 64 | bool ShouldReinterpret(Image& dst, Image& src); | ||
| 65 | |||
| 66 | void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | ||
| 67 | |||
| 64 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled); | 68 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled); |
| 65 | 69 | ||
| 66 | bool CanAccelerateImageUpload(Image&) const noexcept { | 70 | bool CanAccelerateImageUpload(Image&) const noexcept { |
| @@ -82,6 +86,8 @@ public: | |||
| 82 | return true; | 86 | return true; |
| 83 | } | 87 | } |
| 84 | 88 | ||
| 89 | [[nodiscard]] VkBuffer GetTemporaryBuffer(size_t needed_size); | ||
| 90 | |||
| 85 | const Device& device; | 91 | const Device& device; |
| 86 | VKScheduler& scheduler; | 92 | VKScheduler& scheduler; |
| 87 | MemoryAllocator& memory_allocator; | 93 | MemoryAllocator& memory_allocator; |
| @@ -90,6 +96,10 @@ public: | |||
| 90 | ASTCDecoderPass& astc_decoder_pass; | 96 | ASTCDecoderPass& astc_decoder_pass; |
| 91 | RenderPassCache& render_pass_cache; | 97 | RenderPassCache& render_pass_cache; |
| 92 | const Settings::ResolutionScalingInfo& resolution; | 98 | const Settings::ResolutionScalingInfo& resolution; |
| 99 | |||
| 100 | constexpr static size_t indexing_slots = 8 * sizeof(size_t); | ||
| 101 | std::array<vk::Buffer, indexing_slots> buffers{}; | ||
| 102 | std::array<std::unique_ptr<MemoryCommit>, indexing_slots> buffer_commits{}; | ||
| 93 | }; | 103 | }; |
| 94 | 104 | ||
| 95 | class Image : public VideoCommon::ImageBase { | 105 | class Image : public VideoCommon::ImageBase { |
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index 58d262446..a36015c8c 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp | |||
| @@ -82,6 +82,8 @@ PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { | |||
| 82 | return PixelFormat::D32_FLOAT; | 82 | return PixelFormat::D32_FLOAT; |
| 83 | case Tegra::DepthFormat::D16_UNORM: | 83 | case Tegra::DepthFormat::D16_UNORM: |
| 84 | return PixelFormat::D16_UNORM; | 84 | return PixelFormat::D16_UNORM; |
| 85 | case Tegra::DepthFormat::S8_UINT: | ||
| 86 | return PixelFormat::S8_UINT; | ||
| 85 | case Tegra::DepthFormat::D32_FLOAT_S8X24_UINT: | 87 | case Tegra::DepthFormat::D32_FLOAT_S8X24_UINT: |
| 86 | return PixelFormat::D32_FLOAT_S8_UINT; | 88 | return PixelFormat::D32_FLOAT_S8_UINT; |
| 87 | default: | 89 | default: |
| @@ -214,6 +216,11 @@ SurfaceType GetFormatType(PixelFormat pixel_format) { | |||
| 214 | } | 216 | } |
| 215 | 217 | ||
| 216 | if (static_cast<std::size_t>(pixel_format) < | 218 | if (static_cast<std::size_t>(pixel_format) < |
| 219 | static_cast<std::size_t>(PixelFormat::MaxStencilFormat)) { | ||
| 220 | return SurfaceType::Stencil; | ||
| 221 | } | ||
| 222 | |||
| 223 | if (static_cast<std::size_t>(pixel_format) < | ||
| 217 | static_cast<std::size_t>(PixelFormat::MaxDepthStencilFormat)) { | 224 | static_cast<std::size_t>(PixelFormat::MaxDepthStencilFormat)) { |
| 218 | return SurfaceType::DepthStencil; | 225 | return SurfaceType::DepthStencil; |
| 219 | } | 226 | } |
diff --git a/src/video_core/surface.h b/src/video_core/surface.h index 2ce7c7d33..33e8d24ab 100644 --- a/src/video_core/surface.h +++ b/src/video_core/surface.h | |||
| @@ -110,8 +110,12 @@ enum class PixelFormat { | |||
| 110 | 110 | ||
| 111 | MaxDepthFormat, | 111 | MaxDepthFormat, |
| 112 | 112 | ||
| 113 | // Stencil formats | ||
| 114 | S8_UINT = MaxDepthFormat, | ||
| 115 | MaxStencilFormat, | ||
| 116 | |||
| 113 | // DepthStencil formats | 117 | // DepthStencil formats |
| 114 | D24_UNORM_S8_UINT = MaxDepthFormat, | 118 | D24_UNORM_S8_UINT = MaxStencilFormat, |
| 115 | S8_UINT_D24_UNORM, | 119 | S8_UINT_D24_UNORM, |
| 116 | D32_FLOAT_S8_UINT, | 120 | D32_FLOAT_S8_UINT, |
| 117 | 121 | ||
| @@ -125,8 +129,9 @@ constexpr std::size_t MaxPixelFormat = static_cast<std::size_t>(PixelFormat::Max | |||
| 125 | enum class SurfaceType { | 129 | enum class SurfaceType { |
| 126 | ColorTexture = 0, | 130 | ColorTexture = 0, |
| 127 | Depth = 1, | 131 | Depth = 1, |
| 128 | DepthStencil = 2, | 132 | Stencil = 2, |
| 129 | Invalid = 3, | 133 | DepthStencil = 3, |
| 134 | Invalid = 4, | ||
| 130 | }; | 135 | }; |
| 131 | 136 | ||
| 132 | enum class SurfaceTarget { | 137 | enum class SurfaceTarget { |
| @@ -229,6 +234,7 @@ constexpr std::array<u32, MaxPixelFormat> BLOCK_WIDTH_TABLE = {{ | |||
| 229 | 1, // E5B9G9R9_FLOAT | 234 | 1, // E5B9G9R9_FLOAT |
| 230 | 1, // D32_FLOAT | 235 | 1, // D32_FLOAT |
| 231 | 1, // D16_UNORM | 236 | 1, // D16_UNORM |
| 237 | 1, // S8_UINT | ||
| 232 | 1, // D24_UNORM_S8_UINT | 238 | 1, // D24_UNORM_S8_UINT |
| 233 | 1, // S8_UINT_D24_UNORM | 239 | 1, // S8_UINT_D24_UNORM |
| 234 | 1, // D32_FLOAT_S8_UINT | 240 | 1, // D32_FLOAT_S8_UINT |
| @@ -328,6 +334,7 @@ constexpr std::array<u32, MaxPixelFormat> BLOCK_HEIGHT_TABLE = {{ | |||
| 328 | 1, // E5B9G9R9_FLOAT | 334 | 1, // E5B9G9R9_FLOAT |
| 329 | 1, // D32_FLOAT | 335 | 1, // D32_FLOAT |
| 330 | 1, // D16_UNORM | 336 | 1, // D16_UNORM |
| 337 | 1, // S8_UINT | ||
| 331 | 1, // D24_UNORM_S8_UINT | 338 | 1, // D24_UNORM_S8_UINT |
| 332 | 1, // S8_UINT_D24_UNORM | 339 | 1, // S8_UINT_D24_UNORM |
| 333 | 1, // D32_FLOAT_S8_UINT | 340 | 1, // D32_FLOAT_S8_UINT |
| @@ -427,6 +434,7 @@ constexpr std::array<u32, MaxPixelFormat> BITS_PER_BLOCK_TABLE = {{ | |||
| 427 | 32, // E5B9G9R9_FLOAT | 434 | 32, // E5B9G9R9_FLOAT |
| 428 | 32, // D32_FLOAT | 435 | 32, // D32_FLOAT |
| 429 | 16, // D16_UNORM | 436 | 16, // D16_UNORM |
| 437 | 8, // S8_UINT | ||
| 430 | 32, // D24_UNORM_S8_UINT | 438 | 32, // D24_UNORM_S8_UINT |
| 431 | 32, // S8_UINT_D24_UNORM | 439 | 32, // S8_UINT_D24_UNORM |
| 432 | 64, // D32_FLOAT_S8_UINT | 440 | 64, // D32_FLOAT_S8_UINT |
diff --git a/src/video_core/texture_cache/formatter.h b/src/video_core/texture_cache/formatter.h index c6cf0583f..b2c81057b 100644 --- a/src/video_core/texture_cache/formatter.h +++ b/src/video_core/texture_cache/formatter.h | |||
| @@ -194,6 +194,8 @@ struct fmt::formatter<VideoCore::Surface::PixelFormat> : fmt::formatter<fmt::str | |||
| 194 | return "D32_FLOAT"; | 194 | return "D32_FLOAT"; |
| 195 | case PixelFormat::D16_UNORM: | 195 | case PixelFormat::D16_UNORM: |
| 196 | return "D16_UNORM"; | 196 | return "D16_UNORM"; |
| 197 | case PixelFormat::S8_UINT: | ||
| 198 | return "S8_UINT"; | ||
| 197 | case PixelFormat::D24_UNORM_S8_UINT: | 199 | case PixelFormat::D24_UNORM_S8_UINT: |
| 198 | return "D24_UNORM_S8_UINT"; | 200 | return "D24_UNORM_S8_UINT"; |
| 199 | case PixelFormat::S8_UINT_D24_UNORM: | 201 | case PixelFormat::S8_UINT_D24_UNORM: |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 4d2874bf2..44a0d42ba 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -475,6 +475,7 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 475 | const BlitImages images = GetBlitImages(dst, src); | 475 | const BlitImages images = GetBlitImages(dst, src); |
| 476 | const ImageId dst_id = images.dst_id; | 476 | const ImageId dst_id = images.dst_id; |
| 477 | const ImageId src_id = images.src_id; | 477 | const ImageId src_id = images.src_id; |
| 478 | |||
| 478 | PrepareImage(src_id, false, false); | 479 | PrepareImage(src_id, false, false); |
| 479 | PrepareImage(dst_id, true, false); | 480 | PrepareImage(dst_id, true, false); |
| 480 | 481 | ||
| @@ -758,7 +759,8 @@ ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr, | |||
| 758 | return ImageId{}; | 759 | return ImageId{}; |
| 759 | } | 760 | } |
| 760 | } | 761 | } |
| 761 | const bool broken_views = runtime.HasBrokenTextureViewFormats(); | 762 | const bool broken_views = |
| 763 | runtime.HasBrokenTextureViewFormats() || True(options & RelaxedOptions::ForceBrokenViews); | ||
| 762 | const bool native_bgr = runtime.HasNativeBgr(); | 764 | const bool native_bgr = runtime.HasNativeBgr(); |
| 763 | ImageId image_id; | 765 | ImageId image_id; |
| 764 | const auto lambda = [&](ImageId existing_image_id, ImageBase& existing_image) { | 766 | const auto lambda = [&](ImageId existing_image_id, ImageBase& existing_image) { |
| @@ -1094,12 +1096,13 @@ typename TextureCache<P>::BlitImages TextureCache<P>::GetBlitImages( | |||
| 1094 | if (GetFormatType(dst_info.format) != GetFormatType(src_info.format)) { | 1096 | if (GetFormatType(dst_info.format) != GetFormatType(src_info.format)) { |
| 1095 | continue; | 1097 | continue; |
| 1096 | } | 1098 | } |
| 1097 | if (!dst_id) { | 1099 | RelaxedOptions find_options{}; |
| 1098 | dst_id = InsertImage(dst_info, dst_addr, RelaxedOptions{}); | 1100 | if (src_info.num_samples > 1) { |
| 1099 | } | 1101 | // it's a resolve, we must enforce the same format. |
| 1100 | if (!src_id) { | 1102 | find_options = RelaxedOptions::ForceBrokenViews; |
| 1101 | src_id = InsertImage(src_info, src_addr, RelaxedOptions{}); | ||
| 1102 | } | 1103 | } |
| 1104 | src_id = FindOrInsertImage(src_info, src_addr, find_options); | ||
| 1105 | dst_id = FindOrInsertImage(dst_info, dst_addr, find_options); | ||
| 1103 | } while (has_deleted_images); | 1106 | } while (has_deleted_images); |
| 1104 | return BlitImages{ | 1107 | return BlitImages{ |
| 1105 | .dst_id = dst_id, | 1108 | .dst_id = dst_id, |
| @@ -1759,6 +1762,9 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag | |||
| 1759 | } | 1762 | } |
| 1760 | UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D); | 1763 | UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D); |
| 1761 | UNIMPLEMENTED_IF(src.info.type != ImageType::e2D); | 1764 | UNIMPLEMENTED_IF(src.info.type != ImageType::e2D); |
| 1765 | if (runtime.ShouldReinterpret(dst, src)) { | ||
| 1766 | return runtime.ReinterpretImage(dst, src, copies); | ||
| 1767 | } | ||
| 1762 | for (const ImageCopy& copy : copies) { | 1768 | for (const ImageCopy& copy : copies) { |
| 1763 | UNIMPLEMENTED_IF(copy.dst_subresource.num_layers != 1); | 1769 | UNIMPLEMENTED_IF(copy.dst_subresource.num_layers != 1); |
| 1764 | UNIMPLEMENTED_IF(copy.src_subresource.num_layers != 1); | 1770 | UNIMPLEMENTED_IF(copy.src_subresource.num_layers != 1); |
diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h index 5c274abdf..5ac27b3a7 100644 --- a/src/video_core/texture_cache/types.h +++ b/src/video_core/texture_cache/types.h | |||
| @@ -54,6 +54,7 @@ enum class RelaxedOptions : u32 { | |||
| 54 | Size = 1 << 0, | 54 | Size = 1 << 0, |
| 55 | Format = 1 << 1, | 55 | Format = 1 << 1, |
| 56 | Samples = 1 << 2, | 56 | Samples = 1 << 2, |
| 57 | ForceBrokenViews = 1 << 3, | ||
| 57 | }; | 58 | }; |
| 58 | DECLARE_ENUM_FLAG_OPERATORS(RelaxedOptions) | 59 | DECLARE_ENUM_FLAG_OPERATORS(RelaxedOptions) |
| 59 | 60 | ||
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index ddc9fb13a..e4d82631e 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp | |||
| @@ -1151,18 +1151,39 @@ bool IsSubresource(const ImageInfo& candidate, const ImageBase& image, GPUVAddr | |||
| 1151 | 1151 | ||
| 1152 | void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst, | 1152 | void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst, |
| 1153 | const ImageBase* src) { | 1153 | const ImageBase* src) { |
| 1154 | if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) { | 1154 | bool is_resolve = false; |
| 1155 | src_info.format = src->info.format; | 1155 | const auto original_src_format = src_info.format; |
| 1156 | const auto original_dst_format = dst_info.format; | ||
| 1157 | if (src) { | ||
| 1158 | if (GetFormatType(src->info.format) != SurfaceType::ColorTexture) { | ||
| 1159 | src_info.format = src->info.format; | ||
| 1160 | } | ||
| 1161 | is_resolve = src->info.num_samples > 1; | ||
| 1162 | src_info.num_samples = src->info.num_samples; | ||
| 1163 | src_info.size = src->info.size; | ||
| 1156 | } | 1164 | } |
| 1157 | if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { | 1165 | if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { |
| 1158 | dst_info.format = dst->info.format; | 1166 | dst_info.format = dst->info.format; |
| 1159 | } | 1167 | } |
| 1160 | if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) { | 1168 | if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) { |
| 1161 | dst_info.format = src->info.format; | 1169 | if (dst) { |
| 1170 | if (GetFormatType(dst->info.format) == SurfaceType::ColorTexture) { | ||
| 1171 | src_info.format = original_src_format; | ||
| 1172 | } | ||
| 1173 | } else { | ||
| 1174 | dst_info.format = src->info.format; | ||
| 1175 | } | ||
| 1162 | } | 1176 | } |
| 1163 | if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { | 1177 | if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { |
| 1164 | src_info.format = dst->info.format; | 1178 | if (src) { |
| 1179 | if (GetFormatType(src->info.format) == SurfaceType::ColorTexture) { | ||
| 1180 | dst_info.format = original_dst_format; | ||
| 1181 | } | ||
| 1182 | } else { | ||
| 1183 | src_info.format = dst->info.format; | ||
| 1184 | } | ||
| 1165 | } | 1185 | } |
| 1186 | ASSERT(!is_resolve || dst_info.format == src_info.format); | ||
| 1166 | } | 1187 | } |
| 1167 | 1188 | ||
| 1168 | u32 MapSizeBytes(const ImageBase& image) { | 1189 | u32 MapSizeBytes(const ImageBase& image) { |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 95106f88f..70c52aaac 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -21,6 +21,13 @@ | |||
| 21 | namespace Vulkan { | 21 | namespace Vulkan { |
| 22 | namespace { | 22 | namespace { |
| 23 | namespace Alternatives { | 23 | namespace Alternatives { |
| 24 | constexpr std::array STENCIL8_UINT{ | ||
| 25 | VK_FORMAT_D16_UNORM_S8_UINT, | ||
| 26 | VK_FORMAT_D24_UNORM_S8_UINT, | ||
| 27 | VK_FORMAT_D32_SFLOAT_S8_UINT, | ||
| 28 | VK_FORMAT_UNDEFINED, | ||
| 29 | }; | ||
| 30 | |||
| 24 | constexpr std::array DEPTH24_UNORM_STENCIL8_UINT{ | 31 | constexpr std::array DEPTH24_UNORM_STENCIL8_UINT{ |
| 25 | VK_FORMAT_D32_SFLOAT_S8_UINT, | 32 | VK_FORMAT_D32_SFLOAT_S8_UINT, |
| 26 | VK_FORMAT_D16_UNORM_S8_UINT, | 33 | VK_FORMAT_D16_UNORM_S8_UINT, |
| @@ -74,6 +81,8 @@ void SetNext(void**& next, T& data) { | |||
| 74 | 81 | ||
| 75 | constexpr const VkFormat* GetFormatAlternatives(VkFormat format) { | 82 | constexpr const VkFormat* GetFormatAlternatives(VkFormat format) { |
| 76 | switch (format) { | 83 | switch (format) { |
| 84 | case VK_FORMAT_S8_UINT: | ||
| 85 | return Alternatives::STENCIL8_UINT.data(); | ||
| 77 | case VK_FORMAT_D24_UNORM_S8_UINT: | 86 | case VK_FORMAT_D24_UNORM_S8_UINT: |
| 78 | return Alternatives::DEPTH24_UNORM_STENCIL8_UINT.data(); | 87 | return Alternatives::DEPTH24_UNORM_STENCIL8_UINT.data(); |
| 79 | case VK_FORMAT_D16_UNORM_S8_UINT: | 88 | case VK_FORMAT_D16_UNORM_S8_UINT: |
| @@ -145,6 +154,7 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(vk::Physica | |||
| 145 | VK_FORMAT_R4G4B4A4_UNORM_PACK16, | 154 | VK_FORMAT_R4G4B4A4_UNORM_PACK16, |
| 146 | VK_FORMAT_D32_SFLOAT, | 155 | VK_FORMAT_D32_SFLOAT, |
| 147 | VK_FORMAT_D16_UNORM, | 156 | VK_FORMAT_D16_UNORM, |
| 157 | VK_FORMAT_S8_UINT, | ||
| 148 | VK_FORMAT_D16_UNORM_S8_UINT, | 158 | VK_FORMAT_D16_UNORM_S8_UINT, |
| 149 | VK_FORMAT_D24_UNORM_S8_UINT, | 159 | VK_FORMAT_D24_UNORM_S8_UINT, |
| 150 | VK_FORMAT_D32_SFLOAT_S8_UINT, | 160 | VK_FORMAT_D32_SFLOAT_S8_UINT, |
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index 660b68c1c..9241678e4 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui | |||
| @@ -429,7 +429,7 @@ | |||
| 429 | </item> | 429 | </item> |
| 430 | <item> | 430 | <item> |
| 431 | <property name="text"> | 431 | <property name="text"> |
| 432 | <string>AMD's FidelityFX™️ Super Resolution [Vulkan Only]</string> | 432 | <string>AMD FidelityFX™️ Super Resolution [Vulkan Only]</string> |
| 433 | </property> | 433 | </property> |
| 434 | </item> | 434 | </item> |
| 435 | </widget> | 435 | </widget> |
diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp index d4e97fa16..e7e58f314 100644 --- a/src/yuzu/hotkeys.cpp +++ b/src/yuzu/hotkeys.cpp | |||
| @@ -46,6 +46,8 @@ QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action | |||
| 46 | if (!hk.shortcut) | 46 | if (!hk.shortcut) |
| 47 | hk.shortcut = new QShortcut(hk.keyseq, widget, nullptr, nullptr, hk.context); | 47 | hk.shortcut = new QShortcut(hk.keyseq, widget, nullptr, nullptr, hk.context); |
| 48 | 48 | ||
| 49 | hk.shortcut->setAutoRepeat(false); | ||
| 50 | |||
| 49 | return hk.shortcut; | 51 | return hk.shortcut; |
| 50 | } | 52 | } |
| 51 | 53 | ||
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index d057dc889..c4c76b094 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -1031,7 +1031,7 @@ void GMainWindow::InitializeHotkeys() { | |||
| 1031 | &QShortcut::activatedAmbiguously, ui->action_Fullscreen, &QAction::trigger); | 1031 | &QShortcut::activatedAmbiguously, ui->action_Fullscreen, &QAction::trigger); |
| 1032 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Exit Fullscreen"), this), | 1032 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Exit Fullscreen"), this), |
| 1033 | &QShortcut::activated, this, [&] { | 1033 | &QShortcut::activated, this, [&] { |
| 1034 | if (emulation_running) { | 1034 | if (emulation_running && ui->action_Fullscreen->isChecked()) { |
| 1035 | ui->action_Fullscreen->setChecked(false); | 1035 | ui->action_Fullscreen->setChecked(false); |
| 1036 | ToggleFullscreen(); | 1036 | ToggleFullscreen(); |
| 1037 | } | 1037 | } |
| @@ -3106,7 +3106,7 @@ void GMainWindow::UpdateFilterText() { | |||
| 3106 | filter_status_button->setText(tr("SCALEFORCE")); | 3106 | filter_status_button->setText(tr("SCALEFORCE")); |
| 3107 | break; | 3107 | break; |
| 3108 | case Settings::ScalingFilter::Fsr: | 3108 | case Settings::ScalingFilter::Fsr: |
| 3109 | filter_status_button->setText(tr("AMD'S FIDELITYFX SR")); | 3109 | filter_status_button->setText(tr("FSR")); |
| 3110 | break; | 3110 | break; |
| 3111 | default: | 3111 | default: |
| 3112 | filter_status_button->setText(tr("BILINEAR")); | 3112 | filter_status_button->setText(tr("BILINEAR")); |
| @@ -3117,15 +3117,15 @@ void GMainWindow::UpdateFilterText() { | |||
| 3117 | void GMainWindow::UpdateAAText() { | 3117 | void GMainWindow::UpdateAAText() { |
| 3118 | const auto aa_mode = Settings::values.anti_aliasing.GetValue(); | 3118 | const auto aa_mode = Settings::values.anti_aliasing.GetValue(); |
| 3119 | switch (aa_mode) { | 3119 | switch (aa_mode) { |
| 3120 | case Settings::AntiAliasing::Fxaa: | ||
| 3121 | aa_status_button->setText(tr("FXAA")); | ||
| 3122 | break; | ||
| 3123 | case Settings::AntiAliasing::None: | 3120 | case Settings::AntiAliasing::None: |
| 3124 | aa_status_button->setText(tr("NO AA")); | 3121 | aa_status_button->setText(tr("NO AA")); |
| 3125 | break; | 3122 | break; |
| 3126 | default: | 3123 | case Settings::AntiAliasing::Fxaa: |
| 3127 | aa_status_button->setText(tr("FXAA")); | 3124 | aa_status_button->setText(tr("FXAA")); |
| 3128 | break; | 3125 | break; |
| 3126 | default: | ||
| 3127 | aa_status_button->setText(tr("NO AA")); | ||
| 3128 | break; | ||
| 3129 | } | 3129 | } |
| 3130 | } | 3130 | } |
| 3131 | 3131 | ||
| @@ -3300,9 +3300,9 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { | |||
| 3300 | if (!errors.isEmpty()) { | 3300 | if (!errors.isEmpty()) { |
| 3301 | QMessageBox::warning( | 3301 | QMessageBox::warning( |
| 3302 | this, tr("Derivation Components Missing"), | 3302 | this, tr("Derivation Components Missing"), |
| 3303 | tr("Components are missing that may hinder key derivation from completing. " | 3303 | tr("Encryption keys are missing. " |
| 3304 | "<br>Please follow <a href='https://yuzu-emu.org/help/quickstart/'>the yuzu " | 3304 | "<br>Please follow <a href='https://yuzu-emu.org/help/quickstart/'>the yuzu " |
| 3305 | "quickstart guide</a> to get all your keys and " | 3305 | "quickstart guide</a> to get all your keys, firmware and " |
| 3306 | "games.<br><br><small>(%1)</small>") | 3306 | "games.<br><br><small>(%1)</small>") |
| 3307 | .arg(errors)); | 3307 | .arg(errors)); |
| 3308 | } | 3308 | } |