diff options
106 files changed, 3239 insertions, 2247 deletions
diff --git a/.ci/scripts/linux/docker.sh b/.ci/scripts/linux/docker.sh index 5559a527c..277775ef6 100755 --- a/.ci/scripts/linux/docker.sh +++ b/.ci/scripts/linux/docker.sh | |||
| @@ -5,7 +5,7 @@ cd /yuzu | |||
| 5 | ccache -s | 5 | ccache -s |
| 6 | 6 | ||
| 7 | mkdir build || true && cd build | 7 | mkdir build || true && cd build |
| 8 | cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON | 8 | cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON |
| 9 | 9 | ||
| 10 | ninja | 10 | ninja |
| 11 | 11 | ||
diff --git a/.ci/scripts/windows/docker.sh b/.ci/scripts/windows/docker.sh index d53281741..adfd636fa 100755 --- a/.ci/scripts/windows/docker.sh +++ b/.ci/scripts/windows/docker.sh | |||
| @@ -5,7 +5,7 @@ cd /yuzu | |||
| 5 | ccache -s | 5 | ccache -s |
| 6 | 6 | ||
| 7 | mkdir build || true && cd build | 7 | mkdir build || true && cd build |
| 8 | cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_UNICORN=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release | 8 | cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_UNICORN=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON |
| 9 | ninja | 9 | ninja |
| 10 | 10 | ||
| 11 | ccache -s | 11 | ccache -s |
diff --git a/CMakeLists.txt b/CMakeLists.txt index ce46a2c2b..7a49318aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -13,6 +13,7 @@ project(yuzu) | |||
| 13 | option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) | 13 | option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) |
| 14 | 14 | ||
| 15 | option(ENABLE_QT "Enable the Qt frontend" ON) | 15 | option(ENABLE_QT "Enable the Qt frontend" ON) |
| 16 | option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) | ||
| 16 | CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "ENABLE_QT;MSVC" OFF) | 17 | CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "ENABLE_QT;MSVC" OFF) |
| 17 | 18 | ||
| 18 | option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) | 19 | option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) |
| @@ -224,6 +225,10 @@ if(ENABLE_QT) | |||
| 224 | if (YUZU_USE_QT_WEB_ENGINE) | 225 | if (YUZU_USE_QT_WEB_ENGINE) |
| 225 | find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets) | 226 | find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets) |
| 226 | endif() | 227 | endif() |
| 228 | |||
| 229 | if (ENABLE_QT_TRANSLATION) | ||
| 230 | find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT}) | ||
| 231 | endif() | ||
| 227 | if (NOT Qt5_FOUND) | 232 | if (NOT Qt5_FOUND) |
| 228 | list(APPEND CONAN_REQUIRED_LIBS "qt/5.14.1@bincrafters/stable") | 233 | list(APPEND CONAN_REQUIRED_LIBS "qt/5.14.1@bincrafters/stable") |
| 229 | endif() | 234 | endif() |
| @@ -24,6 +24,8 @@ Most of the development happens on GitHub. It's also where [our central reposito | |||
| 24 | 24 | ||
| 25 | If you want to contribute please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator. | 25 | If you want to contribute please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator. |
| 26 | 26 | ||
| 27 | If you want to contribute to the user interface translation, please check out the [yuzu project on transifex](https://www.transifex.com/yuzu-emulator/yuzu). We centralize translation work there, and periodically upstream translations. | ||
| 28 | |||
| 27 | ### Building | 29 | ### Building |
| 28 | 30 | ||
| 29 | * __Windows__: [Windows Build](https://github.com/yuzu-emu/yuzu/wiki/Building-For-Windows) | 31 | * __Windows__: [Windows Build](https://github.com/yuzu-emu/yuzu/wiki/Building-For-Windows) |
diff --git a/dist/languages/.gitignore b/dist/languages/.gitignore new file mode 100644 index 000000000..27e5a0158 --- /dev/null +++ b/dist/languages/.gitignore | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | # Ignore the source language file | ||
| 2 | en.ts | ||
diff --git a/dist/languages/.tx/config b/dist/languages/.tx/config new file mode 100644 index 000000000..0d9b512ea --- /dev/null +++ b/dist/languages/.tx/config | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | [main] | ||
| 2 | host = https://www.transifex.com | ||
| 3 | |||
| 4 | [yuzu.emulator] | ||
| 5 | file_filter = <lang>.ts | ||
| 6 | source_file = en.ts | ||
| 7 | source_lang = en | ||
| 8 | type = QT | ||
diff --git a/dist/languages/README.md b/dist/languages/README.md new file mode 100644 index 000000000..61981ab1d --- /dev/null +++ b/dist/languages/README.md | |||
| @@ -0,0 +1 @@ | |||
| This directory stores translation patches (TS files) for yuzu Qt frontend. This directory is linked with [yuzu project on transifex](https://www.transifex.com/yuzu-emulator/yuzu), so you can update the translation by executing `tx pull -a`. If you want to contribute to the translation, please go the transifex link and submit your translation there. This directory on the main repo will be synchronized with transifex periodically. Do not directly open PRs on github to modify the translation. | |||
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index aab3e979a..f80ab92e4 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp | |||
| @@ -38,7 +38,7 @@ Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format fo | |||
| 38 | sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} { | 38 | sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} { |
| 39 | 39 | ||
| 40 | release_event = Core::Timing::CreateEvent( | 40 | release_event = Core::Timing::CreateEvent( |
| 41 | name, [this](u64 userdata, s64 cycles_late) { ReleaseActiveBuffer(cycles_late); }); | 41 | name, [this](u64, std::chrono::nanoseconds ns_late) { ReleaseActiveBuffer(ns_late); }); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | void Stream::Play() { | 44 | void Stream::Play() { |
| @@ -59,11 +59,9 @@ Stream::State Stream::GetState() const { | |||
| 59 | return state; | 59 | return state; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | s64 Stream::GetBufferReleaseNS(const Buffer& buffer) const { | 62 | std::chrono::nanoseconds Stream::GetBufferReleaseNS(const Buffer& buffer) const { |
| 63 | const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()}; | 63 | const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()}; |
| 64 | const auto ns = | 64 | return std::chrono::nanoseconds((static_cast<u64>(num_samples) * 1000000000ULL) / sample_rate); |
| 65 | std::chrono::nanoseconds((static_cast<u64>(num_samples) * 1000000000ULL) / sample_rate); | ||
| 66 | return ns.count(); | ||
| 67 | } | 65 | } |
| 68 | 66 | ||
| 69 | static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) { | 67 | static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) { |
| @@ -80,7 +78,7 @@ static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) { | |||
| 80 | } | 78 | } |
| 81 | } | 79 | } |
| 82 | 80 | ||
| 83 | void Stream::PlayNextBuffer(s64 cycles_late) { | 81 | void Stream::PlayNextBuffer(std::chrono::nanoseconds ns_late) { |
| 84 | if (!IsPlaying()) { | 82 | if (!IsPlaying()) { |
| 85 | // Ensure we are in playing state before playing the next buffer | 83 | // Ensure we are in playing state before playing the next buffer |
| 86 | sink_stream.Flush(); | 84 | sink_stream.Flush(); |
| @@ -105,17 +103,18 @@ void Stream::PlayNextBuffer(s64 cycles_late) { | |||
| 105 | 103 | ||
| 106 | sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples()); | 104 | sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples()); |
| 107 | 105 | ||
| 108 | core_timing.ScheduleEvent( | 106 | const auto time_stretch_delta = Settings::values.enable_audio_stretching.GetValue() |
| 109 | GetBufferReleaseNS(*active_buffer) - | 107 | ? std::chrono::nanoseconds::zero() |
| 110 | (Settings::values.enable_audio_stretching.GetValue() ? 0 : cycles_late), | 108 | : ns_late; |
| 111 | release_event, {}); | 109 | const auto future_time = GetBufferReleaseNS(*active_buffer) - time_stretch_delta; |
| 110 | core_timing.ScheduleEvent(future_time, release_event, {}); | ||
| 112 | } | 111 | } |
| 113 | 112 | ||
| 114 | void Stream::ReleaseActiveBuffer(s64 cycles_late) { | 113 | void Stream::ReleaseActiveBuffer(std::chrono::nanoseconds ns_late) { |
| 115 | ASSERT(active_buffer); | 114 | ASSERT(active_buffer); |
| 116 | released_buffers.push(std::move(active_buffer)); | 115 | released_buffers.push(std::move(active_buffer)); |
| 117 | release_callback(); | 116 | release_callback(); |
| 118 | PlayNextBuffer(cycles_late); | 117 | PlayNextBuffer(ns_late); |
| 119 | } | 118 | } |
| 120 | 119 | ||
| 121 | bool Stream::QueueBuffer(BufferPtr&& buffer) { | 120 | bool Stream::QueueBuffer(BufferPtr&& buffer) { |
diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h index 524376257..6437b8591 100644 --- a/src/audio_core/stream.h +++ b/src/audio_core/stream.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <chrono> | ||
| 7 | #include <functional> | 8 | #include <functional> |
| 8 | #include <memory> | 9 | #include <memory> |
| 9 | #include <string> | 10 | #include <string> |
| @@ -90,16 +91,13 @@ public: | |||
| 90 | 91 | ||
| 91 | private: | 92 | private: |
| 92 | /// Plays the next queued buffer in the audio stream, starting playback if necessary | 93 | /// Plays the next queued buffer in the audio stream, starting playback if necessary |
| 93 | void PlayNextBuffer(s64 cycles_late = 0); | 94 | void PlayNextBuffer(std::chrono::nanoseconds ns_late = {}); |
| 94 | 95 | ||
| 95 | /// Releases the actively playing buffer, signalling that it has been completed | 96 | /// Releases the actively playing buffer, signalling that it has been completed |
| 96 | void ReleaseActiveBuffer(s64 cycles_late = 0); | 97 | void ReleaseActiveBuffer(std::chrono::nanoseconds ns_late = {}); |
| 97 | 98 | ||
| 98 | /// Gets the number of core cycles when the specified buffer will be released | 99 | /// Gets the number of core cycles when the specified buffer will be released |
| 99 | s64 GetBufferReleaseNS(const Buffer& buffer) const; | 100 | std::chrono::nanoseconds GetBufferReleaseNS(const Buffer& buffer) const; |
| 100 | |||
| 101 | /// Gets the number of core cycles when the specified buffer will be released | ||
| 102 | s64 GetBufferReleaseNSHostTiming(const Buffer& buffer) const; | ||
| 103 | 101 | ||
| 104 | u32 sample_rate; ///< Sample rate of the stream | 102 | u32 sample_rate; ///< Sample rate of the stream |
| 105 | Format format; ///< Format of the stream | 103 | Format format; ///< Format of the stream |
diff --git a/src/common/alignment.h b/src/common/alignment.h index b37044bb6..ef4d6f896 100644 --- a/src/common/alignment.h +++ b/src/common/alignment.h | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | #pragma once | 3 | #pragma once |
| 4 | 4 | ||
| 5 | #include <cstddef> | 5 | #include <cstddef> |
| 6 | #include <memory> | 6 | #include <new> |
| 7 | #include <type_traits> | 7 | #include <type_traits> |
| 8 | 8 | ||
| 9 | namespace Common { | 9 | namespace Common { |
| @@ -54,66 +54,28 @@ public: | |||
| 54 | using size_type = std::size_t; | 54 | using size_type = std::size_t; |
| 55 | using difference_type = std::ptrdiff_t; | 55 | using difference_type = std::ptrdiff_t; |
| 56 | 56 | ||
| 57 | using pointer = T*; | ||
| 58 | using const_pointer = const T*; | ||
| 59 | |||
| 60 | using reference = T&; | ||
| 61 | using const_reference = const T&; | ||
| 62 | |||
| 63 | using propagate_on_container_copy_assignment = std::true_type; | 57 | using propagate_on_container_copy_assignment = std::true_type; |
| 64 | using propagate_on_container_move_assignment = std::true_type; | 58 | using propagate_on_container_move_assignment = std::true_type; |
| 65 | using propagate_on_container_swap = std::true_type; | 59 | using propagate_on_container_swap = std::true_type; |
| 66 | using is_always_equal = std::true_type; | 60 | using is_always_equal = std::true_type; |
| 67 | 61 | ||
| 68 | public: | ||
| 69 | constexpr AlignmentAllocator() noexcept = default; | 62 | constexpr AlignmentAllocator() noexcept = default; |
| 70 | 63 | ||
| 71 | template <typename T2> | 64 | template <typename T2> |
| 72 | constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {} | 65 | constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {} |
| 73 | 66 | ||
| 74 | pointer address(reference r) noexcept { | 67 | T* allocate(size_type n) { |
| 75 | return std::addressof(r); | 68 | return static_cast<T*>(::operator new (n * sizeof(T), std::align_val_t{Align})); |
| 76 | } | ||
| 77 | |||
| 78 | const_pointer address(const_reference r) const noexcept { | ||
| 79 | return std::addressof(r); | ||
| 80 | } | ||
| 81 | |||
| 82 | pointer allocate(size_type n) { | ||
| 83 | return static_cast<pointer>(::operator new (n, std::align_val_t{Align})); | ||
| 84 | } | ||
| 85 | |||
| 86 | void deallocate(pointer p, size_type) { | ||
| 87 | ::operator delete (p, std::align_val_t{Align}); | ||
| 88 | } | 69 | } |
| 89 | 70 | ||
| 90 | void construct(pointer p, const value_type& wert) { | 71 | void deallocate(T* p, size_type n) { |
| 91 | new (p) value_type(wert); | 72 | ::operator delete (p, n * sizeof(T), std::align_val_t{Align}); |
| 92 | } | ||
| 93 | |||
| 94 | void destroy(pointer p) { | ||
| 95 | p->~value_type(); | ||
| 96 | } | ||
| 97 | |||
| 98 | size_type max_size() const noexcept { | ||
| 99 | return size_type(-1) / sizeof(value_type); | ||
| 100 | } | 73 | } |
| 101 | 74 | ||
| 102 | template <typename T2> | 75 | template <typename T2> |
| 103 | struct rebind { | 76 | struct rebind { |
| 104 | using other = AlignmentAllocator<T2, Align>; | 77 | using other = AlignmentAllocator<T2, Align>; |
| 105 | }; | 78 | }; |
| 106 | |||
| 107 | bool operator!=(const AlignmentAllocator<T, Align>& other) const noexcept { | ||
| 108 | return !(*this == other); | ||
| 109 | } | ||
| 110 | |||
| 111 | // Returns true if and only if storage allocated from *this | ||
| 112 | // can be deallocated from other, and vice versa. | ||
| 113 | // Always returns true for stateless allocators. | ||
| 114 | bool operator==(const AlignmentAllocator<T, Align>& other) const noexcept { | ||
| 115 | return true; | ||
| 116 | } | ||
| 117 | }; | 79 | }; |
| 118 | 80 | ||
| 119 | } // namespace Common | 81 | } // namespace Common |
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index a63e60461..b5feb3f24 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -53,12 +53,12 @@ void CoreTiming::ThreadEntry(CoreTiming& instance) { | |||
| 53 | instance.ThreadLoop(); | 53 | instance.ThreadLoop(); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | void CoreTiming::Initialize(std::function<void(void)>&& on_thread_init_) { | 56 | void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) { |
| 57 | on_thread_init = std::move(on_thread_init_); | 57 | on_thread_init = std::move(on_thread_init_); |
| 58 | event_fifo_id = 0; | 58 | event_fifo_id = 0; |
| 59 | shutting_down = false; | 59 | shutting_down = false; |
| 60 | ticks = 0; | 60 | ticks = 0; |
| 61 | const auto empty_timed_callback = [](u64, s64) {}; | 61 | const auto empty_timed_callback = [](u64, std::chrono::nanoseconds) {}; |
| 62 | ev_lost = CreateEvent("_lost_event", empty_timed_callback); | 62 | ev_lost = CreateEvent("_lost_event", empty_timed_callback); |
| 63 | if (is_multicore) { | 63 | if (is_multicore) { |
| 64 | timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); | 64 | timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); |
| @@ -106,11 +106,11 @@ bool CoreTiming::HasPendingEvents() const { | |||
| 106 | return !(wait_set && event_queue.empty()); | 106 | return !(wait_set && event_queue.empty()); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | void CoreTiming::ScheduleEvent(s64 ns_into_future, const std::shared_ptr<EventType>& event_type, | 109 | void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future, |
| 110 | u64 userdata) { | 110 | const std::shared_ptr<EventType>& event_type, u64 userdata) { |
| 111 | { | 111 | { |
| 112 | std::scoped_lock scope{basic_lock}; | 112 | std::scoped_lock scope{basic_lock}; |
| 113 | const u64 timeout = static_cast<u64>(GetGlobalTimeNs().count() + ns_into_future); | 113 | const u64 timeout = static_cast<u64>((GetGlobalTimeNs() + ns_into_future).count()); |
| 114 | 114 | ||
| 115 | event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type}); | 115 | event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type}); |
| 116 | 116 | ||
| @@ -195,8 +195,9 @@ std::optional<s64> CoreTiming::Advance() { | |||
| 195 | event_queue.pop_back(); | 195 | event_queue.pop_back(); |
| 196 | basic_lock.unlock(); | 196 | basic_lock.unlock(); |
| 197 | 197 | ||
| 198 | if (auto event_type{evt.type.lock()}) { | 198 | if (const auto event_type{evt.type.lock()}) { |
| 199 | event_type->callback(evt.userdata, global_timer - evt.time); | 199 | event_type->callback( |
| 200 | evt.userdata, std::chrono::nanoseconds{static_cast<s64>(global_timer - evt.time)}); | ||
| 200 | } | 201 | } |
| 201 | 202 | ||
| 202 | basic_lock.lock(); | 203 | basic_lock.lock(); |
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 72faaab64..120c74e46 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -17,14 +17,12 @@ | |||
| 17 | #include "common/common_types.h" | 17 | #include "common/common_types.h" |
| 18 | #include "common/spin_lock.h" | 18 | #include "common/spin_lock.h" |
| 19 | #include "common/thread.h" | 19 | #include "common/thread.h" |
| 20 | #include "common/threadsafe_queue.h" | ||
| 21 | #include "common/wall_clock.h" | 20 | #include "common/wall_clock.h" |
| 22 | #include "core/hardware_properties.h" | ||
| 23 | 21 | ||
| 24 | namespace Core::Timing { | 22 | namespace Core::Timing { |
| 25 | 23 | ||
| 26 | /// A callback that may be scheduled for a particular core timing event. | 24 | /// A callback that may be scheduled for a particular core timing event. |
| 27 | using TimedCallback = std::function<void(u64 userdata, s64 cycles_late)>; | 25 | using TimedCallback = std::function<void(u64 userdata, std::chrono::nanoseconds ns_late)>; |
| 28 | 26 | ||
| 29 | /// Contains the characteristics of a particular event. | 27 | /// Contains the characteristics of a particular event. |
| 30 | struct EventType { | 28 | struct EventType { |
| @@ -42,12 +40,12 @@ struct EventType { | |||
| 42 | * in main CPU clock cycles. | 40 | * in main CPU clock cycles. |
| 43 | * | 41 | * |
| 44 | * To schedule an event, you first have to register its type. This is where you pass in the | 42 | * To schedule an event, you first have to register its type. This is where you pass in the |
| 45 | * callback. You then schedule events using the type id you get back. | 43 | * callback. You then schedule events using the type ID you get back. |
| 46 | * | 44 | * |
| 47 | * The int cyclesLate that the callbacks get is how many cycles late it was. | 45 | * The s64 ns_late that the callbacks get is how many ns late it was. |
| 48 | * So to schedule a new event on a regular basis: | 46 | * So to schedule a new event on a regular basis: |
| 49 | * inside callback: | 47 | * inside callback: |
| 50 | * ScheduleEvent(periodInCycles - cyclesLate, callback, "whatever") | 48 | * ScheduleEvent(period_in_ns - ns_late, callback, "whatever") |
| 51 | */ | 49 | */ |
| 52 | class CoreTiming { | 50 | class CoreTiming { |
| 53 | public: | 51 | public: |
| @@ -62,7 +60,7 @@ public: | |||
| 62 | 60 | ||
| 63 | /// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is | 61 | /// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is |
| 64 | /// required to end slice - 1 and start slice 0 before the first cycle of code is executed. | 62 | /// required to end slice - 1 and start slice 0 before the first cycle of code is executed. |
| 65 | void Initialize(std::function<void(void)>&& on_thread_init_); | 63 | void Initialize(std::function<void()>&& on_thread_init_); |
| 66 | 64 | ||
| 67 | /// Tears down all timing related functionality. | 65 | /// Tears down all timing related functionality. |
| 68 | void Shutdown(); | 66 | void Shutdown(); |
| @@ -95,8 +93,8 @@ public: | |||
| 95 | bool HasPendingEvents() const; | 93 | bool HasPendingEvents() const; |
| 96 | 94 | ||
| 97 | /// Schedules an event in core timing | 95 | /// Schedules an event in core timing |
| 98 | void ScheduleEvent(s64 ns_into_future, const std::shared_ptr<EventType>& event_type, | 96 | void ScheduleEvent(std::chrono::nanoseconds ns_into_future, |
| 99 | u64 userdata = 0); | 97 | const std::shared_ptr<EventType>& event_type, u64 userdata = 0); |
| 100 | 98 | ||
| 101 | void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata); | 99 | void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata); |
| 102 | 100 | ||
| @@ -141,8 +139,6 @@ private: | |||
| 141 | 139 | ||
| 142 | u64 global_timer = 0; | 140 | u64 global_timer = 0; |
| 143 | 141 | ||
| 144 | std::chrono::nanoseconds start_point; | ||
| 145 | |||
| 146 | // The queue is a min-heap using std::make_heap/push_heap/pop_heap. | 142 | // The queue is a min-heap using std::make_heap/push_heap/pop_heap. |
| 147 | // We don't use std::priority_queue because we need to be able to serialize, unserialize and | 143 | // We don't use std::priority_queue because we need to be able to serialize, unserialize and |
| 148 | // erase arbitrary events (RemoveEvent()) regardless of the queue order. These aren't | 144 | // erase arbitrary events (RemoveEvent()) regardless of the queue order. These aren't |
| @@ -161,7 +157,7 @@ private: | |||
| 161 | std::atomic<bool> wait_set{}; | 157 | std::atomic<bool> wait_set{}; |
| 162 | std::atomic<bool> shutting_down{}; | 158 | std::atomic<bool> shutting_down{}; |
| 163 | std::atomic<bool> has_started{}; | 159 | std::atomic<bool> has_started{}; |
| 164 | std::function<void(void)> on_thread_init{}; | 160 | std::function<void()> on_thread_init{}; |
| 165 | 161 | ||
| 166 | bool is_multicore{}; | 162 | bool is_multicore{}; |
| 167 | 163 | ||
diff --git a/src/core/file_sys/fsmitm_romfsbuild.cpp b/src/core/file_sys/fsmitm_romfsbuild.cpp index d126ae8dd..2aff2708a 100644 --- a/src/core/file_sys/fsmitm_romfsbuild.cpp +++ b/src/core/file_sys/fsmitm_romfsbuild.cpp | |||
| @@ -240,7 +240,7 @@ RomFSBuildContext::RomFSBuildContext(VirtualDir base_, VirtualDir ext_) | |||
| 240 | 240 | ||
| 241 | RomFSBuildContext::~RomFSBuildContext() = default; | 241 | RomFSBuildContext::~RomFSBuildContext() = default; |
| 242 | 242 | ||
| 243 | std::map<u64, VirtualFile> RomFSBuildContext::Build() { | 243 | std::multimap<u64, VirtualFile> RomFSBuildContext::Build() { |
| 244 | const u64 dir_hash_table_entry_count = romfs_get_hash_table_count(num_dirs); | 244 | const u64 dir_hash_table_entry_count = romfs_get_hash_table_count(num_dirs); |
| 245 | const u64 file_hash_table_entry_count = romfs_get_hash_table_count(num_files); | 245 | const u64 file_hash_table_entry_count = romfs_get_hash_table_count(num_files); |
| 246 | dir_hash_table_size = 4 * dir_hash_table_entry_count; | 246 | dir_hash_table_size = 4 * dir_hash_table_entry_count; |
| @@ -294,7 +294,7 @@ std::map<u64, VirtualFile> RomFSBuildContext::Build() { | |||
| 294 | cur_dir->parent->child = cur_dir; | 294 | cur_dir->parent->child = cur_dir; |
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | std::map<u64, VirtualFile> out; | 297 | std::multimap<u64, VirtualFile> out; |
| 298 | 298 | ||
| 299 | // Populate file tables. | 299 | // Populate file tables. |
| 300 | for (const auto& it : files) { | 300 | for (const auto& it : files) { |
diff --git a/src/core/file_sys/fsmitm_romfsbuild.h b/src/core/file_sys/fsmitm_romfsbuild.h index a62502193..049de180b 100644 --- a/src/core/file_sys/fsmitm_romfsbuild.h +++ b/src/core/file_sys/fsmitm_romfsbuild.h | |||
| @@ -43,7 +43,7 @@ public: | |||
| 43 | ~RomFSBuildContext(); | 43 | ~RomFSBuildContext(); |
| 44 | 44 | ||
| 45 | // This finalizes the context. | 45 | // This finalizes the context. |
| 46 | std::map<u64, VirtualFile> Build(); | 46 | std::multimap<u64, VirtualFile> Build(); |
| 47 | 47 | ||
| 48 | private: | 48 | private: |
| 49 | VirtualDir base; | 49 | VirtualDir base; |
diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp index 16d801c0c..e0ff70174 100644 --- a/src/core/file_sys/vfs_concat.cpp +++ b/src/core/file_sys/vfs_concat.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | namespace FileSys { | 12 | namespace FileSys { |
| 13 | 13 | ||
| 14 | static bool VerifyConcatenationMapContinuity(const std::map<u64, VirtualFile>& map) { | 14 | static bool VerifyConcatenationMapContinuity(const std::multimap<u64, VirtualFile>& map) { |
| 15 | const auto last_valid = --map.end(); | 15 | const auto last_valid = --map.end(); |
| 16 | for (auto iter = map.begin(); iter != last_valid;) { | 16 | for (auto iter = map.begin(); iter != last_valid;) { |
| 17 | const auto old = iter++; | 17 | const auto old = iter++; |
| @@ -27,12 +27,12 @@ ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector<VirtualFile> files_, std::s | |||
| 27 | : name(std::move(name)) { | 27 | : name(std::move(name)) { |
| 28 | std::size_t next_offset = 0; | 28 | std::size_t next_offset = 0; |
| 29 | for (const auto& file : files_) { | 29 | for (const auto& file : files_) { |
| 30 | files[next_offset] = file; | 30 | files.emplace(next_offset, file); |
| 31 | next_offset += file->GetSize(); | 31 | next_offset += file->GetSize(); |
| 32 | } | 32 | } |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | ConcatenatedVfsFile::ConcatenatedVfsFile(std::map<u64, VirtualFile> files_, std::string name) | 35 | ConcatenatedVfsFile::ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files_, std::string name) |
| 36 | : files(std::move(files_)), name(std::move(name)) { | 36 | : files(std::move(files_)), name(std::move(name)) { |
| 37 | ASSERT(VerifyConcatenationMapContinuity(files)); | 37 | ASSERT(VerifyConcatenationMapContinuity(files)); |
| 38 | } | 38 | } |
| @@ -50,7 +50,7 @@ VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(std::vector<VirtualFile> f | |||
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte, | 52 | VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte, |
| 53 | std::map<u64, VirtualFile> files, | 53 | std::multimap<u64, VirtualFile> files, |
| 54 | std::string name) { | 54 | std::string name) { |
| 55 | if (files.empty()) | 55 | if (files.empty()) |
| 56 | return nullptr; | 56 | return nullptr; |
diff --git a/src/core/file_sys/vfs_concat.h b/src/core/file_sys/vfs_concat.h index c90f9d5d1..7a26343c0 100644 --- a/src/core/file_sys/vfs_concat.h +++ b/src/core/file_sys/vfs_concat.h | |||
| @@ -15,7 +15,7 @@ namespace FileSys { | |||
| 15 | // read-only. | 15 | // read-only. |
| 16 | class ConcatenatedVfsFile : public VfsFile { | 16 | class ConcatenatedVfsFile : public VfsFile { |
| 17 | ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name); | 17 | ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name); |
| 18 | ConcatenatedVfsFile(std::map<u64, VirtualFile> files, std::string name); | 18 | ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files, std::string name); |
| 19 | 19 | ||
| 20 | public: | 20 | public: |
| 21 | ~ConcatenatedVfsFile() override; | 21 | ~ConcatenatedVfsFile() override; |
| @@ -25,7 +25,7 @@ public: | |||
| 25 | 25 | ||
| 26 | /// Convenience function that turns a map of offsets to files into a concatenated file, filling | 26 | /// Convenience function that turns a map of offsets to files into a concatenated file, filling |
| 27 | /// gaps with a given filler byte. | 27 | /// gaps with a given filler byte. |
| 28 | static VirtualFile MakeConcatenatedFile(u8 filler_byte, std::map<u64, VirtualFile> files, | 28 | static VirtualFile MakeConcatenatedFile(u8 filler_byte, std::multimap<u64, VirtualFile> files, |
| 29 | std::string name); | 29 | std::string name); |
| 30 | 30 | ||
| 31 | std::string GetName() const override; | 31 | std::string GetName() const override; |
| @@ -40,7 +40,7 @@ public: | |||
| 40 | 40 | ||
| 41 | private: | 41 | private: |
| 42 | // Maps starting offset to file -- more efficient. | 42 | // Maps starting offset to file -- more efficient. |
| 43 | std::map<u64, VirtualFile> files; | 43 | std::multimap<u64, VirtualFile> files; |
| 44 | std::string name; | 44 | std::string name; |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
diff --git a/src/core/hardware_interrupt_manager.cpp b/src/core/hardware_interrupt_manager.cpp index c629d9fa1..efc1030c1 100644 --- a/src/core/hardware_interrupt_manager.cpp +++ b/src/core/hardware_interrupt_manager.cpp | |||
| @@ -11,19 +11,20 @@ | |||
| 11 | namespace Core::Hardware { | 11 | namespace Core::Hardware { |
| 12 | 12 | ||
| 13 | InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) { | 13 | InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) { |
| 14 | gpu_interrupt_event = Core::Timing::CreateEvent("GPUInterrupt", [this](u64 message, s64) { | 14 | gpu_interrupt_event = |
| 15 | auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv"); | 15 | Core::Timing::CreateEvent("GPUInterrupt", [this](u64 message, std::chrono::nanoseconds) { |
| 16 | const u32 syncpt = static_cast<u32>(message >> 32); | 16 | auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv"); |
| 17 | const u32 value = static_cast<u32>(message); | 17 | const u32 syncpt = static_cast<u32>(message >> 32); |
| 18 | nvdrv->SignalGPUInterruptSyncpt(syncpt, value); | 18 | const u32 value = static_cast<u32>(message); |
| 19 | }); | 19 | nvdrv->SignalGPUInterruptSyncpt(syncpt, value); |
| 20 | }); | ||
| 20 | } | 21 | } |
| 21 | 22 | ||
| 22 | InterruptManager::~InterruptManager() = default; | 23 | InterruptManager::~InterruptManager() = default; |
| 23 | 24 | ||
| 24 | void InterruptManager::GPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) { | 25 | void InterruptManager::GPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) { |
| 25 | const u64 msg = (static_cast<u64>(syncpoint_id) << 32ULL) | value; | 26 | const u64 msg = (static_cast<u64>(syncpoint_id) << 32ULL) | value; |
| 26 | system.CoreTiming().ScheduleEvent(10, gpu_interrupt_event, msg); | 27 | system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{10}, gpu_interrupt_event, msg); |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | } // namespace Core::Hardware | 30 | } // namespace Core::Hardware |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index e1c7a0f3b..8dd4a2637 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -145,16 +145,18 @@ struct KernelCore::Impl { | |||
| 145 | 145 | ||
| 146 | void InitializePreemption(KernelCore& kernel) { | 146 | void InitializePreemption(KernelCore& kernel) { |
| 147 | preemption_event = Core::Timing::CreateEvent( | 147 | preemption_event = Core::Timing::CreateEvent( |
| 148 | "PreemptionCallback", [this, &kernel](u64 userdata, s64 cycles_late) { | 148 | "PreemptionCallback", [this, &kernel](u64, std::chrono::nanoseconds) { |
| 149 | { | 149 | { |
| 150 | SchedulerLock lock(kernel); | 150 | SchedulerLock lock(kernel); |
| 151 | global_scheduler.PreemptThreads(); | 151 | global_scheduler.PreemptThreads(); |
| 152 | } | 152 | } |
| 153 | s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10)); | 153 | const auto time_interval = std::chrono::nanoseconds{ |
| 154 | Core::Timing::msToCycles(std::chrono::milliseconds(10))}; | ||
| 154 | system.CoreTiming().ScheduleEvent(time_interval, preemption_event); | 155 | system.CoreTiming().ScheduleEvent(time_interval, preemption_event); |
| 155 | }); | 156 | }); |
| 156 | 157 | ||
| 157 | s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10)); | 158 | const auto time_interval = |
| 159 | std::chrono::nanoseconds{Core::Timing::msToCycles(std::chrono::milliseconds(10))}; | ||
| 158 | system.CoreTiming().ScheduleEvent(time_interval, preemption_event); | 160 | system.CoreTiming().ScheduleEvent(time_interval, preemption_event); |
| 159 | } | 161 | } |
| 160 | 162 | ||
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 7b23a6889..af22f4c33 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp | |||
| @@ -34,7 +34,7 @@ ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kern | |||
| 34 | std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)}; | 34 | std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)}; |
| 35 | 35 | ||
| 36 | session->request_event = Core::Timing::CreateEvent( | 36 | session->request_event = Core::Timing::CreateEvent( |
| 37 | name, [session](u64 userdata, s64 cycles_late) { session->CompleteSyncRequest(); }); | 37 | name, [session](u64, std::chrono::nanoseconds) { session->CompleteSyncRequest(); }); |
| 38 | session->name = std::move(name); | 38 | session->name = std::move(name); |
| 39 | session->parent = std::move(parent); | 39 | session->parent = std::move(parent); |
| 40 | 40 | ||
| @@ -184,8 +184,8 @@ ResultCode ServerSession::CompleteSyncRequest() { | |||
| 184 | 184 | ||
| 185 | ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread, | 185 | ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread, |
| 186 | Core::Memory::Memory& memory) { | 186 | Core::Memory::Memory& memory) { |
| 187 | ResultCode result = QueueSyncRequest(std::move(thread), memory); | 187 | const ResultCode result = QueueSyncRequest(std::move(thread), memory); |
| 188 | const u64 delay = kernel.IsMulticore() ? 0U : 20000U; | 188 | const auto delay = std::chrono::nanoseconds{kernel.IsMulticore() ? 0 : 20000}; |
| 189 | Core::System::GetInstance().CoreTiming().ScheduleEvent(delay, request_event, {}); | 189 | Core::System::GetInstance().CoreTiming().ScheduleEvent(delay, request_event, {}); |
| 190 | return result; | 190 | return result; |
| 191 | } | 191 | } |
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp index 941305e8e..88b01b751 100644 --- a/src/core/hle/kernel/time_manager.cpp +++ b/src/core/hle/kernel/time_manager.cpp | |||
| @@ -16,7 +16,7 @@ namespace Kernel { | |||
| 16 | 16 | ||
| 17 | TimeManager::TimeManager(Core::System& system_) : system{system_} { | 17 | TimeManager::TimeManager(Core::System& system_) : system{system_} { |
| 18 | time_manager_event_type = Core::Timing::CreateEvent( | 18 | time_manager_event_type = Core::Timing::CreateEvent( |
| 19 | "Kernel::TimeManagerCallback", [this](u64 thread_handle, [[maybe_unused]] s64 cycles_late) { | 19 | "Kernel::TimeManagerCallback", [this](u64 thread_handle, std::chrono::nanoseconds) { |
| 20 | SchedulerLock lock(system.Kernel()); | 20 | SchedulerLock lock(system.Kernel()); |
| 21 | Handle proper_handle = static_cast<Handle>(thread_handle); | 21 | Handle proper_handle = static_cast<Handle>(thread_handle); |
| 22 | if (cancelled_events[proper_handle]) { | 22 | if (cancelled_events[proper_handle]) { |
| @@ -34,7 +34,8 @@ void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 | |||
| 34 | ASSERT(timetask); | 34 | ASSERT(timetask); |
| 35 | ASSERT(timetask->GetStatus() != ThreadStatus::Ready); | 35 | ASSERT(timetask->GetStatus() != ThreadStatus::Ready); |
| 36 | ASSERT(timetask->GetStatus() != ThreadStatus::WaitMutex); | 36 | ASSERT(timetask->GetStatus() != ThreadStatus::WaitMutex); |
| 37 | system.CoreTiming().ScheduleEvent(nanoseconds, time_manager_event_type, event_handle); | 37 | system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{nanoseconds}, |
| 38 | time_manager_event_type, event_handle); | ||
| 38 | } else { | 39 | } else { |
| 39 | event_handle = InvalidHandle; | 40 | event_handle = InvalidHandle; |
| 40 | } | 41 | } |
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index cadc03805..c66124998 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -55,6 +55,10 @@ std::string VfsDirectoryServiceWrapper::GetName() const { | |||
| 55 | ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const { | 55 | ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const { |
| 56 | std::string path(FileUtil::SanitizePath(path_)); | 56 | std::string path(FileUtil::SanitizePath(path_)); |
| 57 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | 57 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); |
| 58 | // dir can be nullptr if path contains subdirectories, create those prior to creating the file. | ||
| 59 | if (dir == nullptr) { | ||
| 60 | dir = backing->CreateSubdirectory(FileUtil::GetParentPath(path)); | ||
| 61 | } | ||
| 58 | auto file = dir->CreateFile(FileUtil::GetFilename(path)); | 62 | auto file = dir->CreateFile(FileUtil::GetFilename(path)); |
| 59 | if (file == nullptr) { | 63 | if (file == nullptr) { |
| 60 | // TODO(DarkLordZach): Find a better error code for this | 64 | // TODO(DarkLordZach): Find a better error code for this |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index e9020e0dc..680290cbd 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -39,9 +39,10 @@ namespace Service::HID { | |||
| 39 | 39 | ||
| 40 | // Updating period for each HID device. | 40 | // Updating period for each HID device. |
| 41 | // TODO(ogniK): Find actual polling rate of hid | 41 | // TODO(ogniK): Find actual polling rate of hid |
| 42 | constexpr s64 pad_update_ticks = static_cast<s64>(1000000000 / 66); | 42 | constexpr auto pad_update_ns = std::chrono::nanoseconds{1000000000 / 66}; |
| 43 | [[maybe_unused]] constexpr s64 accelerometer_update_ticks = static_cast<s64>(1000000000 / 100); | 43 | [[maybe_unused]] constexpr auto accelerometer_update_ns = |
| 44 | [[maybe_unused]] constexpr s64 gyroscope_update_ticks = static_cast<s64>(1000000000 / 100); | 44 | std::chrono::nanoseconds{1000000000 / 100}; |
| 45 | [[maybe_unused]] constexpr auto gyroscope_update_ticks = std::chrono::nanoseconds{1000000000 / 100}; | ||
| 45 | constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; | 46 | constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; |
| 46 | 47 | ||
| 47 | IAppletResource::IAppletResource(Core::System& system) | 48 | IAppletResource::IAppletResource(Core::System& system) |
| @@ -75,14 +76,14 @@ IAppletResource::IAppletResource(Core::System& system) | |||
| 75 | GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000); | 76 | GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000); |
| 76 | 77 | ||
| 77 | // Register update callbacks | 78 | // Register update callbacks |
| 78 | pad_update_event = | 79 | pad_update_event = Core::Timing::CreateEvent( |
| 79 | Core::Timing::CreateEvent("HID::UpdatePadCallback", [this](u64 userdata, s64 ns_late) { | 80 | "HID::UpdatePadCallback", [this](u64 userdata, std::chrono::nanoseconds ns_late) { |
| 80 | UpdateControllers(userdata, ns_late); | 81 | UpdateControllers(userdata, ns_late); |
| 81 | }); | 82 | }); |
| 82 | 83 | ||
| 83 | // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) | 84 | // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) |
| 84 | 85 | ||
| 85 | system.CoreTiming().ScheduleEvent(pad_update_ticks, pad_update_event); | 86 | system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event); |
| 86 | 87 | ||
| 87 | ReloadInputDevices(); | 88 | ReloadInputDevices(); |
| 88 | } | 89 | } |
| @@ -107,7 +108,7 @@ void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) { | |||
| 107 | rb.PushCopyObjects(shared_mem); | 108 | rb.PushCopyObjects(shared_mem); |
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | void IAppletResource::UpdateControllers(u64 userdata, s64 ns_late) { | 111 | void IAppletResource::UpdateControllers(u64 userdata, std::chrono::nanoseconds ns_late) { |
| 111 | auto& core_timing = system.CoreTiming(); | 112 | auto& core_timing = system.CoreTiming(); |
| 112 | 113 | ||
| 113 | const bool should_reload = Settings::values.is_device_reload_pending.exchange(false); | 114 | const bool should_reload = Settings::values.is_device_reload_pending.exchange(false); |
| @@ -118,7 +119,7 @@ void IAppletResource::UpdateControllers(u64 userdata, s64 ns_late) { | |||
| 118 | controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); | 119 | controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); |
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | core_timing.ScheduleEvent(pad_update_ticks - ns_late, pad_update_event); | 122 | core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event); |
| 122 | } | 123 | } |
| 123 | 124 | ||
| 124 | class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> { | 125 | class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> { |
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 6fb048360..c6f0a2584 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -4,10 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/service/hid/controllers/controller_base.h" | 7 | #include <chrono> |
| 8 | #include "core/hle/service/service.h" | ||
| 9 | 8 | ||
| 10 | #include "controllers/controller_base.h" | 9 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 11 | #include "core/hle/service/service.h" | 10 | #include "core/hle/service/service.h" |
| 12 | 11 | ||
| 13 | namespace Core::Timing { | 12 | namespace Core::Timing { |
| @@ -65,7 +64,7 @@ private: | |||
| 65 | } | 64 | } |
| 66 | 65 | ||
| 67 | void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); | 66 | void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); |
| 68 | void UpdateControllers(u64 userdata, s64 cycles_late); | 67 | void UpdateControllers(u64 userdata, std::chrono::nanoseconds ns_late); |
| 69 | 68 | ||
| 70 | std::shared_ptr<Kernel::SharedMemory> shared_mem; | 69 | std::shared_ptr<Kernel::SharedMemory> shared_mem; |
| 71 | 70 | ||
diff --git a/src/core/hle/service/mii/manager.cpp b/src/core/hle/service/mii/manager.cpp index 4a1d1182e..4730070cb 100644 --- a/src/core/hle/service/mii/manager.cpp +++ b/src/core/hle/service/mii/manager.cpp | |||
| @@ -47,66 +47,67 @@ std::array<T, DestArraySize> ResizeArray(const std::array<T, SourceArraySize>& i | |||
| 47 | MiiInfo ConvertStoreDataToInfo(const MiiStoreData& data) { | 47 | MiiInfo ConvertStoreDataToInfo(const MiiStoreData& data) { |
| 48 | MiiStoreBitFields bf; | 48 | MiiStoreBitFields bf; |
| 49 | std::memcpy(&bf, data.data.data.data(), sizeof(MiiStoreBitFields)); | 49 | std::memcpy(&bf, data.data.data.data(), sizeof(MiiStoreBitFields)); |
| 50 | MiiInfo info{}; | 50 | |
| 51 | info.name = ResizeArray<char16_t, 10, 11>(data.data.name); | 51 | return { |
| 52 | info.uuid = data.data.uuid; | 52 | .uuid = data.data.uuid, |
| 53 | info.font_region = static_cast<u8>(bf.font_region.Value()); | 53 | .name = ResizeArray<char16_t, 10, 11>(data.data.name), |
| 54 | info.favorite_color = static_cast<u8>(bf.favorite_color.Value()); | 54 | .font_region = static_cast<u8>(bf.font_region.Value()), |
| 55 | info.gender = static_cast<u8>(bf.gender.Value()); | 55 | .favorite_color = static_cast<u8>(bf.favorite_color.Value()), |
| 56 | info.height = static_cast<u8>(bf.height.Value()); | 56 | .gender = static_cast<u8>(bf.gender.Value()), |
| 57 | info.build = static_cast<u8>(bf.build.Value()); | 57 | .height = static_cast<u8>(bf.height.Value()), |
| 58 | info.type = static_cast<u8>(bf.type.Value()); | 58 | .build = static_cast<u8>(bf.build.Value()), |
| 59 | info.region_move = static_cast<u8>(bf.region_move.Value()); | 59 | .type = static_cast<u8>(bf.type.Value()), |
| 60 | info.faceline_type = static_cast<u8>(bf.faceline_type.Value()); | 60 | .region_move = static_cast<u8>(bf.region_move.Value()), |
| 61 | info.faceline_color = static_cast<u8>(bf.faceline_color.Value()); | 61 | .faceline_type = static_cast<u8>(bf.faceline_type.Value()), |
| 62 | info.faceline_wrinkle = static_cast<u8>(bf.faceline_wrinkle.Value()); | 62 | .faceline_color = static_cast<u8>(bf.faceline_color.Value()), |
| 63 | info.faceline_make = static_cast<u8>(bf.faceline_makeup.Value()); | 63 | .faceline_wrinkle = static_cast<u8>(bf.faceline_wrinkle.Value()), |
| 64 | info.hair_type = static_cast<u8>(bf.hair_type.Value()); | 64 | .faceline_make = static_cast<u8>(bf.faceline_makeup.Value()), |
| 65 | info.hair_color = static_cast<u8>(bf.hair_color.Value()); | 65 | .hair_type = static_cast<u8>(bf.hair_type.Value()), |
| 66 | info.hair_flip = static_cast<u8>(bf.hair_flip.Value()); | 66 | .hair_color = static_cast<u8>(bf.hair_color.Value()), |
| 67 | info.eye_type = static_cast<u8>(bf.eye_type.Value()); | 67 | .hair_flip = static_cast<u8>(bf.hair_flip.Value()), |
| 68 | info.eye_color = static_cast<u8>(bf.eye_color.Value()); | 68 | .eye_type = static_cast<u8>(bf.eye_type.Value()), |
| 69 | info.eye_scale = static_cast<u8>(bf.eye_scale.Value()); | 69 | .eye_color = static_cast<u8>(bf.eye_color.Value()), |
| 70 | info.eye_aspect = static_cast<u8>(bf.eye_aspect.Value()); | 70 | .eye_scale = static_cast<u8>(bf.eye_scale.Value()), |
| 71 | info.eye_rotate = static_cast<u8>(bf.eye_rotate.Value()); | 71 | .eye_aspect = static_cast<u8>(bf.eye_aspect.Value()), |
| 72 | info.eye_x = static_cast<u8>(bf.eye_x.Value()); | 72 | .eye_rotate = static_cast<u8>(bf.eye_rotate.Value()), |
| 73 | info.eye_y = static_cast<u8>(bf.eye_y.Value()); | 73 | .eye_x = static_cast<u8>(bf.eye_x.Value()), |
| 74 | info.eyebrow_type = static_cast<u8>(bf.eyebrow_type.Value()); | 74 | .eye_y = static_cast<u8>(bf.eye_y.Value()), |
| 75 | info.eyebrow_color = static_cast<u8>(bf.eyebrow_color.Value()); | 75 | .eyebrow_type = static_cast<u8>(bf.eyebrow_type.Value()), |
| 76 | info.eyebrow_scale = static_cast<u8>(bf.eyebrow_scale.Value()); | 76 | .eyebrow_color = static_cast<u8>(bf.eyebrow_color.Value()), |
| 77 | info.eyebrow_aspect = static_cast<u8>(bf.eyebrow_aspect.Value()); | 77 | .eyebrow_scale = static_cast<u8>(bf.eyebrow_scale.Value()), |
| 78 | info.eyebrow_rotate = static_cast<u8>(bf.eyebrow_rotate.Value()); | 78 | .eyebrow_aspect = static_cast<u8>(bf.eyebrow_aspect.Value()), |
| 79 | info.eyebrow_x = static_cast<u8>(bf.eyebrow_x.Value()); | 79 | .eyebrow_rotate = static_cast<u8>(bf.eyebrow_rotate.Value()), |
| 80 | info.eyebrow_y = static_cast<u8>(bf.eyebrow_y.Value() + 3); | 80 | .eyebrow_x = static_cast<u8>(bf.eyebrow_x.Value()), |
| 81 | info.nose_type = static_cast<u8>(bf.nose_type.Value()); | 81 | .eyebrow_y = static_cast<u8>(bf.eyebrow_y.Value() + 3), |
| 82 | info.nose_scale = static_cast<u8>(bf.nose_scale.Value()); | 82 | .nose_type = static_cast<u8>(bf.nose_type.Value()), |
| 83 | info.nose_y = static_cast<u8>(bf.nose_y.Value()); | 83 | .nose_scale = static_cast<u8>(bf.nose_scale.Value()), |
| 84 | info.mouth_type = static_cast<u8>(bf.mouth_type.Value()); | 84 | .nose_y = static_cast<u8>(bf.nose_y.Value()), |
| 85 | info.mouth_color = static_cast<u8>(bf.mouth_color.Value()); | 85 | .mouth_type = static_cast<u8>(bf.mouth_type.Value()), |
| 86 | info.mouth_scale = static_cast<u8>(bf.mouth_scale.Value()); | 86 | .mouth_color = static_cast<u8>(bf.mouth_color.Value()), |
| 87 | info.mouth_aspect = static_cast<u8>(bf.mouth_aspect.Value()); | 87 | .mouth_scale = static_cast<u8>(bf.mouth_scale.Value()), |
| 88 | info.mouth_y = static_cast<u8>(bf.mouth_y.Value()); | 88 | .mouth_aspect = static_cast<u8>(bf.mouth_aspect.Value()), |
| 89 | info.beard_color = static_cast<u8>(bf.beard_color.Value()); | 89 | .mouth_y = static_cast<u8>(bf.mouth_y.Value()), |
| 90 | info.beard_type = static_cast<u8>(bf.beard_type.Value()); | 90 | .beard_color = static_cast<u8>(bf.beard_color.Value()), |
| 91 | info.mustache_type = static_cast<u8>(bf.mustache_type.Value()); | 91 | .beard_type = static_cast<u8>(bf.beard_type.Value()), |
| 92 | info.mustache_scale = static_cast<u8>(bf.mustache_scale.Value()); | 92 | .mustache_type = static_cast<u8>(bf.mustache_type.Value()), |
| 93 | info.mustache_y = static_cast<u8>(bf.mustache_y.Value()); | 93 | .mustache_scale = static_cast<u8>(bf.mustache_scale.Value()), |
| 94 | info.glasses_type = static_cast<u8>(bf.glasses_type.Value()); | 94 | .mustache_y = static_cast<u8>(bf.mustache_y.Value()), |
| 95 | info.glasses_color = static_cast<u8>(bf.glasses_color.Value()); | 95 | .glasses_type = static_cast<u8>(bf.glasses_type.Value()), |
| 96 | info.glasses_scale = static_cast<u8>(bf.glasses_scale.Value()); | 96 | .glasses_color = static_cast<u8>(bf.glasses_color.Value()), |
| 97 | info.glasses_y = static_cast<u8>(bf.glasses_y.Value()); | 97 | .glasses_scale = static_cast<u8>(bf.glasses_scale.Value()), |
| 98 | info.mole_type = static_cast<u8>(bf.mole_type.Value()); | 98 | .glasses_y = static_cast<u8>(bf.glasses_y.Value()), |
| 99 | info.mole_scale = static_cast<u8>(bf.mole_scale.Value()); | 99 | .mole_type = static_cast<u8>(bf.mole_type.Value()), |
| 100 | info.mole_x = static_cast<u8>(bf.mole_x.Value()); | 100 | .mole_scale = static_cast<u8>(bf.mole_scale.Value()), |
| 101 | info.mole_y = static_cast<u8>(bf.mole_y.Value()); | 101 | .mole_x = static_cast<u8>(bf.mole_x.Value()), |
| 102 | return info; | 102 | .mole_y = static_cast<u8>(bf.mole_y.Value()), |
| 103 | }; | ||
| 103 | } | 104 | } |
| 104 | 105 | ||
| 105 | u16 GenerateCrc16(const void* data, std::size_t size) { | 106 | u16 GenerateCrc16(const void* data, std::size_t size) { |
| 106 | s32 crc{}; | 107 | s32 crc{}; |
| 107 | for (int i = 0; i < size; i++) { | 108 | for (std::size_t i = 0; i < size; i++) { |
| 108 | crc ^= reinterpret_cast<const u8*>(data)[i] << 8; | 109 | crc ^= static_cast<const u8*>(data)[i] << 8; |
| 109 | for (int j = 0; j < 8; j++) { | 110 | for (std::size_t j = 0; j < 8; j++) { |
| 110 | crc <<= 1; | 111 | crc <<= 1; |
| 111 | if ((crc & 0x10000) != 0) { | 112 | if ((crc & 0x10000) != 0) { |
| 112 | crc = (crc ^ 0x1021) & 0xFFFF; | 113 | crc = (crc ^ 0x1021) & 0xFFFF; |
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 2f44d3779..789856118 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp | |||
| @@ -28,8 +28,7 @@ | |||
| 28 | 28 | ||
| 29 | namespace Service::NVFlinger { | 29 | namespace Service::NVFlinger { |
| 30 | 30 | ||
| 31 | constexpr s64 frame_ticks = static_cast<s64>(1000000000 / 60); | 31 | constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60}; |
| 32 | constexpr s64 frame_ticks_30fps = static_cast<s64>(1000000000 / 30); | ||
| 33 | 32 | ||
| 34 | void NVFlinger::VSyncThread(NVFlinger& nv_flinger) { | 33 | void NVFlinger::VSyncThread(NVFlinger& nv_flinger) { |
| 35 | nv_flinger.SplitVSync(); | 34 | nv_flinger.SplitVSync(); |
| @@ -67,20 +66,24 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) { | |||
| 67 | guard = std::make_shared<std::mutex>(); | 66 | guard = std::make_shared<std::mutex>(); |
| 68 | 67 | ||
| 69 | // Schedule the screen composition events | 68 | // Schedule the screen composition events |
| 70 | composition_event = | 69 | composition_event = Core::Timing::CreateEvent( |
| 71 | Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 ns_late) { | 70 | "ScreenComposition", [this](u64, std::chrono::nanoseconds ns_late) { |
| 72 | Lock(); | 71 | Lock(); |
| 73 | Compose(); | 72 | Compose(); |
| 74 | const auto ticks = GetNextTicks(); | 73 | |
| 75 | this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late), | 74 | const auto ticks = std::chrono::nanoseconds{GetNextTicks()}; |
| 76 | composition_event); | 75 | const auto ticks_delta = ticks - ns_late; |
| 76 | const auto future_ns = std::max(std::chrono::nanoseconds::zero(), ticks_delta); | ||
| 77 | |||
| 78 | this->system.CoreTiming().ScheduleEvent(future_ns, composition_event); | ||
| 77 | }); | 79 | }); |
| 80 | |||
| 78 | if (system.IsMulticore()) { | 81 | if (system.IsMulticore()) { |
| 79 | is_running = true; | 82 | is_running = true; |
| 80 | wait_event = std::make_unique<Common::Event>(); | 83 | wait_event = std::make_unique<Common::Event>(); |
| 81 | vsync_thread = std::make_unique<std::thread>(VSyncThread, std::ref(*this)); | 84 | vsync_thread = std::make_unique<std::thread>(VSyncThread, std::ref(*this)); |
| 82 | } else { | 85 | } else { |
| 83 | system.CoreTiming().ScheduleEvent(frame_ticks, composition_event); | 86 | system.CoreTiming().ScheduleEvent(frame_ns, composition_event); |
| 84 | } | 87 | } |
| 85 | } | 88 | } |
| 86 | 89 | ||
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index 53d27859b..ced41b1fe 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | namespace Core::Memory { | 21 | namespace Core::Memory { |
| 22 | 22 | ||
| 23 | constexpr s64 CHEAT_ENGINE_TICKS = static_cast<s64>(1000000000 / 12); | 23 | constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12}; |
| 24 | constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF; | 24 | constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF; |
| 25 | 25 | ||
| 26 | StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata) | 26 | StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata) |
| @@ -188,10 +188,12 @@ CheatEngine::~CheatEngine() { | |||
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | void CheatEngine::Initialize() { | 190 | void CheatEngine::Initialize() { |
| 191 | event = Core::Timing::CreateEvent( | 191 | event = Core::Timing::CreateEvent("CheatEngine::FrameCallback::" + |
| 192 | "CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id), | 192 | Common::HexToString(metadata.main_nso_build_id), |
| 193 | [this](u64 userdata, s64 ns_late) { FrameCallback(userdata, ns_late); }); | 193 | [this](u64 userdata, std::chrono::nanoseconds ns_late) { |
| 194 | core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event); | 194 | FrameCallback(userdata, ns_late); |
| 195 | }); | ||
| 196 | core_timing.ScheduleEvent(CHEAT_ENGINE_NS, event); | ||
| 195 | 197 | ||
| 196 | metadata.process_id = system.CurrentProcess()->GetProcessID(); | 198 | metadata.process_id = system.CurrentProcess()->GetProcessID(); |
| 197 | metadata.title_id = system.CurrentProcess()->GetTitleID(); | 199 | metadata.title_id = system.CurrentProcess()->GetTitleID(); |
| @@ -217,7 +219,7 @@ void CheatEngine::Reload(std::vector<CheatEntry> cheats) { | |||
| 217 | 219 | ||
| 218 | MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70)); | 220 | MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70)); |
| 219 | 221 | ||
| 220 | void CheatEngine::FrameCallback(u64 userdata, s64 ns_late) { | 222 | void CheatEngine::FrameCallback(u64, std::chrono::nanoseconds ns_late) { |
| 221 | if (is_pending_reload.exchange(false)) { | 223 | if (is_pending_reload.exchange(false)) { |
| 222 | vm.LoadProgram(cheats); | 224 | vm.LoadProgram(cheats); |
| 223 | } | 225 | } |
| @@ -230,7 +232,7 @@ void CheatEngine::FrameCallback(u64 userdata, s64 ns_late) { | |||
| 230 | 232 | ||
| 231 | vm.Execute(metadata); | 233 | vm.Execute(metadata); |
| 232 | 234 | ||
| 233 | core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS - ns_late, event); | 235 | core_timing.ScheduleEvent(CHEAT_ENGINE_NS - ns_late, event); |
| 234 | } | 236 | } |
| 235 | 237 | ||
| 236 | } // namespace Core::Memory | 238 | } // namespace Core::Memory |
diff --git a/src/core/memory/cheat_engine.h b/src/core/memory/cheat_engine.h index 2649423f8..d4068cf84 100644 --- a/src/core/memory/cheat_engine.h +++ b/src/core/memory/cheat_engine.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | 7 | #include <atomic> |
| 8 | #include <chrono> | ||
| 8 | #include <memory> | 9 | #include <memory> |
| 9 | #include <vector> | 10 | #include <vector> |
| 10 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| @@ -71,7 +72,7 @@ public: | |||
| 71 | void Reload(std::vector<CheatEntry> cheats); | 72 | void Reload(std::vector<CheatEntry> cheats); |
| 72 | 73 | ||
| 73 | private: | 74 | private: |
| 74 | void FrameCallback(u64 userdata, s64 cycles_late); | 75 | void FrameCallback(u64 userdata, std::chrono::nanoseconds ns_late); |
| 75 | 76 | ||
| 76 | DmntCheatVm vm; | 77 | DmntCheatVm vm; |
| 77 | CheatProcessMetadata metadata; | 78 | CheatProcessMetadata metadata; |
diff --git a/src/core/memory/dmnt_cheat_vm.cpp b/src/core/memory/dmnt_cheat_vm.cpp index fb9f36bfd..2e7da23fe 100644 --- a/src/core/memory/dmnt_cheat_vm.cpp +++ b/src/core/memory/dmnt_cheat_vm.cpp | |||
| @@ -190,6 +190,15 @@ void DmntCheatVm::LogOpcode(const CheatVmOpcode& opcode) { | |||
| 190 | callbacks->CommandLog( | 190 | callbacks->CommandLog( |
| 191 | fmt::format("Act[{:02X}]: {:d}", i, save_restore_regmask->should_operate[i])); | 191 | fmt::format("Act[{:02X}]: {:d}", i, save_restore_regmask->should_operate[i])); |
| 192 | } | 192 | } |
| 193 | } else if (auto rw_static_reg = std::get_if<ReadWriteStaticRegisterOpcode>(&opcode.opcode)) { | ||
| 194 | callbacks->CommandLog("Opcode: Read/Write Static Register"); | ||
| 195 | if (rw_static_reg->static_idx < NumReadableStaticRegisters) { | ||
| 196 | callbacks->CommandLog("Op Type: ReadStaticRegister"); | ||
| 197 | } else { | ||
| 198 | callbacks->CommandLog("Op Type: WriteStaticRegister"); | ||
| 199 | } | ||
| 200 | callbacks->CommandLog(fmt::format("Reg Idx {:X}", rw_static_reg->idx)); | ||
| 201 | callbacks->CommandLog(fmt::format("Stc Idx {:X}", rw_static_reg->static_idx)); | ||
| 193 | } else if (auto debug_log = std::get_if<DebugLogOpcode>(&opcode.opcode)) { | 202 | } else if (auto debug_log = std::get_if<DebugLogOpcode>(&opcode.opcode)) { |
| 194 | callbacks->CommandLog("Opcode: Debug Log"); | 203 | callbacks->CommandLog("Opcode: Debug Log"); |
| 195 | callbacks->CommandLog(fmt::format("Bit Width: {:X}", debug_log->bit_width)); | 204 | callbacks->CommandLog(fmt::format("Bit Width: {:X}", debug_log->bit_width)); |
| @@ -544,6 +553,16 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 544 | } | 553 | } |
| 545 | opcode.opcode = save_restore_regmask; | 554 | opcode.opcode = save_restore_regmask; |
| 546 | } break; | 555 | } break; |
| 556 | case CheatVmOpcodeType::ReadWriteStaticRegister: { | ||
| 557 | ReadWriteStaticRegisterOpcode rw_static_reg{}; | ||
| 558 | // C3000XXx | ||
| 559 | // C3 = opcode 0xC3. | ||
| 560 | // XX = static register index. | ||
| 561 | // x = register index. | ||
| 562 | rw_static_reg.static_idx = ((first_dword >> 4) & 0xFF); | ||
| 563 | rw_static_reg.idx = (first_dword & 0xF); | ||
| 564 | opcode.opcode = rw_static_reg; | ||
| 565 | } break; | ||
| 547 | case CheatVmOpcodeType::DebugLog: { | 566 | case CheatVmOpcodeType::DebugLog: { |
| 548 | DebugLogOpcode debug_log{}; | 567 | DebugLogOpcode debug_log{}; |
| 549 | // FFFTIX## | 568 | // FFFTIX## |
| @@ -667,6 +686,7 @@ void DmntCheatVm::ResetState() { | |||
| 667 | registers.fill(0); | 686 | registers.fill(0); |
| 668 | saved_values.fill(0); | 687 | saved_values.fill(0); |
| 669 | loop_tops.fill(0); | 688 | loop_tops.fill(0); |
| 689 | static_registers.fill(0); | ||
| 670 | instruction_ptr = 0; | 690 | instruction_ptr = 0; |
| 671 | condition_depth = 0; | 691 | condition_depth = 0; |
| 672 | decode_success = true; | 692 | decode_success = true; |
| @@ -1153,6 +1173,15 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) { | |||
| 1153 | } | 1173 | } |
| 1154 | } | 1174 | } |
| 1155 | } | 1175 | } |
| 1176 | } else if (auto rw_static_reg = | ||
| 1177 | std::get_if<ReadWriteStaticRegisterOpcode>(&cur_opcode.opcode)) { | ||
| 1178 | if (rw_static_reg->static_idx < NumReadableStaticRegisters) { | ||
| 1179 | // Load a register with a static register. | ||
| 1180 | registers[rw_static_reg->idx] = static_registers[rw_static_reg->static_idx]; | ||
| 1181 | } else { | ||
| 1182 | // Store a register to a static register. | ||
| 1183 | static_registers[rw_static_reg->static_idx] = registers[rw_static_reg->idx]; | ||
| 1184 | } | ||
| 1156 | } else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) { | 1185 | } else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) { |
| 1157 | // Read value from memory. | 1186 | // Read value from memory. |
| 1158 | u64 log_value = 0; | 1187 | u64 log_value = 0; |
diff --git a/src/core/memory/dmnt_cheat_vm.h b/src/core/memory/dmnt_cheat_vm.h index 8351fd798..21b86b72c 100644 --- a/src/core/memory/dmnt_cheat_vm.h +++ b/src/core/memory/dmnt_cheat_vm.h | |||
| @@ -56,6 +56,7 @@ enum class CheatVmOpcodeType : u32 { | |||
| 56 | BeginRegisterConditionalBlock = 0xC0, | 56 | BeginRegisterConditionalBlock = 0xC0, |
| 57 | SaveRestoreRegister = 0xC1, | 57 | SaveRestoreRegister = 0xC1, |
| 58 | SaveRestoreRegisterMask = 0xC2, | 58 | SaveRestoreRegisterMask = 0xC2, |
| 59 | ReadWriteStaticRegister = 0xC3, | ||
| 59 | 60 | ||
| 60 | // This is a meta entry, and not a real opcode. | 61 | // This is a meta entry, and not a real opcode. |
| 61 | // This is to facilitate multi-nybble instruction decoding. | 62 | // This is to facilitate multi-nybble instruction decoding. |
| @@ -237,6 +238,11 @@ struct SaveRestoreRegisterMaskOpcode { | |||
| 237 | std::array<bool, 0x10> should_operate{}; | 238 | std::array<bool, 0x10> should_operate{}; |
| 238 | }; | 239 | }; |
| 239 | 240 | ||
| 241 | struct ReadWriteStaticRegisterOpcode { | ||
| 242 | u32 static_idx{}; | ||
| 243 | u32 idx{}; | ||
| 244 | }; | ||
| 245 | |||
| 240 | struct DebugLogOpcode { | 246 | struct DebugLogOpcode { |
| 241 | u32 bit_width{}; | 247 | u32 bit_width{}; |
| 242 | u32 log_id{}; | 248 | u32 log_id{}; |
| @@ -259,7 +265,8 @@ struct CheatVmOpcode { | |||
| 259 | PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode, | 265 | PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode, |
| 260 | PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode, | 266 | PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode, |
| 261 | BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode, | 267 | BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode, |
| 262 | SaveRestoreRegisterMaskOpcode, DebugLogOpcode, UnrecognizedInstruction> | 268 | SaveRestoreRegisterMaskOpcode, ReadWriteStaticRegisterOpcode, DebugLogOpcode, |
| 269 | UnrecognizedInstruction> | ||
| 263 | opcode{}; | 270 | opcode{}; |
| 264 | }; | 271 | }; |
| 265 | 272 | ||
| @@ -281,6 +288,10 @@ public: | |||
| 281 | 288 | ||
| 282 | static constexpr std::size_t MaximumProgramOpcodeCount = 0x400; | 289 | static constexpr std::size_t MaximumProgramOpcodeCount = 0x400; |
| 283 | static constexpr std::size_t NumRegisters = 0x10; | 290 | static constexpr std::size_t NumRegisters = 0x10; |
| 291 | static constexpr std::size_t NumReadableStaticRegisters = 0x80; | ||
| 292 | static constexpr std::size_t NumWritableStaticRegisters = 0x80; | ||
| 293 | static constexpr std::size_t NumStaticRegisters = | ||
| 294 | NumReadableStaticRegisters + NumWritableStaticRegisters; | ||
| 284 | 295 | ||
| 285 | explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks); | 296 | explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks); |
| 286 | ~DmntCheatVm(); | 297 | ~DmntCheatVm(); |
| @@ -302,6 +313,7 @@ private: | |||
| 302 | std::array<u32, MaximumProgramOpcodeCount> program{}; | 313 | std::array<u32, MaximumProgramOpcodeCount> program{}; |
| 303 | std::array<u64, NumRegisters> registers{}; | 314 | std::array<u64, NumRegisters> registers{}; |
| 304 | std::array<u64, NumRegisters> saved_values{}; | 315 | std::array<u64, NumRegisters> saved_values{}; |
| 316 | std::array<u64, NumStaticRegisters> static_registers{}; | ||
| 305 | std::array<std::size_t, NumRegisters> loop_tops{}; | 317 | std::array<std::size_t, NumRegisters> loop_tops{}; |
| 306 | 318 | ||
| 307 | bool DecodeNextOpcode(CheatVmOpcode& out); | 319 | bool DecodeNextOpcode(CheatVmOpcode& out); |
diff --git a/src/core/settings.cpp b/src/core/settings.cpp index e8a6f2a6e..44252dd81 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp | |||
| @@ -115,6 +115,7 @@ void LogSettings() { | |||
| 115 | values.use_asynchronous_gpu_emulation.GetValue()); | 115 | values.use_asynchronous_gpu_emulation.GetValue()); |
| 116 | log_setting("Renderer_UseVsync", values.use_vsync.GetValue()); | 116 | log_setting("Renderer_UseVsync", values.use_vsync.GetValue()); |
| 117 | log_setting("Renderer_UseAssemblyShaders", values.use_assembly_shaders.GetValue()); | 117 | log_setting("Renderer_UseAssemblyShaders", values.use_assembly_shaders.GetValue()); |
| 118 | log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue()); | ||
| 118 | log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue()); | 119 | log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue()); |
| 119 | log_setting("Audio_OutputEngine", values.sink_id); | 120 | log_setting("Audio_OutputEngine", values.sink_id); |
| 120 | log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); | 121 | log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); |
| @@ -170,6 +171,7 @@ void RestoreGlobalState() { | |||
| 170 | values.use_asynchronous_gpu_emulation.SetGlobal(true); | 171 | values.use_asynchronous_gpu_emulation.SetGlobal(true); |
| 171 | values.use_vsync.SetGlobal(true); | 172 | values.use_vsync.SetGlobal(true); |
| 172 | values.use_assembly_shaders.SetGlobal(true); | 173 | values.use_assembly_shaders.SetGlobal(true); |
| 174 | values.use_asynchronous_shaders.SetGlobal(true); | ||
| 173 | values.use_fast_gpu_time.SetGlobal(true); | 175 | values.use_fast_gpu_time.SetGlobal(true); |
| 174 | values.force_30fps_mode.SetGlobal(true); | 176 | values.force_30fps_mode.SetGlobal(true); |
| 175 | values.bg_red.SetGlobal(true); | 177 | values.bg_red.SetGlobal(true); |
diff --git a/src/core/settings.h b/src/core/settings.h index a64debd25..386233fdf 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -434,6 +434,7 @@ struct Values { | |||
| 434 | Setting<bool> use_asynchronous_gpu_emulation; | 434 | Setting<bool> use_asynchronous_gpu_emulation; |
| 435 | Setting<bool> use_vsync; | 435 | Setting<bool> use_vsync; |
| 436 | Setting<bool> use_assembly_shaders; | 436 | Setting<bool> use_assembly_shaders; |
| 437 | Setting<bool> use_asynchronous_shaders; | ||
| 437 | Setting<bool> force_30fps_mode; | 438 | Setting<bool> force_30fps_mode; |
| 438 | Setting<bool> use_fast_gpu_time; | 439 | Setting<bool> use_fast_gpu_time; |
| 439 | 440 | ||
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 78915e6db..5a30c75da 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp | |||
| @@ -207,6 +207,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { | |||
| 207 | AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue()); | 207 | AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue()); |
| 208 | AddField(field_type, "Renderer_UseAssemblyShaders", | 208 | AddField(field_type, "Renderer_UseAssemblyShaders", |
| 209 | Settings::values.use_assembly_shaders.GetValue()); | 209 | Settings::values.use_assembly_shaders.GetValue()); |
| 210 | AddField(field_type, "Renderer_UseAsynchronousShaders", | ||
| 211 | Settings::values.use_asynchronous_shaders.GetValue()); | ||
| 210 | AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode); | 212 | AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode); |
| 211 | } | 213 | } |
| 212 | 214 | ||
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp index 8b0c50d11..27b894b51 100644 --- a/src/core/tools/freezer.cpp +++ b/src/core/tools/freezer.cpp | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | namespace Tools { | 14 | namespace Tools { |
| 15 | namespace { | 15 | namespace { |
| 16 | 16 | ||
| 17 | constexpr s64 MEMORY_FREEZER_TICKS = static_cast<s64>(1000000000 / 60); | 17 | constexpr auto memory_freezer_ns = std::chrono::nanoseconds{1000000000 / 60}; |
| 18 | 18 | ||
| 19 | u64 MemoryReadWidth(Core::Memory::Memory& memory, u32 width, VAddr addr) { | 19 | u64 MemoryReadWidth(Core::Memory::Memory& memory, u32 width, VAddr addr) { |
| 20 | switch (width) { | 20 | switch (width) { |
| @@ -55,10 +55,11 @@ void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 v | |||
| 55 | 55 | ||
| 56 | Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_) | 56 | Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_) |
| 57 | : core_timing{core_timing_}, memory{memory_} { | 57 | : core_timing{core_timing_}, memory{memory_} { |
| 58 | event = Core::Timing::CreateEvent( | 58 | event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback", |
| 59 | "MemoryFreezer::FrameCallback", | 59 | [this](u64 userdata, std::chrono::nanoseconds ns_late) { |
| 60 | [this](u64 userdata, s64 ns_late) { FrameCallback(userdata, ns_late); }); | 60 | FrameCallback(userdata, ns_late); |
| 61 | core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS, event); | 61 | }); |
| 62 | core_timing.ScheduleEvent(memory_freezer_ns, event); | ||
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | Freezer::~Freezer() { | 65 | Freezer::~Freezer() { |
| @@ -68,7 +69,7 @@ Freezer::~Freezer() { | |||
| 68 | void Freezer::SetActive(bool active) { | 69 | void Freezer::SetActive(bool active) { |
| 69 | if (!this->active.exchange(active)) { | 70 | if (!this->active.exchange(active)) { |
| 70 | FillEntryReads(); | 71 | FillEntryReads(); |
| 71 | core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS, event); | 72 | core_timing.ScheduleEvent(memory_freezer_ns, event); |
| 72 | LOG_DEBUG(Common_Memory, "Memory freezer activated!"); | 73 | LOG_DEBUG(Common_Memory, "Memory freezer activated!"); |
| 73 | } else { | 74 | } else { |
| 74 | LOG_DEBUG(Common_Memory, "Memory freezer deactivated!"); | 75 | LOG_DEBUG(Common_Memory, "Memory freezer deactivated!"); |
| @@ -158,7 +159,7 @@ std::vector<Freezer::Entry> Freezer::GetEntries() const { | |||
| 158 | return entries; | 159 | return entries; |
| 159 | } | 160 | } |
| 160 | 161 | ||
| 161 | void Freezer::FrameCallback(u64 userdata, s64 ns_late) { | 162 | void Freezer::FrameCallback(u64, std::chrono::nanoseconds ns_late) { |
| 162 | if (!IsActive()) { | 163 | if (!IsActive()) { |
| 163 | LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events."); | 164 | LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events."); |
| 164 | return; | 165 | return; |
| @@ -173,7 +174,7 @@ void Freezer::FrameCallback(u64 userdata, s64 ns_late) { | |||
| 173 | MemoryWriteWidth(memory, entry.width, entry.address, entry.value); | 174 | MemoryWriteWidth(memory, entry.width, entry.address, entry.value); |
| 174 | } | 175 | } |
| 175 | 176 | ||
| 176 | core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS - ns_late, event); | 177 | core_timing.ScheduleEvent(memory_freezer_ns - ns_late, event); |
| 177 | } | 178 | } |
| 178 | 179 | ||
| 179 | void Freezer::FillEntryReads() { | 180 | void Freezer::FillEntryReads() { |
diff --git a/src/core/tools/freezer.h b/src/core/tools/freezer.h index 62fc6aa6c..8438783d5 100644 --- a/src/core/tools/freezer.h +++ b/src/core/tools/freezer.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | 7 | #include <atomic> |
| 8 | #include <chrono> | ||
| 8 | #include <memory> | 9 | #include <memory> |
| 9 | #include <mutex> | 10 | #include <mutex> |
| 10 | #include <optional> | 11 | #include <optional> |
| @@ -72,7 +73,7 @@ public: | |||
| 72 | std::vector<Entry> GetEntries() const; | 73 | std::vector<Entry> GetEntries() const; |
| 73 | 74 | ||
| 74 | private: | 75 | private: |
| 75 | void FrameCallback(u64 userdata, s64 cycles_late); | 76 | void FrameCallback(u64 userdata, std::chrono::nanoseconds ns_late); |
| 76 | void FillEntryReads(); | 77 | void FillEntryReads(); |
| 77 | 78 | ||
| 78 | std::atomic_bool active{false}; | 79 | std::atomic_bool active{false}; |
diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp index e66db1940..244463a47 100644 --- a/src/tests/core/core_timing.cpp +++ b/src/tests/core/core_timing.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <bitset> | 8 | #include <bitset> |
| 9 | #include <chrono> | ||
| 9 | #include <cstdlib> | 10 | #include <cstdlib> |
| 10 | #include <memory> | 11 | #include <memory> |
| 11 | #include <string> | 12 | #include <string> |
| @@ -17,7 +18,6 @@ | |||
| 17 | namespace { | 18 | namespace { |
| 18 | // Numbers are chosen randomly to make sure the correct one is given. | 19 | // Numbers are chosen randomly to make sure the correct one is given. |
| 19 | constexpr std::array<u64, 5> CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}}; | 20 | constexpr std::array<u64, 5> CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}}; |
| 20 | constexpr int MAX_SLICE_LENGTH = 10000; // Copied from CoreTiming internals | ||
| 21 | constexpr std::array<u64, 5> calls_order{{2, 0, 1, 4, 3}}; | 21 | constexpr std::array<u64, 5> calls_order{{2, 0, 1, 4, 3}}; |
| 22 | std::array<s64, 5> delays{}; | 22 | std::array<s64, 5> delays{}; |
| 23 | 23 | ||
| @@ -25,12 +25,12 @@ std::bitset<CB_IDS.size()> callbacks_ran_flags; | |||
| 25 | u64 expected_callback = 0; | 25 | u64 expected_callback = 0; |
| 26 | 26 | ||
| 27 | template <unsigned int IDX> | 27 | template <unsigned int IDX> |
| 28 | void HostCallbackTemplate(u64 userdata, s64 nanoseconds_late) { | 28 | void HostCallbackTemplate(u64 userdata, std::chrono::nanoseconds ns_late) { |
| 29 | static_assert(IDX < CB_IDS.size(), "IDX out of range"); | 29 | static_assert(IDX < CB_IDS.size(), "IDX out of range"); |
| 30 | callbacks_ran_flags.set(IDX); | 30 | callbacks_ran_flags.set(IDX); |
| 31 | REQUIRE(CB_IDS[IDX] == userdata); | 31 | REQUIRE(CB_IDS[IDX] == userdata); |
| 32 | REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]); | 32 | REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]); |
| 33 | delays[IDX] = nanoseconds_late; | 33 | delays[IDX] = ns_late.count(); |
| 34 | ++expected_callback; | 34 | ++expected_callback; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| @@ -77,10 +77,12 @@ TEST_CASE("CoreTiming[BasicOrder]", "[core]") { | |||
| 77 | 77 | ||
| 78 | core_timing.SyncPause(true); | 78 | core_timing.SyncPause(true); |
| 79 | 79 | ||
| 80 | u64 one_micro = 1000U; | 80 | const u64 one_micro = 1000U; |
| 81 | for (std::size_t i = 0; i < events.size(); i++) { | 81 | for (std::size_t i = 0; i < events.size(); i++) { |
| 82 | u64 order = calls_order[i]; | 82 | const u64 order = calls_order[i]; |
| 83 | core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]); | 83 | const auto future_ns = std::chrono::nanoseconds{static_cast<s64>(i * one_micro + 100)}; |
| 84 | |||
| 85 | core_timing.ScheduleEvent(future_ns, events[order], CB_IDS[order]); | ||
| 84 | } | 86 | } |
| 85 | /// test pause | 87 | /// test pause |
| 86 | REQUIRE(callbacks_ran_flags.none()); | 88 | REQUIRE(callbacks_ran_flags.none()); |
| @@ -116,13 +118,16 @@ TEST_CASE("CoreTiming[BasicOrderNoPausing]", "[core]") { | |||
| 116 | 118 | ||
| 117 | expected_callback = 0; | 119 | expected_callback = 0; |
| 118 | 120 | ||
| 119 | u64 start = core_timing.GetGlobalTimeNs().count(); | 121 | const u64 start = core_timing.GetGlobalTimeNs().count(); |
| 120 | u64 one_micro = 1000U; | 122 | const u64 one_micro = 1000U; |
| 123 | |||
| 121 | for (std::size_t i = 0; i < events.size(); i++) { | 124 | for (std::size_t i = 0; i < events.size(); i++) { |
| 122 | u64 order = calls_order[i]; | 125 | const u64 order = calls_order[i]; |
| 123 | core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]); | 126 | const auto future_ns = std::chrono::nanoseconds{static_cast<s64>(i * one_micro + 100)}; |
| 127 | core_timing.ScheduleEvent(future_ns, events[order], CB_IDS[order]); | ||
| 124 | } | 128 | } |
| 125 | u64 end = core_timing.GetGlobalTimeNs().count(); | 129 | |
| 130 | const u64 end = core_timing.GetGlobalTimeNs().count(); | ||
| 126 | const double scheduling_time = static_cast<double>(end - start); | 131 | const double scheduling_time = static_cast<double>(end - start); |
| 127 | const double timer_time = static_cast<double>(TestTimerSpeed(core_timing)); | 132 | const double timer_time = static_cast<double>(TestTimerSpeed(core_timing)); |
| 128 | 133 | ||
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 21c46a567..3cd896a0f 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -98,6 +98,8 @@ add_library(video_core STATIC | |||
| 98 | sampler_cache.cpp | 98 | sampler_cache.cpp |
| 99 | sampler_cache.h | 99 | sampler_cache.h |
| 100 | shader_cache.h | 100 | shader_cache.h |
| 101 | shader_notify.cpp | ||
| 102 | shader_notify.h | ||
| 101 | shader/decode/arithmetic.cpp | 103 | shader/decode/arithmetic.cpp |
| 102 | shader/decode/arithmetic_immediate.cpp | 104 | shader/decode/arithmetic_immediate.cpp |
| 103 | shader/decode/bfe.cpp | 105 | shader/decode/bfe.cpp |
| @@ -128,6 +130,8 @@ add_library(video_core STATIC | |||
| 128 | shader/decode/other.cpp | 130 | shader/decode/other.cpp |
| 129 | shader/ast.cpp | 131 | shader/ast.cpp |
| 130 | shader/ast.h | 132 | shader/ast.h |
| 133 | shader/async_shaders.cpp | ||
| 134 | shader/async_shaders.h | ||
| 131 | shader/compiler_settings.cpp | 135 | shader/compiler_settings.cpp |
| 132 | shader/compiler_settings.h | 136 | shader/compiler_settings.h |
| 133 | shader/control_flow.cpp | 137 | shader/control_flow.cpp |
diff --git a/src/video_core/compatible_formats.cpp b/src/video_core/compatible_formats.cpp index 6c426b035..b06c32c84 100644 --- a/src/video_core/compatible_formats.cpp +++ b/src/video_core/compatible_formats.cpp | |||
| @@ -17,101 +17,94 @@ namespace { | |||
| 17 | // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_view.txt | 17 | // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_view.txt |
| 18 | 18 | ||
| 19 | constexpr std::array VIEW_CLASS_128_BITS = { | 19 | constexpr std::array VIEW_CLASS_128_BITS = { |
| 20 | PixelFormat::RGBA32F, | 20 | PixelFormat::R32G32B32A32_FLOAT, |
| 21 | PixelFormat::RGBA32UI, | 21 | PixelFormat::R32G32B32A32_UINT, |
| 22 | PixelFormat::R32G32B32A32_SINT, | ||
| 22 | }; | 23 | }; |
| 23 | // Missing formats: | ||
| 24 | // PixelFormat::RGBA32I | ||
| 25 | 24 | ||
| 26 | constexpr std::array VIEW_CLASS_96_BITS = { | 25 | constexpr std::array VIEW_CLASS_96_BITS = { |
| 27 | PixelFormat::RGB32F, | 26 | PixelFormat::R32G32B32_FLOAT, |
| 28 | }; | 27 | }; |
| 29 | // Missing formats: | 28 | // Missing formats: |
| 30 | // PixelFormat::RGB32UI, | 29 | // PixelFormat::RGB32UI, |
| 31 | // PixelFormat::RGB32I, | 30 | // PixelFormat::RGB32I, |
| 32 | 31 | ||
| 33 | constexpr std::array VIEW_CLASS_64_BITS = { | 32 | constexpr std::array VIEW_CLASS_64_BITS = { |
| 34 | PixelFormat::RGBA16F, PixelFormat::RG32F, PixelFormat::RGBA16UI, PixelFormat::RG32UI, | 33 | PixelFormat::R32G32_FLOAT, PixelFormat::R32G32_UINT, |
| 35 | PixelFormat::RGBA16U, PixelFormat::RGBA16F, PixelFormat::RGBA16S, | 34 | PixelFormat::R32G32_SINT, PixelFormat::R16G16B16A16_FLOAT, |
| 35 | PixelFormat::R16G16B16A16_UNORM, PixelFormat::R16G16B16A16_SNORM, | ||
| 36 | PixelFormat::R16G16B16A16_UINT, PixelFormat::R16G16B16A16_SINT, | ||
| 36 | }; | 37 | }; |
| 37 | // Missing formats: | ||
| 38 | // PixelFormat::RGBA16I | ||
| 39 | // PixelFormat::RG32I | ||
| 40 | 38 | ||
| 41 | // TODO: How should we handle 48 bits? | 39 | // TODO: How should we handle 48 bits? |
| 42 | 40 | ||
| 43 | constexpr std::array VIEW_CLASS_32_BITS = { | 41 | constexpr std::array VIEW_CLASS_32_BITS = { |
| 44 | PixelFormat::RG16F, PixelFormat::R11FG11FB10F, PixelFormat::R32F, | 42 | PixelFormat::R16G16_FLOAT, PixelFormat::B10G11R11_FLOAT, PixelFormat::R32_FLOAT, |
| 45 | PixelFormat::A2B10G10R10U, PixelFormat::RG16UI, PixelFormat::R32UI, | 43 | PixelFormat::A2B10G10R10_UNORM, PixelFormat::R16G16_UINT, PixelFormat::R32_UINT, |
| 46 | PixelFormat::RG16I, PixelFormat::R32I, PixelFormat::ABGR8U, | 44 | PixelFormat::R16G16_SINT, PixelFormat::R32_SINT, PixelFormat::A8B8G8R8_UNORM, |
| 47 | PixelFormat::RG16, PixelFormat::ABGR8S, PixelFormat::RG16S, | 45 | PixelFormat::R16G16_UNORM, PixelFormat::A8B8G8R8_SNORM, PixelFormat::R16G16_SNORM, |
| 48 | PixelFormat::RGBA8_SRGB, PixelFormat::E5B9G9R9F, PixelFormat::BGRA8, | 46 | PixelFormat::A8B8G8R8_SRGB, PixelFormat::E5B9G9R9_FLOAT, PixelFormat::B8G8R8A8_UNORM, |
| 49 | PixelFormat::BGRA8_SRGB, | 47 | PixelFormat::B8G8R8A8_SRGB, PixelFormat::A8B8G8R8_UINT, PixelFormat::A8B8G8R8_SINT, |
| 48 | PixelFormat::A2B10G10R10_UINT, | ||
| 50 | }; | 49 | }; |
| 51 | // Missing formats: | ||
| 52 | // PixelFormat::RGBA8UI | ||
| 53 | // PixelFormat::RGBA8I | ||
| 54 | // PixelFormat::RGB10_A2_UI | ||
| 55 | 50 | ||
| 56 | // TODO: How should we handle 24 bits? | 51 | // TODO: How should we handle 24 bits? |
| 57 | 52 | ||
| 58 | constexpr std::array VIEW_CLASS_16_BITS = { | 53 | constexpr std::array VIEW_CLASS_16_BITS = { |
| 59 | PixelFormat::R16F, PixelFormat::RG8UI, PixelFormat::R16UI, PixelFormat::R16I, | 54 | PixelFormat::R16_FLOAT, PixelFormat::R8G8_UINT, PixelFormat::R16_UINT, |
| 60 | PixelFormat::RG8U, PixelFormat::R16U, PixelFormat::RG8S, PixelFormat::R16S, | 55 | PixelFormat::R16_SINT, PixelFormat::R8G8_UNORM, PixelFormat::R16_UNORM, |
| 56 | PixelFormat::R8G8_SNORM, PixelFormat::R16_SNORM, PixelFormat::R8G8_SINT, | ||
| 61 | }; | 57 | }; |
| 62 | // Missing formats: | ||
| 63 | // PixelFormat::RG8I | ||
| 64 | 58 | ||
| 65 | constexpr std::array VIEW_CLASS_8_BITS = { | 59 | constexpr std::array VIEW_CLASS_8_BITS = { |
| 66 | PixelFormat::R8UI, | 60 | PixelFormat::R8_UINT, |
| 67 | PixelFormat::R8U, | 61 | PixelFormat::R8_UNORM, |
| 62 | PixelFormat::R8_SINT, | ||
| 63 | PixelFormat::R8_SNORM, | ||
| 68 | }; | 64 | }; |
| 69 | // Missing formats: | ||
| 70 | // PixelFormat::R8I | ||
| 71 | // PixelFormat::R8S | ||
| 72 | 65 | ||
| 73 | constexpr std::array VIEW_CLASS_RGTC1_RED = { | 66 | constexpr std::array VIEW_CLASS_RGTC1_RED = { |
| 74 | PixelFormat::DXN1, | 67 | PixelFormat::BC4_UNORM, |
| 68 | PixelFormat::BC4_SNORM, | ||
| 75 | }; | 69 | }; |
| 76 | // Missing formats: | ||
| 77 | // COMPRESSED_SIGNED_RED_RGTC1 | ||
| 78 | 70 | ||
| 79 | constexpr std::array VIEW_CLASS_RGTC2_RG = { | 71 | constexpr std::array VIEW_CLASS_RGTC2_RG = { |
| 80 | PixelFormat::DXN2UNORM, | 72 | PixelFormat::BC5_UNORM, |
| 81 | PixelFormat::DXN2SNORM, | 73 | PixelFormat::BC5_SNORM, |
| 82 | }; | 74 | }; |
| 83 | 75 | ||
| 84 | constexpr std::array VIEW_CLASS_BPTC_UNORM = { | 76 | constexpr std::array VIEW_CLASS_BPTC_UNORM = { |
| 85 | PixelFormat::BC7U, | 77 | PixelFormat::BC7_UNORM, |
| 86 | PixelFormat::BC7U_SRGB, | 78 | PixelFormat::BC7_SRGB, |
| 87 | }; | 79 | }; |
| 88 | 80 | ||
| 89 | constexpr std::array VIEW_CLASS_BPTC_FLOAT = { | 81 | constexpr std::array VIEW_CLASS_BPTC_FLOAT = { |
| 90 | PixelFormat::BC6H_SF16, | 82 | PixelFormat::BC6H_SFLOAT, |
| 91 | PixelFormat::BC6H_UF16, | 83 | PixelFormat::BC6H_UFLOAT, |
| 92 | }; | 84 | }; |
| 93 | 85 | ||
| 94 | // Compatibility table taken from Table 4.X.1 in: | 86 | // Compatibility table taken from Table 4.X.1 in: |
| 95 | // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_copy_image.txt | 87 | // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_copy_image.txt |
| 96 | 88 | ||
| 97 | constexpr std::array COPY_CLASS_128_BITS = { | 89 | constexpr std::array COPY_CLASS_128_BITS = { |
| 98 | PixelFormat::RGBA32UI, PixelFormat::RGBA32F, PixelFormat::DXT23, | 90 | PixelFormat::R32G32B32A32_UINT, PixelFormat::R32G32B32A32_FLOAT, PixelFormat::R32G32B32A32_SINT, |
| 99 | PixelFormat::DXT23_SRGB, PixelFormat::DXT45, PixelFormat::DXT45_SRGB, | 91 | PixelFormat::BC2_UNORM, PixelFormat::BC2_SRGB, PixelFormat::BC3_UNORM, |
| 100 | PixelFormat::DXN2SNORM, PixelFormat::BC7U, PixelFormat::BC7U_SRGB, | 92 | PixelFormat::BC3_SRGB, PixelFormat::BC5_UNORM, PixelFormat::BC5_SNORM, |
| 101 | PixelFormat::BC6H_SF16, PixelFormat::BC6H_UF16, | 93 | PixelFormat::BC7_UNORM, PixelFormat::BC7_SRGB, PixelFormat::BC6H_SFLOAT, |
| 94 | PixelFormat::BC6H_UFLOAT, | ||
| 102 | }; | 95 | }; |
| 103 | // Missing formats: | 96 | // Missing formats: |
| 104 | // PixelFormat::RGBA32I | 97 | // PixelFormat::RGBA32I |
| 105 | // COMPRESSED_RG_RGTC2 | 98 | // COMPRESSED_RG_RGTC2 |
| 106 | 99 | ||
| 107 | constexpr std::array COPY_CLASS_64_BITS = { | 100 | constexpr std::array COPY_CLASS_64_BITS = { |
| 108 | PixelFormat::RGBA16F, PixelFormat::RG32F, PixelFormat::RGBA16UI, PixelFormat::RG32UI, | 101 | PixelFormat::R16G16B16A16_FLOAT, PixelFormat::R16G16B16A16_UINT, |
| 109 | PixelFormat::RGBA16U, PixelFormat::RGBA16S, PixelFormat::DXT1_SRGB, PixelFormat::DXT1, | 102 | PixelFormat::R16G16B16A16_UNORM, PixelFormat::R16G16B16A16_SNORM, |
| 110 | 103 | PixelFormat::R16G16B16A16_SINT, PixelFormat::R32G32_UINT, | |
| 104 | PixelFormat::R32G32_FLOAT, PixelFormat::R32G32_SINT, | ||
| 105 | PixelFormat::BC1_RGBA_UNORM, PixelFormat::BC1_RGBA_SRGB, | ||
| 111 | }; | 106 | }; |
| 112 | // Missing formats: | 107 | // Missing formats: |
| 113 | // PixelFormat::RGBA16I | ||
| 114 | // PixelFormat::RG32I, | ||
| 115 | // COMPRESSED_RGB_S3TC_DXT1_EXT | 108 | // COMPRESSED_RGB_S3TC_DXT1_EXT |
| 116 | // COMPRESSED_SRGB_S3TC_DXT1_EXT | 109 | // COMPRESSED_SRGB_S3TC_DXT1_EXT |
| 117 | // COMPRESSED_RGBA_S3TC_DXT1_EXT | 110 | // COMPRESSED_RGBA_S3TC_DXT1_EXT |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 758bfe148..8e19c3373 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "video_core/gpu.h" | 20 | #include "video_core/gpu.h" |
| 21 | #include "video_core/memory_manager.h" | 21 | #include "video_core/memory_manager.h" |
| 22 | #include "video_core/renderer_base.h" | 22 | #include "video_core/renderer_base.h" |
| 23 | #include "video_core/shader_notify.h" | ||
| 23 | #include "video_core/video_core.h" | 24 | #include "video_core/video_core.h" |
| 24 | 25 | ||
| 25 | namespace Tegra { | 26 | namespace Tegra { |
| @@ -36,6 +37,7 @@ GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& render | |||
| 36 | kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager); | 37 | kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager); |
| 37 | maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager); | 38 | maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager); |
| 38 | kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager); | 39 | kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager); |
| 40 | shader_notify = std::make_unique<VideoCore::ShaderNotify>(); | ||
| 39 | } | 41 | } |
| 40 | 42 | ||
| 41 | GPU::~GPU() = default; | 43 | GPU::~GPU() = default; |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 2c42483bd..19a34c402 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -33,59 +33,68 @@ class System; | |||
| 33 | 33 | ||
| 34 | namespace VideoCore { | 34 | namespace VideoCore { |
| 35 | class RendererBase; | 35 | class RendererBase; |
| 36 | class ShaderNotify; | ||
| 36 | } // namespace VideoCore | 37 | } // namespace VideoCore |
| 37 | 38 | ||
| 38 | namespace Tegra { | 39 | namespace Tegra { |
| 39 | 40 | ||
| 40 | enum class RenderTargetFormat : u32 { | 41 | enum class RenderTargetFormat : u32 { |
| 41 | NONE = 0x0, | 42 | NONE = 0x0, |
| 42 | RGBA32_FLOAT = 0xC0, | 43 | R32B32G32A32_FLOAT = 0xC0, |
| 43 | RGBA32_UINT = 0xC2, | 44 | R32G32B32A32_SINT = 0xC1, |
| 44 | RGBA16_UNORM = 0xC6, | 45 | R32G32B32A32_UINT = 0xC2, |
| 45 | RGBA16_SNORM = 0xC7, | 46 | R16G16B16A16_UNORM = 0xC6, |
| 46 | RGBA16_UINT = 0xC9, | 47 | R16G16B16A16_SNORM = 0xC7, |
| 47 | RGBA16_FLOAT = 0xCA, | 48 | R16G16B16A16_SINT = 0xC8, |
| 48 | RG32_FLOAT = 0xCB, | 49 | R16G16B16A16_UINT = 0xC9, |
| 49 | RG32_UINT = 0xCD, | 50 | R16G16B16A16_FLOAT = 0xCA, |
| 50 | RGBX16_FLOAT = 0xCE, | 51 | R32G32_FLOAT = 0xCB, |
| 51 | BGRA8_UNORM = 0xCF, | 52 | R32G32_SINT = 0xCC, |
| 52 | BGRA8_SRGB = 0xD0, | 53 | R32G32_UINT = 0xCD, |
| 53 | RGB10_A2_UNORM = 0xD1, | 54 | R16G16B16X16_FLOAT = 0xCE, |
| 54 | RGBA8_UNORM = 0xD5, | 55 | B8G8R8A8_UNORM = 0xCF, |
| 55 | RGBA8_SRGB = 0xD6, | 56 | B8G8R8A8_SRGB = 0xD0, |
| 56 | RGBA8_SNORM = 0xD7, | 57 | A2B10G10R10_UNORM = 0xD1, |
| 57 | RGBA8_UINT = 0xD9, | 58 | A2B10G10R10_UINT = 0xD2, |
| 58 | RG16_UNORM = 0xDA, | 59 | A8B8G8R8_UNORM = 0xD5, |
| 59 | RG16_SNORM = 0xDB, | 60 | A8B8G8R8_SRGB = 0xD6, |
| 60 | RG16_SINT = 0xDC, | 61 | A8B8G8R8_SNORM = 0xD7, |
| 61 | RG16_UINT = 0xDD, | 62 | A8B8G8R8_SINT = 0xD8, |
| 62 | RG16_FLOAT = 0xDE, | 63 | A8B8G8R8_UINT = 0xD9, |
| 63 | R11G11B10_FLOAT = 0xE0, | 64 | R16G16_UNORM = 0xDA, |
| 65 | R16G16_SNORM = 0xDB, | ||
| 66 | R16G16_SINT = 0xDC, | ||
| 67 | R16G16_UINT = 0xDD, | ||
| 68 | R16G16_FLOAT = 0xDE, | ||
| 69 | B10G11R11_FLOAT = 0xE0, | ||
| 64 | R32_SINT = 0xE3, | 70 | R32_SINT = 0xE3, |
| 65 | R32_UINT = 0xE4, | 71 | R32_UINT = 0xE4, |
| 66 | R32_FLOAT = 0xE5, | 72 | R32_FLOAT = 0xE5, |
| 67 | B5G6R5_UNORM = 0xE8, | 73 | R5G6B5_UNORM = 0xE8, |
| 68 | BGR5A1_UNORM = 0xE9, | 74 | A1R5G5B5_UNORM = 0xE9, |
| 69 | RG8_UNORM = 0xEA, | 75 | R8G8_UNORM = 0xEA, |
| 70 | RG8_SNORM = 0xEB, | 76 | R8G8_SNORM = 0xEB, |
| 71 | RG8_UINT = 0xED, | 77 | R8G8_SINT = 0xEC, |
| 78 | R8G8_UINT = 0xED, | ||
| 72 | R16_UNORM = 0xEE, | 79 | R16_UNORM = 0xEE, |
| 73 | R16_SNORM = 0xEF, | 80 | R16_SNORM = 0xEF, |
| 74 | R16_SINT = 0xF0, | 81 | R16_SINT = 0xF0, |
| 75 | R16_UINT = 0xF1, | 82 | R16_UINT = 0xF1, |
| 76 | R16_FLOAT = 0xF2, | 83 | R16_FLOAT = 0xF2, |
| 77 | R8_UNORM = 0xF3, | 84 | R8_UNORM = 0xF3, |
| 85 | R8_SNORM = 0xF4, | ||
| 86 | R8_SINT = 0xF5, | ||
| 78 | R8_UINT = 0xF6, | 87 | R8_UINT = 0xF6, |
| 79 | }; | 88 | }; |
| 80 | 89 | ||
| 81 | enum class DepthFormat : u32 { | 90 | enum class DepthFormat : u32 { |
| 82 | Z32_FLOAT = 0xA, | 91 | D32_FLOAT = 0xA, |
| 83 | Z16_UNORM = 0x13, | 92 | D16_UNORM = 0x13, |
| 84 | S8_Z24_UNORM = 0x14, | 93 | S8_UINT_Z24_UNORM = 0x14, |
| 85 | Z24_X8_UNORM = 0x15, | 94 | D24X8_UNORM = 0x15, |
| 86 | Z24_S8_UNORM = 0x16, | 95 | D24S8_UNORM = 0x16, |
| 87 | Z24_C8_UNORM = 0x18, | 96 | D24C8_UNORM = 0x18, |
| 88 | Z32_S8_X24_FLOAT = 0x19, | 97 | D32_FLOAT_S8X24_UINT = 0x19, |
| 89 | }; | 98 | }; |
| 90 | 99 | ||
| 91 | struct CommandListHeader; | 100 | struct CommandListHeader; |
| @@ -96,9 +105,9 @@ class DebugContext; | |||
| 96 | */ | 105 | */ |
| 97 | struct FramebufferConfig { | 106 | struct FramebufferConfig { |
| 98 | enum class PixelFormat : u32 { | 107 | enum class PixelFormat : u32 { |
| 99 | ABGR8 = 1, | 108 | A8B8G8R8_UNORM = 1, |
| 100 | RGB565 = 4, | 109 | RGB565_UNORM = 4, |
| 101 | BGRA8 = 5, | 110 | B8G8R8A8_UNORM = 5, |
| 102 | }; | 111 | }; |
| 103 | 112 | ||
| 104 | VAddr address; | 113 | VAddr address; |
| @@ -207,6 +216,14 @@ public: | |||
| 207 | return *renderer; | 216 | return *renderer; |
| 208 | } | 217 | } |
| 209 | 218 | ||
| 219 | VideoCore::ShaderNotify& ShaderNotify() { | ||
| 220 | return *shader_notify; | ||
| 221 | } | ||
| 222 | |||
| 223 | const VideoCore::ShaderNotify& ShaderNotify() const { | ||
| 224 | return *shader_notify; | ||
| 225 | } | ||
| 226 | |||
| 210 | // Waits for the GPU to finish working | 227 | // Waits for the GPU to finish working |
| 211 | virtual void WaitIdle() const = 0; | 228 | virtual void WaitIdle() const = 0; |
| 212 | 229 | ||
| @@ -347,6 +364,8 @@ private: | |||
| 347 | std::unique_ptr<Engines::MaxwellDMA> maxwell_dma; | 364 | std::unique_ptr<Engines::MaxwellDMA> maxwell_dma; |
| 348 | /// Inline memory engine | 365 | /// Inline memory engine |
| 349 | std::unique_ptr<Engines::KeplerMemory> kepler_memory; | 366 | std::unique_ptr<Engines::KeplerMemory> kepler_memory; |
| 367 | /// Shader build notifier | ||
| 368 | std::unique_ptr<VideoCore::ShaderNotify> shader_notify; | ||
| 350 | 369 | ||
| 351 | std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{}; | 370 | std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{}; |
| 352 | 371 | ||
diff --git a/src/video_core/morton.cpp b/src/video_core/morton.cpp index 836b25c1d..9da9fb4ff 100644 --- a/src/video_core/morton.cpp +++ b/src/video_core/morton.cpp | |||
| @@ -41,146 +41,168 @@ static void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth | |||
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static constexpr ConversionArray morton_to_linear_fns = { | 43 | static constexpr ConversionArray morton_to_linear_fns = { |
| 44 | MortonCopy<true, PixelFormat::ABGR8U>, | 44 | MortonCopy<true, PixelFormat::A8B8G8R8_UNORM>, |
| 45 | MortonCopy<true, PixelFormat::ABGR8S>, | 45 | MortonCopy<true, PixelFormat::A8B8G8R8_SNORM>, |
| 46 | MortonCopy<true, PixelFormat::ABGR8UI>, | 46 | MortonCopy<true, PixelFormat::A8B8G8R8_SINT>, |
| 47 | MortonCopy<true, PixelFormat::B5G6R5U>, | 47 | MortonCopy<true, PixelFormat::A8B8G8R8_UINT>, |
| 48 | MortonCopy<true, PixelFormat::A2B10G10R10U>, | 48 | MortonCopy<true, PixelFormat::R5G6B5_UNORM>, |
| 49 | MortonCopy<true, PixelFormat::A1B5G5R5U>, | 49 | MortonCopy<true, PixelFormat::B5G6R5_UNORM>, |
| 50 | MortonCopy<true, PixelFormat::R8U>, | 50 | MortonCopy<true, PixelFormat::A1R5G5B5_UNORM>, |
| 51 | MortonCopy<true, PixelFormat::R8UI>, | 51 | MortonCopy<true, PixelFormat::A2B10G10R10_UNORM>, |
| 52 | MortonCopy<true, PixelFormat::RGBA16F>, | 52 | MortonCopy<true, PixelFormat::A2B10G10R10_UINT>, |
| 53 | MortonCopy<true, PixelFormat::RGBA16U>, | 53 | MortonCopy<true, PixelFormat::A1B5G5R5_UNORM>, |
| 54 | MortonCopy<true, PixelFormat::RGBA16S>, | 54 | MortonCopy<true, PixelFormat::R8_UNORM>, |
| 55 | MortonCopy<true, PixelFormat::RGBA16UI>, | 55 | MortonCopy<true, PixelFormat::R8_SNORM>, |
| 56 | MortonCopy<true, PixelFormat::R11FG11FB10F>, | 56 | MortonCopy<true, PixelFormat::R8_SINT>, |
| 57 | MortonCopy<true, PixelFormat::RGBA32UI>, | 57 | MortonCopy<true, PixelFormat::R8_UINT>, |
| 58 | MortonCopy<true, PixelFormat::DXT1>, | 58 | MortonCopy<true, PixelFormat::R16G16B16A16_FLOAT>, |
| 59 | MortonCopy<true, PixelFormat::DXT23>, | 59 | MortonCopy<true, PixelFormat::R16G16B16A16_UNORM>, |
| 60 | MortonCopy<true, PixelFormat::DXT45>, | 60 | MortonCopy<true, PixelFormat::R16G16B16A16_SNORM>, |
| 61 | MortonCopy<true, PixelFormat::DXN1>, | 61 | MortonCopy<true, PixelFormat::R16G16B16A16_SINT>, |
| 62 | MortonCopy<true, PixelFormat::DXN2UNORM>, | 62 | MortonCopy<true, PixelFormat::R16G16B16A16_UINT>, |
| 63 | MortonCopy<true, PixelFormat::DXN2SNORM>, | 63 | MortonCopy<true, PixelFormat::B10G11R11_FLOAT>, |
| 64 | MortonCopy<true, PixelFormat::BC7U>, | 64 | MortonCopy<true, PixelFormat::R32G32B32A32_UINT>, |
| 65 | MortonCopy<true, PixelFormat::BC6H_UF16>, | 65 | MortonCopy<true, PixelFormat::BC1_RGBA_UNORM>, |
| 66 | MortonCopy<true, PixelFormat::BC6H_SF16>, | 66 | MortonCopy<true, PixelFormat::BC2_UNORM>, |
| 67 | MortonCopy<true, PixelFormat::ASTC_2D_4X4>, | 67 | MortonCopy<true, PixelFormat::BC3_UNORM>, |
| 68 | MortonCopy<true, PixelFormat::BGRA8>, | 68 | MortonCopy<true, PixelFormat::BC4_UNORM>, |
| 69 | MortonCopy<true, PixelFormat::RGBA32F>, | 69 | MortonCopy<true, PixelFormat::BC4_SNORM>, |
| 70 | MortonCopy<true, PixelFormat::RG32F>, | 70 | MortonCopy<true, PixelFormat::BC5_UNORM>, |
| 71 | MortonCopy<true, PixelFormat::R32F>, | 71 | MortonCopy<true, PixelFormat::BC5_SNORM>, |
| 72 | MortonCopy<true, PixelFormat::R16F>, | 72 | MortonCopy<true, PixelFormat::BC7_UNORM>, |
| 73 | MortonCopy<true, PixelFormat::R16U>, | 73 | MortonCopy<true, PixelFormat::BC6H_UFLOAT>, |
| 74 | MortonCopy<true, PixelFormat::R16S>, | 74 | MortonCopy<true, PixelFormat::BC6H_SFLOAT>, |
| 75 | MortonCopy<true, PixelFormat::R16UI>, | 75 | MortonCopy<true, PixelFormat::ASTC_2D_4X4_UNORM>, |
| 76 | MortonCopy<true, PixelFormat::R16I>, | 76 | MortonCopy<true, PixelFormat::B8G8R8A8_UNORM>, |
| 77 | MortonCopy<true, PixelFormat::RG16>, | 77 | MortonCopy<true, PixelFormat::R32G32B32A32_FLOAT>, |
| 78 | MortonCopy<true, PixelFormat::RG16F>, | 78 | MortonCopy<true, PixelFormat::R32G32B32A32_SINT>, |
| 79 | MortonCopy<true, PixelFormat::RG16UI>, | 79 | MortonCopy<true, PixelFormat::R32G32_FLOAT>, |
| 80 | MortonCopy<true, PixelFormat::RG16I>, | 80 | MortonCopy<true, PixelFormat::R32G32_SINT>, |
| 81 | MortonCopy<true, PixelFormat::RG16S>, | 81 | MortonCopy<true, PixelFormat::R32_FLOAT>, |
| 82 | MortonCopy<true, PixelFormat::RGB32F>, | 82 | MortonCopy<true, PixelFormat::R16_FLOAT>, |
| 83 | MortonCopy<true, PixelFormat::RGBA8_SRGB>, | 83 | MortonCopy<true, PixelFormat::R16_UNORM>, |
| 84 | MortonCopy<true, PixelFormat::RG8U>, | 84 | MortonCopy<true, PixelFormat::R16_SNORM>, |
| 85 | MortonCopy<true, PixelFormat::RG8S>, | 85 | MortonCopy<true, PixelFormat::R16_UINT>, |
| 86 | MortonCopy<true, PixelFormat::RG8UI>, | 86 | MortonCopy<true, PixelFormat::R16_SINT>, |
| 87 | MortonCopy<true, PixelFormat::RG32UI>, | 87 | MortonCopy<true, PixelFormat::R16G16_UNORM>, |
| 88 | MortonCopy<true, PixelFormat::RGBX16F>, | 88 | MortonCopy<true, PixelFormat::R16G16_FLOAT>, |
| 89 | MortonCopy<true, PixelFormat::R32UI>, | 89 | MortonCopy<true, PixelFormat::R16G16_UINT>, |
| 90 | MortonCopy<true, PixelFormat::R32I>, | 90 | MortonCopy<true, PixelFormat::R16G16_SINT>, |
| 91 | MortonCopy<true, PixelFormat::ASTC_2D_8X8>, | 91 | MortonCopy<true, PixelFormat::R16G16_SNORM>, |
| 92 | MortonCopy<true, PixelFormat::ASTC_2D_8X5>, | 92 | MortonCopy<true, PixelFormat::R32G32B32_FLOAT>, |
| 93 | MortonCopy<true, PixelFormat::ASTC_2D_5X4>, | 93 | MortonCopy<true, PixelFormat::A8B8G8R8_SRGB>, |
| 94 | MortonCopy<true, PixelFormat::BGRA8_SRGB>, | 94 | MortonCopy<true, PixelFormat::R8G8_UNORM>, |
| 95 | MortonCopy<true, PixelFormat::DXT1_SRGB>, | 95 | MortonCopy<true, PixelFormat::R8G8_SNORM>, |
| 96 | MortonCopy<true, PixelFormat::DXT23_SRGB>, | 96 | MortonCopy<true, PixelFormat::R8G8_SINT>, |
| 97 | MortonCopy<true, PixelFormat::DXT45_SRGB>, | 97 | MortonCopy<true, PixelFormat::R8G8_UINT>, |
| 98 | MortonCopy<true, PixelFormat::BC7U_SRGB>, | 98 | MortonCopy<true, PixelFormat::R32G32_UINT>, |
| 99 | MortonCopy<true, PixelFormat::R4G4B4A4U>, | 99 | MortonCopy<true, PixelFormat::R16G16B16X16_FLOAT>, |
| 100 | MortonCopy<true, PixelFormat::R32_UINT>, | ||
| 101 | MortonCopy<true, PixelFormat::R32_SINT>, | ||
| 102 | MortonCopy<true, PixelFormat::ASTC_2D_8X8_UNORM>, | ||
| 103 | MortonCopy<true, PixelFormat::ASTC_2D_8X5_UNORM>, | ||
| 104 | MortonCopy<true, PixelFormat::ASTC_2D_5X4_UNORM>, | ||
| 105 | MortonCopy<true, PixelFormat::B8G8R8A8_SRGB>, | ||
| 106 | MortonCopy<true, PixelFormat::BC1_RGBA_SRGB>, | ||
| 107 | MortonCopy<true, PixelFormat::BC2_SRGB>, | ||
| 108 | MortonCopy<true, PixelFormat::BC3_SRGB>, | ||
| 109 | MortonCopy<true, PixelFormat::BC7_SRGB>, | ||
| 110 | MortonCopy<true, PixelFormat::A4B4G4R4_UNORM>, | ||
| 100 | MortonCopy<true, PixelFormat::ASTC_2D_4X4_SRGB>, | 111 | MortonCopy<true, PixelFormat::ASTC_2D_4X4_SRGB>, |
| 101 | MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>, | 112 | MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>, |
| 102 | MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>, | 113 | MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>, |
| 103 | MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>, | 114 | MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>, |
| 104 | MortonCopy<true, PixelFormat::ASTC_2D_5X5>, | 115 | MortonCopy<true, PixelFormat::ASTC_2D_5X5_UNORM>, |
| 105 | MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>, | 116 | MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>, |
| 106 | MortonCopy<true, PixelFormat::ASTC_2D_10X8>, | 117 | MortonCopy<true, PixelFormat::ASTC_2D_10X8_UNORM>, |
| 107 | MortonCopy<true, PixelFormat::ASTC_2D_10X8_SRGB>, | 118 | MortonCopy<true, PixelFormat::ASTC_2D_10X8_SRGB>, |
| 108 | MortonCopy<true, PixelFormat::ASTC_2D_6X6>, | 119 | MortonCopy<true, PixelFormat::ASTC_2D_6X6_UNORM>, |
| 109 | MortonCopy<true, PixelFormat::ASTC_2D_6X6_SRGB>, | 120 | MortonCopy<true, PixelFormat::ASTC_2D_6X6_SRGB>, |
| 110 | MortonCopy<true, PixelFormat::ASTC_2D_10X10>, | 121 | MortonCopy<true, PixelFormat::ASTC_2D_10X10_UNORM>, |
| 111 | MortonCopy<true, PixelFormat::ASTC_2D_10X10_SRGB>, | 122 | MortonCopy<true, PixelFormat::ASTC_2D_10X10_SRGB>, |
| 112 | MortonCopy<true, PixelFormat::ASTC_2D_12X12>, | 123 | MortonCopy<true, PixelFormat::ASTC_2D_12X12_UNORM>, |
| 113 | MortonCopy<true, PixelFormat::ASTC_2D_12X12_SRGB>, | 124 | MortonCopy<true, PixelFormat::ASTC_2D_12X12_SRGB>, |
| 114 | MortonCopy<true, PixelFormat::ASTC_2D_8X6>, | 125 | MortonCopy<true, PixelFormat::ASTC_2D_8X6_UNORM>, |
| 115 | MortonCopy<true, PixelFormat::ASTC_2D_8X6_SRGB>, | 126 | MortonCopy<true, PixelFormat::ASTC_2D_8X6_SRGB>, |
| 116 | MortonCopy<true, PixelFormat::ASTC_2D_6X5>, | 127 | MortonCopy<true, PixelFormat::ASTC_2D_6X5_UNORM>, |
| 117 | MortonCopy<true, PixelFormat::ASTC_2D_6X5_SRGB>, | 128 | MortonCopy<true, PixelFormat::ASTC_2D_6X5_SRGB>, |
| 118 | MortonCopy<true, PixelFormat::E5B9G9R9F>, | 129 | MortonCopy<true, PixelFormat::E5B9G9R9_FLOAT>, |
| 119 | MortonCopy<true, PixelFormat::Z32F>, | 130 | MortonCopy<true, PixelFormat::D32_FLOAT>, |
| 120 | MortonCopy<true, PixelFormat::Z16>, | 131 | MortonCopy<true, PixelFormat::D16_UNORM>, |
| 121 | MortonCopy<true, PixelFormat::Z24S8>, | 132 | MortonCopy<true, PixelFormat::D24_UNORM_S8_UINT>, |
| 122 | MortonCopy<true, PixelFormat::S8Z24>, | 133 | MortonCopy<true, PixelFormat::S8_UINT_D24_UNORM>, |
| 123 | MortonCopy<true, PixelFormat::Z32FS8>, | 134 | MortonCopy<true, PixelFormat::D32_FLOAT_S8_UINT>, |
| 124 | }; | 135 | }; |
| 125 | 136 | ||
| 126 | static constexpr ConversionArray linear_to_morton_fns = { | 137 | static constexpr ConversionArray linear_to_morton_fns = { |
| 127 | MortonCopy<false, PixelFormat::ABGR8U>, | 138 | MortonCopy<false, PixelFormat::A8B8G8R8_UNORM>, |
| 128 | MortonCopy<false, PixelFormat::ABGR8S>, | 139 | MortonCopy<false, PixelFormat::A8B8G8R8_SNORM>, |
| 129 | MortonCopy<false, PixelFormat::ABGR8UI>, | 140 | MortonCopy<false, PixelFormat::A8B8G8R8_SINT>, |
| 130 | MortonCopy<false, PixelFormat::B5G6R5U>, | 141 | MortonCopy<false, PixelFormat::A8B8G8R8_UINT>, |
| 131 | MortonCopy<false, PixelFormat::A2B10G10R10U>, | 142 | MortonCopy<false, PixelFormat::R5G6B5_UNORM>, |
| 132 | MortonCopy<false, PixelFormat::A1B5G5R5U>, | 143 | MortonCopy<false, PixelFormat::B5G6R5_UNORM>, |
| 133 | MortonCopy<false, PixelFormat::R8U>, | 144 | MortonCopy<false, PixelFormat::A1R5G5B5_UNORM>, |
| 134 | MortonCopy<false, PixelFormat::R8UI>, | 145 | MortonCopy<false, PixelFormat::A2B10G10R10_UNORM>, |
| 135 | MortonCopy<false, PixelFormat::RGBA16F>, | 146 | MortonCopy<false, PixelFormat::A2B10G10R10_UINT>, |
| 136 | MortonCopy<false, PixelFormat::RGBA16S>, | 147 | MortonCopy<false, PixelFormat::A1B5G5R5_UNORM>, |
| 137 | MortonCopy<false, PixelFormat::RGBA16U>, | 148 | MortonCopy<false, PixelFormat::R8_UNORM>, |
| 138 | MortonCopy<false, PixelFormat::RGBA16UI>, | 149 | MortonCopy<false, PixelFormat::R8_SNORM>, |
| 139 | MortonCopy<false, PixelFormat::R11FG11FB10F>, | 150 | MortonCopy<false, PixelFormat::R8_SINT>, |
| 140 | MortonCopy<false, PixelFormat::RGBA32UI>, | 151 | MortonCopy<false, PixelFormat::R8_UINT>, |
| 141 | MortonCopy<false, PixelFormat::DXT1>, | 152 | MortonCopy<false, PixelFormat::R16G16B16A16_FLOAT>, |
| 142 | MortonCopy<false, PixelFormat::DXT23>, | 153 | MortonCopy<false, PixelFormat::R16G16B16A16_SNORM>, |
| 143 | MortonCopy<false, PixelFormat::DXT45>, | 154 | MortonCopy<false, PixelFormat::R16G16B16A16_SINT>, |
| 144 | MortonCopy<false, PixelFormat::DXN1>, | 155 | MortonCopy<false, PixelFormat::R16G16B16A16_UNORM>, |
| 145 | MortonCopy<false, PixelFormat::DXN2UNORM>, | 156 | MortonCopy<false, PixelFormat::R16G16B16A16_UINT>, |
| 146 | MortonCopy<false, PixelFormat::DXN2SNORM>, | 157 | MortonCopy<false, PixelFormat::B10G11R11_FLOAT>, |
| 147 | MortonCopy<false, PixelFormat::BC7U>, | 158 | MortonCopy<false, PixelFormat::R32G32B32A32_UINT>, |
| 148 | MortonCopy<false, PixelFormat::BC6H_UF16>, | 159 | MortonCopy<false, PixelFormat::BC1_RGBA_UNORM>, |
| 149 | MortonCopy<false, PixelFormat::BC6H_SF16>, | 160 | MortonCopy<false, PixelFormat::BC2_UNORM>, |
| 161 | MortonCopy<false, PixelFormat::BC3_UNORM>, | ||
| 162 | MortonCopy<false, PixelFormat::BC4_UNORM>, | ||
| 163 | MortonCopy<false, PixelFormat::BC4_SNORM>, | ||
| 164 | MortonCopy<false, PixelFormat::BC5_UNORM>, | ||
| 165 | MortonCopy<false, PixelFormat::BC5_SNORM>, | ||
| 166 | MortonCopy<false, PixelFormat::BC7_UNORM>, | ||
| 167 | MortonCopy<false, PixelFormat::BC6H_UFLOAT>, | ||
| 168 | MortonCopy<false, PixelFormat::BC6H_SFLOAT>, | ||
| 150 | // TODO(Subv): Swizzling ASTC formats are not supported | 169 | // TODO(Subv): Swizzling ASTC formats are not supported |
| 151 | nullptr, | 170 | nullptr, |
| 152 | MortonCopy<false, PixelFormat::BGRA8>, | 171 | MortonCopy<false, PixelFormat::B8G8R8A8_UNORM>, |
| 153 | MortonCopy<false, PixelFormat::RGBA32F>, | 172 | MortonCopy<false, PixelFormat::R32G32B32A32_FLOAT>, |
| 154 | MortonCopy<false, PixelFormat::RG32F>, | 173 | MortonCopy<false, PixelFormat::R32G32B32A32_SINT>, |
| 155 | MortonCopy<false, PixelFormat::R32F>, | 174 | MortonCopy<false, PixelFormat::R32G32_FLOAT>, |
| 156 | MortonCopy<false, PixelFormat::R16F>, | 175 | MortonCopy<false, PixelFormat::R32G32_SINT>, |
| 157 | MortonCopy<false, PixelFormat::R16U>, | 176 | MortonCopy<false, PixelFormat::R32_FLOAT>, |
| 158 | MortonCopy<false, PixelFormat::R16S>, | 177 | MortonCopy<false, PixelFormat::R16_FLOAT>, |
| 159 | MortonCopy<false, PixelFormat::R16UI>, | 178 | MortonCopy<false, PixelFormat::R16_UNORM>, |
| 160 | MortonCopy<false, PixelFormat::R16I>, | 179 | MortonCopy<false, PixelFormat::R16_SNORM>, |
| 161 | MortonCopy<false, PixelFormat::RG16>, | 180 | MortonCopy<false, PixelFormat::R16_UINT>, |
| 162 | MortonCopy<false, PixelFormat::RG16F>, | 181 | MortonCopy<false, PixelFormat::R16_SINT>, |
| 163 | MortonCopy<false, PixelFormat::RG16UI>, | 182 | MortonCopy<false, PixelFormat::R16G16_UNORM>, |
| 164 | MortonCopy<false, PixelFormat::RG16I>, | 183 | MortonCopy<false, PixelFormat::R16G16_FLOAT>, |
| 165 | MortonCopy<false, PixelFormat::RG16S>, | 184 | MortonCopy<false, PixelFormat::R16G16_UINT>, |
| 166 | MortonCopy<false, PixelFormat::RGB32F>, | 185 | MortonCopy<false, PixelFormat::R16G16_SINT>, |
| 167 | MortonCopy<false, PixelFormat::RGBA8_SRGB>, | 186 | MortonCopy<false, PixelFormat::R16G16_SNORM>, |
| 168 | MortonCopy<false, PixelFormat::RG8U>, | 187 | MortonCopy<false, PixelFormat::R32G32B32_FLOAT>, |
| 169 | MortonCopy<false, PixelFormat::RG8S>, | 188 | MortonCopy<false, PixelFormat::A8B8G8R8_SRGB>, |
| 170 | MortonCopy<false, PixelFormat::RG8UI>, | 189 | MortonCopy<false, PixelFormat::R8G8_UNORM>, |
| 171 | MortonCopy<false, PixelFormat::RG32UI>, | 190 | MortonCopy<false, PixelFormat::R8G8_SNORM>, |
| 172 | MortonCopy<false, PixelFormat::RGBX16F>, | 191 | MortonCopy<false, PixelFormat::R8G8_SINT>, |
| 173 | MortonCopy<false, PixelFormat::R32UI>, | 192 | MortonCopy<false, PixelFormat::R8G8_UINT>, |
| 174 | MortonCopy<false, PixelFormat::R32I>, | 193 | MortonCopy<false, PixelFormat::R32G32_UINT>, |
| 194 | MortonCopy<false, PixelFormat::R16G16B16X16_FLOAT>, | ||
| 195 | MortonCopy<false, PixelFormat::R32_UINT>, | ||
| 196 | MortonCopy<false, PixelFormat::R32_SINT>, | ||
| 175 | nullptr, | 197 | nullptr, |
| 176 | nullptr, | 198 | nullptr, |
| 177 | nullptr, | 199 | nullptr, |
| 178 | MortonCopy<false, PixelFormat::BGRA8_SRGB>, | 200 | MortonCopy<false, PixelFormat::B8G8R8A8_SRGB>, |
| 179 | MortonCopy<false, PixelFormat::DXT1_SRGB>, | 201 | MortonCopy<false, PixelFormat::BC1_RGBA_SRGB>, |
| 180 | MortonCopy<false, PixelFormat::DXT23_SRGB>, | 202 | MortonCopy<false, PixelFormat::BC2_SRGB>, |
| 181 | MortonCopy<false, PixelFormat::DXT45_SRGB>, | 203 | MortonCopy<false, PixelFormat::BC3_SRGB>, |
| 182 | MortonCopy<false, PixelFormat::BC7U_SRGB>, | 204 | MortonCopy<false, PixelFormat::BC7_SRGB>, |
| 183 | MortonCopy<false, PixelFormat::R4G4B4A4U>, | 205 | MortonCopy<false, PixelFormat::A4B4G4R4_UNORM>, |
| 184 | nullptr, | 206 | nullptr, |
| 185 | nullptr, | 207 | nullptr, |
| 186 | nullptr, | 208 | nullptr, |
| @@ -199,12 +221,12 @@ static constexpr ConversionArray linear_to_morton_fns = { | |||
| 199 | nullptr, | 221 | nullptr, |
| 200 | nullptr, | 222 | nullptr, |
| 201 | nullptr, | 223 | nullptr, |
| 202 | MortonCopy<false, PixelFormat::E5B9G9R9F>, | 224 | MortonCopy<false, PixelFormat::E5B9G9R9_FLOAT>, |
| 203 | MortonCopy<false, PixelFormat::Z32F>, | 225 | MortonCopy<false, PixelFormat::D32_FLOAT>, |
| 204 | MortonCopy<false, PixelFormat::Z16>, | 226 | MortonCopy<false, PixelFormat::D16_UNORM>, |
| 205 | MortonCopy<false, PixelFormat::Z24S8>, | 227 | MortonCopy<false, PixelFormat::D24_UNORM_S8_UINT>, |
| 206 | MortonCopy<false, PixelFormat::S8Z24>, | 228 | MortonCopy<false, PixelFormat::S8_UINT_D24_UNORM>, |
| 207 | MortonCopy<false, PixelFormat::Z32FS8>, | 229 | MortonCopy<false, PixelFormat::D32_FLOAT_S8_UINT>, |
| 208 | }; | 230 | }; |
| 209 | 231 | ||
| 210 | static MortonCopyFn GetSwizzleFunction(MortonSwizzleMode mode, Surface::PixelFormat format) { | 232 | static MortonCopyFn GetSwizzleFunction(MortonSwizzleMode mode, Surface::PixelFormat format) { |
diff --git a/src/video_core/renderer_opengl/gl_arb_decompiler.cpp b/src/video_core/renderer_opengl/gl_arb_decompiler.cpp index eb5158407..4489abf61 100644 --- a/src/video_core/renderer_opengl/gl_arb_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_arb_decompiler.cpp | |||
| @@ -185,10 +185,6 @@ std::string TextureType(const MetaTexture& meta) { | |||
| 185 | return type; | 185 | return type; |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | std::string GlobalMemoryName(const GlobalMemoryBase& base) { | ||
| 189 | return fmt::format("gmem{}_{}", base.cbuf_index, base.cbuf_offset); | ||
| 190 | } | ||
| 191 | |||
| 192 | class ARBDecompiler final { | 188 | class ARBDecompiler final { |
| 193 | public: | 189 | public: |
| 194 | explicit ARBDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry, | 190 | explicit ARBDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry, |
| @@ -199,6 +195,8 @@ public: | |||
| 199 | } | 195 | } |
| 200 | 196 | ||
| 201 | private: | 197 | private: |
| 198 | void DefineGlobalMemory(); | ||
| 199 | |||
| 202 | void DeclareHeader(); | 200 | void DeclareHeader(); |
| 203 | void DeclareVertex(); | 201 | void DeclareVertex(); |
| 204 | void DeclareGeometry(); | 202 | void DeclareGeometry(); |
| @@ -228,6 +226,7 @@ private: | |||
| 228 | 226 | ||
| 229 | std::pair<std::string, std::size_t> BuildCoords(Operation); | 227 | std::pair<std::string, std::size_t> BuildCoords(Operation); |
| 230 | std::string BuildAoffi(Operation); | 228 | std::string BuildAoffi(Operation); |
| 229 | std::string GlobalMemoryPointer(const GmemNode& gmem); | ||
| 231 | void Exit(); | 230 | void Exit(); |
| 232 | 231 | ||
| 233 | std::string Assign(Operation); | 232 | std::string Assign(Operation); |
| @@ -378,10 +377,8 @@ private: | |||
| 378 | std::string address; | 377 | std::string address; |
| 379 | std::string_view opname; | 378 | std::string_view opname; |
| 380 | if (const auto gmem = std::get_if<GmemNode>(&*operation[0])) { | 379 | if (const auto gmem = std::get_if<GmemNode>(&*operation[0])) { |
| 381 | AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem->GetRealAddress()), | 380 | address = GlobalMemoryPointer(*gmem); |
| 382 | Visit(gmem->GetBaseAddress())); | 381 | opname = "ATOM"; |
| 383 | address = fmt::format("{}[{}]", GlobalMemoryName(gmem->GetDescriptor()), temporary); | ||
| 384 | opname = "ATOMB"; | ||
| 385 | } else if (const auto smem = std::get_if<SmemNode>(&*operation[0])) { | 382 | } else if (const auto smem = std::get_if<SmemNode>(&*operation[0])) { |
| 386 | address = fmt::format("shared_mem[{}]", Visit(smem->GetAddress())); | 383 | address = fmt::format("shared_mem[{}]", Visit(smem->GetAddress())); |
| 387 | opname = "ATOMS"; | 384 | opname = "ATOMS"; |
| @@ -456,9 +453,13 @@ private: | |||
| 456 | shader_source += '\n'; | 453 | shader_source += '\n'; |
| 457 | } | 454 | } |
| 458 | 455 | ||
| 459 | std::string AllocTemporary() { | 456 | std::string AllocLongVectorTemporary() { |
| 460 | max_temporaries = std::max(max_temporaries, num_temporaries + 1); | 457 | max_long_temporaries = std::max(max_long_temporaries, num_long_temporaries + 1); |
| 461 | return fmt::format("T{}.x", num_temporaries++); | 458 | return fmt::format("L{}", num_long_temporaries++); |
| 459 | } | ||
| 460 | |||
| 461 | std::string AllocLongTemporary() { | ||
| 462 | return fmt::format("{}.x", AllocLongVectorTemporary()); | ||
| 462 | } | 463 | } |
| 463 | 464 | ||
| 464 | std::string AllocVectorTemporary() { | 465 | std::string AllocVectorTemporary() { |
| @@ -466,8 +467,13 @@ private: | |||
| 466 | return fmt::format("T{}", num_temporaries++); | 467 | return fmt::format("T{}", num_temporaries++); |
| 467 | } | 468 | } |
| 468 | 469 | ||
| 470 | std::string AllocTemporary() { | ||
| 471 | return fmt::format("{}.x", AllocVectorTemporary()); | ||
| 472 | } | ||
| 473 | |||
| 469 | void ResetTemporaries() noexcept { | 474 | void ResetTemporaries() noexcept { |
| 470 | num_temporaries = 0; | 475 | num_temporaries = 0; |
| 476 | num_long_temporaries = 0; | ||
| 471 | } | 477 | } |
| 472 | 478 | ||
| 473 | const Device& device; | 479 | const Device& device; |
| @@ -478,6 +484,11 @@ private: | |||
| 478 | std::size_t num_temporaries = 0; | 484 | std::size_t num_temporaries = 0; |
| 479 | std::size_t max_temporaries = 0; | 485 | std::size_t max_temporaries = 0; |
| 480 | 486 | ||
| 487 | std::size_t num_long_temporaries = 0; | ||
| 488 | std::size_t max_long_temporaries = 0; | ||
| 489 | |||
| 490 | std::map<GlobalMemoryBase, u32> global_memory_names; | ||
| 491 | |||
| 481 | std::string shader_source; | 492 | std::string shader_source; |
| 482 | 493 | ||
| 483 | static constexpr std::string_view ADD_F32 = "ADD.F32"; | 494 | static constexpr std::string_view ADD_F32 = "ADD.F32"; |
| @@ -784,6 +795,8 @@ private: | |||
| 784 | ARBDecompiler::ARBDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry, | 795 | ARBDecompiler::ARBDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry, |
| 785 | ShaderType stage, std::string_view identifier) | 796 | ShaderType stage, std::string_view identifier) |
| 786 | : device{device}, ir{ir}, registry{registry}, stage{stage} { | 797 | : device{device}, ir{ir}, registry{registry}, stage{stage} { |
| 798 | DefineGlobalMemory(); | ||
| 799 | |||
| 787 | AddLine("TEMP RC;"); | 800 | AddLine("TEMP RC;"); |
| 788 | AddLine("TEMP FSWZA[4];"); | 801 | AddLine("TEMP FSWZA[4];"); |
| 789 | AddLine("TEMP FSWZB[4];"); | 802 | AddLine("TEMP FSWZB[4];"); |
| @@ -829,12 +842,20 @@ std::string_view HeaderStageName(ShaderType stage) { | |||
| 829 | } | 842 | } |
| 830 | } | 843 | } |
| 831 | 844 | ||
| 845 | void ARBDecompiler::DefineGlobalMemory() { | ||
| 846 | u32 binding = 0; | ||
| 847 | for (const auto& pair : ir.GetGlobalMemory()) { | ||
| 848 | const GlobalMemoryBase base = pair.first; | ||
| 849 | global_memory_names.emplace(base, binding); | ||
| 850 | ++binding; | ||
| 851 | } | ||
| 852 | } | ||
| 853 | |||
| 832 | void ARBDecompiler::DeclareHeader() { | 854 | void ARBDecompiler::DeclareHeader() { |
| 833 | AddLine("!!NV{}5.0", HeaderStageName(stage)); | 855 | AddLine("!!NV{}5.0", HeaderStageName(stage)); |
| 834 | // Enabling this allows us to cheat on some instructions like TXL with SHADOWARRAY2D | 856 | // Enabling this allows us to cheat on some instructions like TXL with SHADOWARRAY2D |
| 835 | AddLine("OPTION NV_internal;"); | 857 | AddLine("OPTION NV_internal;"); |
| 836 | AddLine("OPTION NV_gpu_program_fp64;"); | 858 | AddLine("OPTION NV_gpu_program_fp64;"); |
| 837 | AddLine("OPTION NV_shader_storage_buffer;"); | ||
| 838 | AddLine("OPTION NV_shader_thread_group;"); | 859 | AddLine("OPTION NV_shader_thread_group;"); |
| 839 | if (ir.UsesWarps() && device.HasWarpIntrinsics()) { | 860 | if (ir.UsesWarps() && device.HasWarpIntrinsics()) { |
| 840 | AddLine("OPTION NV_shader_thread_shuffle;"); | 861 | AddLine("OPTION NV_shader_thread_shuffle;"); |
| @@ -951,11 +972,10 @@ void ARBDecompiler::DeclareLocalMemory() { | |||
| 951 | } | 972 | } |
| 952 | 973 | ||
| 953 | void ARBDecompiler::DeclareGlobalMemory() { | 974 | void ARBDecompiler::DeclareGlobalMemory() { |
| 954 | u32 binding = 0; // device.GetBaseBindings(stage).shader_storage_buffer; | 975 | const std::size_t num_entries = ir.GetGlobalMemory().size(); |
| 955 | for (const auto& pair : ir.GetGlobalMemory()) { | 976 | if (num_entries > 0) { |
| 956 | const auto& base = pair.first; | 977 | const std::size_t num_vectors = Common::AlignUp(num_entries, 2) / 2; |
| 957 | AddLine("STORAGE {}[] = {{ program.storage[{}] }};", GlobalMemoryName(base), binding); | 978 | AddLine("PARAM c[{}] = {{ program.local[0..{}] }};", num_vectors, num_vectors - 1); |
| 958 | ++binding; | ||
| 959 | } | 979 | } |
| 960 | } | 980 | } |
| 961 | 981 | ||
| @@ -977,6 +997,9 @@ void ARBDecompiler::DeclareTemporaries() { | |||
| 977 | for (std::size_t i = 0; i < max_temporaries; ++i) { | 997 | for (std::size_t i = 0; i < max_temporaries; ++i) { |
| 978 | AddLine("TEMP T{};", i); | 998 | AddLine("TEMP T{};", i); |
| 979 | } | 999 | } |
| 1000 | for (std::size_t i = 0; i < max_long_temporaries; ++i) { | ||
| 1001 | AddLine("LONG TEMP L{};", i); | ||
| 1002 | } | ||
| 980 | } | 1003 | } |
| 981 | 1004 | ||
| 982 | void ARBDecompiler::DeclarePredicates() { | 1005 | void ARBDecompiler::DeclarePredicates() { |
| @@ -1339,10 +1362,7 @@ std::string ARBDecompiler::Visit(const Node& node) { | |||
| 1339 | 1362 | ||
| 1340 | if (const auto gmem = std::get_if<GmemNode>(&*node)) { | 1363 | if (const auto gmem = std::get_if<GmemNode>(&*node)) { |
| 1341 | std::string temporary = AllocTemporary(); | 1364 | std::string temporary = AllocTemporary(); |
| 1342 | AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem->GetRealAddress()), | 1365 | AddLine("LOAD.U32 {}, {};", temporary, GlobalMemoryPointer(*gmem)); |
| 1343 | Visit(gmem->GetBaseAddress())); | ||
| 1344 | AddLine("LDB.U32 {}, {}[{}];", temporary, GlobalMemoryName(gmem->GetDescriptor()), | ||
| 1345 | temporary); | ||
| 1346 | return temporary; | 1366 | return temporary; |
| 1347 | } | 1367 | } |
| 1348 | 1368 | ||
| @@ -1419,6 +1439,22 @@ std::string ARBDecompiler::BuildAoffi(Operation operation) { | |||
| 1419 | return fmt::format(", offset({})", temporary); | 1439 | return fmt::format(", offset({})", temporary); |
| 1420 | } | 1440 | } |
| 1421 | 1441 | ||
| 1442 | std::string ARBDecompiler::GlobalMemoryPointer(const GmemNode& gmem) { | ||
| 1443 | const u32 binding = global_memory_names.at(gmem.GetDescriptor()); | ||
| 1444 | const char result_swizzle = binding % 2 == 0 ? 'x' : 'y'; | ||
| 1445 | |||
| 1446 | const std::string pointer = AllocLongVectorTemporary(); | ||
| 1447 | std::string temporary = AllocTemporary(); | ||
| 1448 | |||
| 1449 | const u32 local_index = binding / 2; | ||
| 1450 | AddLine("PK64.U {}, c[{}];", pointer, local_index); | ||
| 1451 | AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem.GetRealAddress()), | ||
| 1452 | Visit(gmem.GetBaseAddress())); | ||
| 1453 | AddLine("CVT.U64.U32 {}.z, {};", pointer, temporary); | ||
| 1454 | AddLine("ADD.U64 {}.x, {}.{}, {}.z;", pointer, pointer, result_swizzle, pointer); | ||
| 1455 | return fmt::format("{}.x", pointer); | ||
| 1456 | } | ||
| 1457 | |||
| 1422 | void ARBDecompiler::Exit() { | 1458 | void ARBDecompiler::Exit() { |
| 1423 | if (stage != ShaderType::Fragment) { | 1459 | if (stage != ShaderType::Fragment) { |
| 1424 | AddLine("RET;"); | 1460 | AddLine("RET;"); |
| @@ -1515,11 +1551,7 @@ std::string ARBDecompiler::Assign(Operation operation) { | |||
| 1515 | ResetTemporaries(); | 1551 | ResetTemporaries(); |
| 1516 | return {}; | 1552 | return {}; |
| 1517 | } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) { | 1553 | } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) { |
| 1518 | const std::string temporary = AllocTemporary(); | 1554 | AddLine("STORE.U32 {}, {};", Visit(src), GlobalMemoryPointer(*gmem)); |
| 1519 | AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem->GetRealAddress()), | ||
| 1520 | Visit(gmem->GetBaseAddress())); | ||
| 1521 | AddLine("STB.U32 {}, {}[{}];", Visit(src), GlobalMemoryName(gmem->GetDescriptor()), | ||
| 1522 | temporary); | ||
| 1523 | ResetTemporaries(); | 1555 | ResetTemporaries(); |
| 1524 | return {}; | 1556 | return {}; |
| 1525 | } else { | 1557 | } else { |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index e461e4c70..e866d8f2f 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp | |||
| @@ -26,7 +26,7 @@ Buffer::Buffer(const Device& device, VAddr cpu_addr, std::size_t size) | |||
| 26 | : VideoCommon::BufferBlock{cpu_addr, size} { | 26 | : VideoCommon::BufferBlock{cpu_addr, size} { |
| 27 | gl_buffer.Create(); | 27 | gl_buffer.Create(); |
| 28 | glNamedBufferData(gl_buffer.handle, static_cast<GLsizeiptr>(size), nullptr, GL_DYNAMIC_DRAW); | 28 | glNamedBufferData(gl_buffer.handle, static_cast<GLsizeiptr>(size), nullptr, GL_DYNAMIC_DRAW); |
| 29 | if (device.HasVertexBufferUnifiedMemory()) { | 29 | if (device.UseAssemblyShaders() || device.HasVertexBufferUnifiedMemory()) { |
| 30 | glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_WRITE); | 30 | glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_WRITE); |
| 31 | glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); | 31 | glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); |
| 32 | } | 32 | } |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index c1f20f0ab..630acb73b 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -233,6 +233,8 @@ Device::Device() | |||
| 233 | GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 && | 233 | GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 && |
| 234 | GLAD_GL_NV_transform_feedback && GLAD_GL_NV_transform_feedback2; | 234 | GLAD_GL_NV_transform_feedback && GLAD_GL_NV_transform_feedback2; |
| 235 | 235 | ||
| 236 | use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue(); | ||
| 237 | |||
| 236 | LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); | 238 | LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); |
| 237 | LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug); | 239 | LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug); |
| 238 | LOG_INFO(Render_OpenGL, "Renderer_PreciseBug: {}", has_precise_bug); | 240 | LOG_INFO(Render_OpenGL, "Renderer_PreciseBug: {}", has_precise_bug); |
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index e1d811966..94d38d7d1 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h | |||
| @@ -104,6 +104,10 @@ public: | |||
| 104 | return use_assembly_shaders; | 104 | return use_assembly_shaders; |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | bool UseAsynchronousShaders() const { | ||
| 108 | return use_asynchronous_shaders; | ||
| 109 | } | ||
| 110 | |||
| 107 | private: | 111 | private: |
| 108 | static bool TestVariableAoffi(); | 112 | static bool TestVariableAoffi(); |
| 109 | static bool TestPreciseBug(); | 113 | static bool TestPreciseBug(); |
| @@ -127,6 +131,7 @@ private: | |||
| 127 | bool has_fast_buffer_sub_data{}; | 131 | bool has_fast_buffer_sub_data{}; |
| 128 | bool has_nv_viewport_array2{}; | 132 | bool has_nv_viewport_array2{}; |
| 129 | bool use_assembly_shaders{}; | 133 | bool use_assembly_shaders{}; |
| 134 | bool use_asynchronous_shaders{}; | ||
| 130 | }; | 135 | }; |
| 131 | 136 | ||
| 132 | } // namespace OpenGL | 137 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index e960a0ef1..03e82c599 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -139,6 +139,18 @@ void oglEnable(GLenum cap, bool state) { | |||
| 139 | (state ? glEnable : glDisable)(cap); | 139 | (state ? glEnable : glDisable)(cap); |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | void UpdateBindlessPointers(GLenum target, GLuint64EXT* pointers, std::size_t num_entries) { | ||
| 143 | if (num_entries == 0) { | ||
| 144 | return; | ||
| 145 | } | ||
| 146 | if (num_entries % 2 == 1) { | ||
| 147 | pointers[num_entries] = 0; | ||
| 148 | } | ||
| 149 | const GLsizei num_vectors = static_cast<GLsizei>((num_entries + 1) / 2); | ||
| 150 | glProgramLocalParametersI4uivNV(target, 0, num_vectors, | ||
| 151 | reinterpret_cast<const GLuint*>(pointers)); | ||
| 152 | } | ||
| 153 | |||
| 142 | } // Anonymous namespace | 154 | } // Anonymous namespace |
| 143 | 155 | ||
| 144 | RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, | 156 | RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, |
| @@ -149,7 +161,8 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind | |||
| 149 | shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, | 161 | shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, |
| 150 | buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, | 162 | buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, |
| 151 | fence_manager{system, *this, texture_cache, buffer_cache, query_cache}, system{system}, | 163 | fence_manager{system, *this, texture_cache, buffer_cache, query_cache}, system{system}, |
| 152 | screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker} { | 164 | screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker}, |
| 165 | async_shaders{emu_window} { | ||
| 153 | CheckExtensions(); | 166 | CheckExtensions(); |
| 154 | 167 | ||
| 155 | unified_uniform_buffer.Create(); | 168 | unified_uniform_buffer.Create(); |
| @@ -162,6 +175,23 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind | |||
| 162 | nullptr, 0); | 175 | nullptr, 0); |
| 163 | } | 176 | } |
| 164 | } | 177 | } |
| 178 | |||
| 179 | if (device.UseAsynchronousShaders()) { | ||
| 180 | // Max worker threads we should allow | ||
| 181 | constexpr auto MAX_THREADS = 2u; | ||
| 182 | // Amount of threads we should reserve for other parts of yuzu | ||
| 183 | constexpr auto RESERVED_THREADS = 6u; | ||
| 184 | // Get the amount of threads we can use(this can return zero) | ||
| 185 | const auto cpu_thread_count = | ||
| 186 | std::max(RESERVED_THREADS, std::thread::hardware_concurrency()); | ||
| 187 | // Deduce how many "extra" threads we have to use. | ||
| 188 | const auto max_threads_unused = cpu_thread_count - RESERVED_THREADS; | ||
| 189 | // Always allow at least 1 thread regardless of our settings | ||
| 190 | const auto max_worker_count = std::max(1u, max_threads_unused); | ||
| 191 | // Don't use more than MAX_THREADS | ||
| 192 | const auto worker_count = std::min(max_worker_count, MAX_THREADS); | ||
| 193 | async_shaders.AllocateWorkers(worker_count); | ||
| 194 | } | ||
| 165 | } | 195 | } |
| 166 | 196 | ||
| 167 | RasterizerOpenGL::~RasterizerOpenGL() { | 197 | RasterizerOpenGL::~RasterizerOpenGL() { |
| @@ -306,7 +336,6 @@ GLintptr RasterizerOpenGL::SetupIndexBuffer() { | |||
| 306 | void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | 336 | void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { |
| 307 | MICROPROFILE_SCOPE(OpenGL_Shader); | 337 | MICROPROFILE_SCOPE(OpenGL_Shader); |
| 308 | auto& gpu = system.GPU().Maxwell3D(); | 338 | auto& gpu = system.GPU().Maxwell3D(); |
| 309 | std::size_t num_ssbos = 0; | ||
| 310 | u32 clip_distances = 0; | 339 | u32 clip_distances = 0; |
| 311 | 340 | ||
| 312 | for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { | 341 | for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { |
| @@ -329,31 +358,15 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 329 | } | 358 | } |
| 330 | 359 | ||
| 331 | // Currently this stages are not supported in the OpenGL backend. | 360 | // Currently this stages are not supported in the OpenGL backend. |
| 332 | // Todo(Blinkhawk): Port tesselation shaders from Vulkan to OpenGL | 361 | // TODO(Blinkhawk): Port tesselation shaders from Vulkan to OpenGL |
| 333 | if (program == Maxwell::ShaderProgram::TesselationControl) { | 362 | if (program == Maxwell::ShaderProgram::TesselationControl || |
| 334 | continue; | 363 | program == Maxwell::ShaderProgram::TesselationEval) { |
| 335 | } else if (program == Maxwell::ShaderProgram::TesselationEval) { | ||
| 336 | continue; | 364 | continue; |
| 337 | } | 365 | } |
| 338 | 366 | ||
| 339 | Shader* const shader = shader_cache.GetStageProgram(program); | 367 | Shader* const shader = shader_cache.GetStageProgram(program, async_shaders); |
| 340 | |||
| 341 | if (device.UseAssemblyShaders()) { | ||
| 342 | // Check for ARB limitation. We only have 16 SSBOs per context state. To workaround this | ||
| 343 | // all stages share the same bindings. | ||
| 344 | const std::size_t num_stage_ssbos = shader->GetEntries().global_memory_entries.size(); | ||
| 345 | ASSERT_MSG(num_stage_ssbos == 0 || num_ssbos == 0, "SSBOs on more than one stage"); | ||
| 346 | num_ssbos += num_stage_ssbos; | ||
| 347 | } | ||
| 348 | 368 | ||
| 349 | // Stage indices are 0 - 5 | 369 | const GLuint program_handle = shader->IsBuilt() ? shader->GetHandle() : 0; |
| 350 | const std::size_t stage = index == 0 ? 0 : index - 1; | ||
| 351 | SetupDrawConstBuffers(stage, shader); | ||
| 352 | SetupDrawGlobalMemory(stage, shader); | ||
| 353 | SetupDrawTextures(stage, shader); | ||
| 354 | SetupDrawImages(stage, shader); | ||
| 355 | |||
| 356 | const GLuint program_handle = shader->GetHandle(); | ||
| 357 | switch (program) { | 370 | switch (program) { |
| 358 | case Maxwell::ShaderProgram::VertexA: | 371 | case Maxwell::ShaderProgram::VertexA: |
| 359 | case Maxwell::ShaderProgram::VertexB: | 372 | case Maxwell::ShaderProgram::VertexB: |
| @@ -370,6 +383,13 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 370 | shader_config.enable.Value(), shader_config.offset); | 383 | shader_config.enable.Value(), shader_config.offset); |
| 371 | } | 384 | } |
| 372 | 385 | ||
| 386 | // Stage indices are 0 - 5 | ||
| 387 | const std::size_t stage = index == 0 ? 0 : index - 1; | ||
| 388 | SetupDrawConstBuffers(stage, shader); | ||
| 389 | SetupDrawGlobalMemory(stage, shader); | ||
| 390 | SetupDrawTextures(stage, shader); | ||
| 391 | SetupDrawImages(stage, shader); | ||
| 392 | |||
| 373 | // Workaround for Intel drivers. | 393 | // Workaround for Intel drivers. |
| 374 | // When a clip distance is enabled but not set in the shader it crops parts of the screen | 394 | // When a clip distance is enabled but not set in the shader it crops parts of the screen |
| 375 | // (sometimes it's half the screen, sometimes three quarters). To avoid this, enable the | 395 | // (sometimes it's half the screen, sometimes three quarters). To avoid this, enable the |
| @@ -731,6 +751,8 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) { | |||
| 731 | current_cbuf = 0; | 751 | current_cbuf = 0; |
| 732 | 752 | ||
| 733 | auto kernel = shader_cache.GetComputeKernel(code_addr); | 753 | auto kernel = shader_cache.GetComputeKernel(code_addr); |
| 754 | program_manager.BindCompute(kernel->GetHandle()); | ||
| 755 | |||
| 734 | SetupComputeTextures(kernel); | 756 | SetupComputeTextures(kernel); |
| 735 | SetupComputeImages(kernel); | 757 | SetupComputeImages(kernel); |
| 736 | 758 | ||
| @@ -745,7 +767,6 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) { | |||
| 745 | buffer_cache.Unmap(); | 767 | buffer_cache.Unmap(); |
| 746 | 768 | ||
| 747 | const auto& launch_desc = system.GPU().KeplerCompute().launch_description; | 769 | const auto& launch_desc = system.GPU().KeplerCompute().launch_description; |
| 748 | program_manager.BindCompute(kernel->GetHandle()); | ||
| 749 | glDispatchCompute(launch_desc.grid_dim_x, launch_desc.grid_dim_y, launch_desc.grid_dim_z); | 770 | glDispatchCompute(launch_desc.grid_dim_x, launch_desc.grid_dim_y, launch_desc.grid_dim_z); |
| 750 | ++num_queued_commands; | 771 | ++num_queued_commands; |
| 751 | } | 772 | } |
| @@ -1005,40 +1026,66 @@ void RasterizerOpenGL::SetupConstBuffer(GLenum stage, u32 binding, | |||
| 1005 | } | 1026 | } |
| 1006 | 1027 | ||
| 1007 | void RasterizerOpenGL::SetupDrawGlobalMemory(std::size_t stage_index, Shader* shader) { | 1028 | void RasterizerOpenGL::SetupDrawGlobalMemory(std::size_t stage_index, Shader* shader) { |
| 1029 | static constexpr std::array TARGET_LUT = { | ||
| 1030 | GL_VERTEX_PROGRAM_NV, GL_TESS_CONTROL_PROGRAM_NV, GL_TESS_EVALUATION_PROGRAM_NV, | ||
| 1031 | GL_GEOMETRY_PROGRAM_NV, GL_FRAGMENT_PROGRAM_NV, | ||
| 1032 | }; | ||
| 1033 | |||
| 1008 | auto& gpu{system.GPU()}; | 1034 | auto& gpu{system.GPU()}; |
| 1009 | auto& memory_manager{gpu.MemoryManager()}; | 1035 | auto& memory_manager{gpu.MemoryManager()}; |
| 1010 | const auto cbufs{gpu.Maxwell3D().state.shader_stages[stage_index]}; | 1036 | const auto& cbufs{gpu.Maxwell3D().state.shader_stages[stage_index]}; |
| 1037 | const auto& entries{shader->GetEntries().global_memory_entries}; | ||
| 1038 | |||
| 1039 | std::array<GLuint64EXT, 32> pointers; | ||
| 1040 | ASSERT(entries.size() < pointers.size()); | ||
| 1011 | 1041 | ||
| 1012 | u32 binding = | 1042 | const bool assembly_shaders = device.UseAssemblyShaders(); |
| 1013 | device.UseAssemblyShaders() ? 0 : device.GetBaseBindings(stage_index).shader_storage_buffer; | 1043 | u32 binding = assembly_shaders ? 0 : device.GetBaseBindings(stage_index).shader_storage_buffer; |
| 1014 | for (const auto& entry : shader->GetEntries().global_memory_entries) { | 1044 | for (const auto& entry : entries) { |
| 1015 | const GPUVAddr addr{cbufs.const_buffers[entry.cbuf_index].address + entry.cbuf_offset}; | 1045 | const GPUVAddr addr{cbufs.const_buffers[entry.cbuf_index].address + entry.cbuf_offset}; |
| 1016 | const GPUVAddr gpu_addr{memory_manager.Read<u64>(addr)}; | 1046 | const GPUVAddr gpu_addr{memory_manager.Read<u64>(addr)}; |
| 1017 | const u32 size{memory_manager.Read<u32>(addr + 8)}; | 1047 | const u32 size{memory_manager.Read<u32>(addr + 8)}; |
| 1018 | SetupGlobalMemory(binding++, entry, gpu_addr, size); | 1048 | SetupGlobalMemory(binding, entry, gpu_addr, size, &pointers[binding]); |
| 1049 | ++binding; | ||
| 1050 | } | ||
| 1051 | if (assembly_shaders) { | ||
| 1052 | UpdateBindlessPointers(TARGET_LUT[stage_index], pointers.data(), entries.size()); | ||
| 1019 | } | 1053 | } |
| 1020 | } | 1054 | } |
| 1021 | 1055 | ||
| 1022 | void RasterizerOpenGL::SetupComputeGlobalMemory(Shader* kernel) { | 1056 | void RasterizerOpenGL::SetupComputeGlobalMemory(Shader* kernel) { |
| 1023 | auto& gpu{system.GPU()}; | 1057 | auto& gpu{system.GPU()}; |
| 1024 | auto& memory_manager{gpu.MemoryManager()}; | 1058 | auto& memory_manager{gpu.MemoryManager()}; |
| 1025 | const auto cbufs{gpu.KeplerCompute().launch_description.const_buffer_config}; | 1059 | const auto& cbufs{gpu.KeplerCompute().launch_description.const_buffer_config}; |
| 1060 | const auto& entries{kernel->GetEntries().global_memory_entries}; | ||
| 1061 | |||
| 1062 | std::array<GLuint64EXT, 32> pointers; | ||
| 1063 | ASSERT(entries.size() < pointers.size()); | ||
| 1026 | 1064 | ||
| 1027 | u32 binding = 0; | 1065 | u32 binding = 0; |
| 1028 | for (const auto& entry : kernel->GetEntries().global_memory_entries) { | 1066 | for (const auto& entry : entries) { |
| 1029 | const auto addr{cbufs[entry.cbuf_index].Address() + entry.cbuf_offset}; | 1067 | const GPUVAddr addr{cbufs[entry.cbuf_index].Address() + entry.cbuf_offset}; |
| 1030 | const auto gpu_addr{memory_manager.Read<u64>(addr)}; | 1068 | const GPUVAddr gpu_addr{memory_manager.Read<u64>(addr)}; |
| 1031 | const auto size{memory_manager.Read<u32>(addr + 8)}; | 1069 | const u32 size{memory_manager.Read<u32>(addr + 8)}; |
| 1032 | SetupGlobalMemory(binding++, entry, gpu_addr, size); | 1070 | SetupGlobalMemory(binding, entry, gpu_addr, size, &pointers[binding]); |
| 1071 | ++binding; | ||
| 1072 | } | ||
| 1073 | if (device.UseAssemblyShaders()) { | ||
| 1074 | UpdateBindlessPointers(GL_COMPUTE_PROGRAM_NV, pointers.data(), entries.size()); | ||
| 1033 | } | 1075 | } |
| 1034 | } | 1076 | } |
| 1035 | 1077 | ||
| 1036 | void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, | 1078 | void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, |
| 1037 | GPUVAddr gpu_addr, std::size_t size) { | 1079 | GPUVAddr gpu_addr, std::size_t size, |
| 1038 | const auto alignment{device.GetShaderStorageBufferAlignment()}; | 1080 | GLuint64EXT* pointer) { |
| 1081 | const std::size_t alignment{device.GetShaderStorageBufferAlignment()}; | ||
| 1039 | const auto info = buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.is_written); | 1082 | const auto info = buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.is_written); |
| 1040 | glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, info.handle, info.offset, | 1083 | if (device.UseAssemblyShaders()) { |
| 1041 | static_cast<GLsizeiptr>(size)); | 1084 | *pointer = info.address + info.offset; |
| 1085 | } else { | ||
| 1086 | glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, info.handle, info.offset, | ||
| 1087 | static_cast<GLsizeiptr>(size)); | ||
| 1088 | } | ||
| 1042 | } | 1089 | } |
| 1043 | 1090 | ||
| 1044 | void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, Shader* shader) { | 1091 | void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, Shader* shader) { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 4f082592f..ccc6f50f6 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include "video_core/renderer_opengl/gl_state_tracker.h" | 33 | #include "video_core/renderer_opengl/gl_state_tracker.h" |
| 34 | #include "video_core/renderer_opengl/gl_texture_cache.h" | 34 | #include "video_core/renderer_opengl/gl_texture_cache.h" |
| 35 | #include "video_core/renderer_opengl/utils.h" | 35 | #include "video_core/renderer_opengl/utils.h" |
| 36 | #include "video_core/shader/async_shaders.h" | ||
| 36 | #include "video_core/textures/texture.h" | 37 | #include "video_core/textures/texture.h" |
| 37 | 38 | ||
| 38 | namespace Core { | 39 | namespace Core { |
| @@ -91,6 +92,14 @@ public: | |||
| 91 | return num_queued_commands > 0; | 92 | return num_queued_commands > 0; |
| 92 | } | 93 | } |
| 93 | 94 | ||
| 95 | VideoCommon::Shader::AsyncShaders& GetAsyncShaders() { | ||
| 96 | return async_shaders; | ||
| 97 | } | ||
| 98 | |||
| 99 | const VideoCommon::Shader::AsyncShaders& GetAsyncShaders() const { | ||
| 100 | return async_shaders; | ||
| 101 | } | ||
| 102 | |||
| 94 | private: | 103 | private: |
| 95 | /// Configures the color and depth framebuffer states. | 104 | /// Configures the color and depth framebuffer states. |
| 96 | void ConfigureFramebuffers(); | 105 | void ConfigureFramebuffers(); |
| @@ -115,9 +124,9 @@ private: | |||
| 115 | /// Configures the current global memory entries to use for the kernel invocation. | 124 | /// Configures the current global memory entries to use for the kernel invocation. |
| 116 | void SetupComputeGlobalMemory(Shader* kernel); | 125 | void SetupComputeGlobalMemory(Shader* kernel); |
| 117 | 126 | ||
| 118 | /// Configures a constant buffer. | 127 | /// Configures a global memory buffer. |
| 119 | void SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, GPUVAddr gpu_addr, | 128 | void SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, GPUVAddr gpu_addr, |
| 120 | std::size_t size); | 129 | std::size_t size, GLuint64EXT* pointer); |
| 121 | 130 | ||
| 122 | /// Configures the current textures to use for the draw command. | 131 | /// Configures the current textures to use for the draw command. |
| 123 | void SetupDrawTextures(std::size_t stage_index, Shader* shader); | 132 | void SetupDrawTextures(std::size_t stage_index, Shader* shader); |
| @@ -242,6 +251,7 @@ private: | |||
| 242 | ScreenInfo& screen_info; | 251 | ScreenInfo& screen_info; |
| 243 | ProgramManager& program_manager; | 252 | ProgramManager& program_manager; |
| 244 | StateTracker& state_tracker; | 253 | StateTracker& state_tracker; |
| 254 | VideoCommon::Shader::AsyncShaders async_shaders; | ||
| 245 | 255 | ||
| 246 | static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; | 256 | static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; |
| 247 | 257 | ||
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index f8b322227..b05cb641c 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h | |||
| @@ -177,6 +177,12 @@ public: | |||
| 177 | Release(); | 177 | Release(); |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | OGLAssemblyProgram& operator=(OGLAssemblyProgram&& o) noexcept { | ||
| 181 | Release(); | ||
| 182 | handle = std::exchange(o.handle, 0); | ||
| 183 | return *this; | ||
| 184 | } | ||
| 185 | |||
| 180 | /// Deletes the internal OpenGL resource | 186 | /// Deletes the internal OpenGL resource |
| 181 | void Release(); | 187 | void Release(); |
| 182 | 188 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index c6a3bf3a1..f469ed656 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include "video_core/shader/registry.h" | 31 | #include "video_core/shader/registry.h" |
| 32 | #include "video_core/shader/shader_ir.h" | 32 | #include "video_core/shader/shader_ir.h" |
| 33 | #include "video_core/shader_cache.h" | 33 | #include "video_core/shader_cache.h" |
| 34 | #include "video_core/shader_notify.h" | ||
| 34 | 35 | ||
| 35 | namespace OpenGL { | 36 | namespace OpenGL { |
| 36 | 37 | ||
| @@ -140,9 +141,24 @@ std::shared_ptr<Registry> MakeRegistry(const ShaderDiskCacheEntry& entry) { | |||
| 140 | return registry; | 141 | return registry; |
| 141 | } | 142 | } |
| 142 | 143 | ||
| 144 | std::unordered_set<GLenum> GetSupportedFormats() { | ||
| 145 | GLint num_formats; | ||
| 146 | glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &num_formats); | ||
| 147 | |||
| 148 | std::vector<GLint> formats(num_formats); | ||
| 149 | glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, formats.data()); | ||
| 150 | |||
| 151 | std::unordered_set<GLenum> supported_formats; | ||
| 152 | for (const GLint format : formats) { | ||
| 153 | supported_formats.insert(static_cast<GLenum>(format)); | ||
| 154 | } | ||
| 155 | return supported_formats; | ||
| 156 | } | ||
| 157 | |||
| 158 | } // Anonymous namespace | ||
| 159 | |||
| 143 | ProgramSharedPtr BuildShader(const Device& device, ShaderType shader_type, u64 unique_identifier, | 160 | ProgramSharedPtr BuildShader(const Device& device, ShaderType shader_type, u64 unique_identifier, |
| 144 | const ShaderIR& ir, const Registry& registry, | 161 | const ShaderIR& ir, const Registry& registry, bool hint_retrievable) { |
| 145 | bool hint_retrievable = false) { | ||
| 146 | const std::string shader_id = MakeShaderID(unique_identifier, shader_type); | 162 | const std::string shader_id = MakeShaderID(unique_identifier, shader_type); |
| 147 | LOG_INFO(Render_OpenGL, "{}", shader_id); | 163 | LOG_INFO(Render_OpenGL, "{}", shader_id); |
| 148 | 164 | ||
| @@ -181,30 +197,17 @@ ProgramSharedPtr BuildShader(const Device& device, ShaderType shader_type, u64 u | |||
| 181 | return program; | 197 | return program; |
| 182 | } | 198 | } |
| 183 | 199 | ||
| 184 | std::unordered_set<GLenum> GetSupportedFormats() { | ||
| 185 | GLint num_formats; | ||
| 186 | glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &num_formats); | ||
| 187 | |||
| 188 | std::vector<GLint> formats(num_formats); | ||
| 189 | glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, formats.data()); | ||
| 190 | |||
| 191 | std::unordered_set<GLenum> supported_formats; | ||
| 192 | for (const GLint format : formats) { | ||
| 193 | supported_formats.insert(static_cast<GLenum>(format)); | ||
| 194 | } | ||
| 195 | return supported_formats; | ||
| 196 | } | ||
| 197 | |||
| 198 | } // Anonymous namespace | ||
| 199 | |||
| 200 | Shader::Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry_, ShaderEntries entries_, | 200 | Shader::Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry_, ShaderEntries entries_, |
| 201 | ProgramSharedPtr program_) | 201 | ProgramSharedPtr program_, bool is_built) |
| 202 | : registry{std::move(registry_)}, entries{std::move(entries_)}, program{std::move(program_)} { | 202 | : registry{std::move(registry_)}, entries{std::move(entries_)}, program{std::move(program_)}, |
| 203 | is_built(is_built) { | ||
| 203 | handle = program->assembly_program.handle; | 204 | handle = program->assembly_program.handle; |
| 204 | if (handle == 0) { | 205 | if (handle == 0) { |
| 205 | handle = program->source_program.handle; | 206 | handle = program->source_program.handle; |
| 206 | } | 207 | } |
| 207 | ASSERT(handle != 0); | 208 | if (is_built) { |
| 209 | ASSERT(handle != 0); | ||
| 210 | } | ||
| 208 | } | 211 | } |
| 209 | 212 | ||
| 210 | Shader::~Shader() = default; | 213 | Shader::~Shader() = default; |
| @@ -214,42 +217,82 @@ GLuint Shader::GetHandle() const { | |||
| 214 | return handle; | 217 | return handle; |
| 215 | } | 218 | } |
| 216 | 219 | ||
| 217 | std::unique_ptr<Shader> Shader::CreateStageFromMemory(const ShaderParameters& params, | 220 | bool Shader::IsBuilt() const { |
| 218 | Maxwell::ShaderProgram program_type, | 221 | return is_built; |
| 219 | ProgramCode code, ProgramCode code_b) { | 222 | } |
| 223 | |||
| 224 | void Shader::AsyncOpenGLBuilt(OGLProgram new_program) { | ||
| 225 | program->source_program = std::move(new_program); | ||
| 226 | handle = program->source_program.handle; | ||
| 227 | is_built = true; | ||
| 228 | } | ||
| 229 | |||
| 230 | void Shader::AsyncGLASMBuilt(OGLAssemblyProgram new_program) { | ||
| 231 | program->assembly_program = std::move(new_program); | ||
| 232 | handle = program->assembly_program.handle; | ||
| 233 | is_built = true; | ||
| 234 | } | ||
| 235 | |||
| 236 | std::unique_ptr<Shader> Shader::CreateStageFromMemory( | ||
| 237 | const ShaderParameters& params, Maxwell::ShaderProgram program_type, ProgramCode code, | ||
| 238 | ProgramCode code_b, VideoCommon::Shader::AsyncShaders& async_shaders, VAddr cpu_addr) { | ||
| 220 | const auto shader_type = GetShaderType(program_type); | 239 | const auto shader_type = GetShaderType(program_type); |
| 221 | const std::size_t size_in_bytes = code.size() * sizeof(u64); | 240 | const std::size_t size_in_bytes = code.size() * sizeof(u64); |
| 222 | 241 | ||
| 223 | auto registry = std::make_shared<Registry>(shader_type, params.system.GPU().Maxwell3D()); | 242 | auto& gpu = params.system.GPU(); |
| 224 | const ShaderIR ir(code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, *registry); | 243 | gpu.ShaderNotify().MarkSharderBuilding(); |
| 225 | // TODO(Rodrigo): Handle VertexA shaders | 244 | |
| 226 | // std::optional<ShaderIR> ir_b; | 245 | auto registry = std::make_shared<Registry>(shader_type, gpu.Maxwell3D()); |
| 227 | // if (!code_b.empty()) { | 246 | if (!async_shaders.IsShaderAsync(params.system.GPU()) || |
| 228 | // ir_b.emplace(code_b, STAGE_MAIN_OFFSET); | 247 | !params.device.UseAsynchronousShaders()) { |
| 229 | // } | 248 | const ShaderIR ir(code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, *registry); |
| 230 | auto program = BuildShader(params.device, shader_type, params.unique_identifier, ir, *registry); | 249 | // TODO(Rodrigo): Handle VertexA shaders |
| 250 | // std::optional<ShaderIR> ir_b; | ||
| 251 | // if (!code_b.empty()) { | ||
| 252 | // ir_b.emplace(code_b, STAGE_MAIN_OFFSET); | ||
| 253 | // } | ||
| 254 | auto program = | ||
| 255 | BuildShader(params.device, shader_type, params.unique_identifier, ir, *registry); | ||
| 256 | ShaderDiskCacheEntry entry; | ||
| 257 | entry.type = shader_type; | ||
| 258 | entry.code = std::move(code); | ||
| 259 | entry.code_b = std::move(code_b); | ||
| 260 | entry.unique_identifier = params.unique_identifier; | ||
| 261 | entry.bound_buffer = registry->GetBoundBuffer(); | ||
| 262 | entry.graphics_info = registry->GetGraphicsInfo(); | ||
| 263 | entry.keys = registry->GetKeys(); | ||
| 264 | entry.bound_samplers = registry->GetBoundSamplers(); | ||
| 265 | entry.bindless_samplers = registry->GetBindlessSamplers(); | ||
| 266 | params.disk_cache.SaveEntry(std::move(entry)); | ||
| 267 | |||
| 268 | gpu.ShaderNotify().MarkShaderComplete(); | ||
| 269 | |||
| 270 | return std::unique_ptr<Shader>(new Shader(std::move(registry), | ||
| 271 | MakeEntries(params.device, ir, shader_type), | ||
| 272 | std::move(program), true)); | ||
| 273 | } else { | ||
| 274 | // Required for entries | ||
| 275 | const ShaderIR ir(code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, *registry); | ||
| 276 | auto entries = MakeEntries(params.device, ir, shader_type); | ||
| 231 | 277 | ||
| 232 | ShaderDiskCacheEntry entry; | 278 | async_shaders.QueueOpenGLShader(params.device, shader_type, params.unique_identifier, |
| 233 | entry.type = shader_type; | 279 | std::move(code), std::move(code_b), STAGE_MAIN_OFFSET, |
| 234 | entry.code = std::move(code); | 280 | COMPILER_SETTINGS, *registry, cpu_addr); |
| 235 | entry.code_b = std::move(code_b); | ||
| 236 | entry.unique_identifier = params.unique_identifier; | ||
| 237 | entry.bound_buffer = registry->GetBoundBuffer(); | ||
| 238 | entry.graphics_info = registry->GetGraphicsInfo(); | ||
| 239 | entry.keys = registry->GetKeys(); | ||
| 240 | entry.bound_samplers = registry->GetBoundSamplers(); | ||
| 241 | entry.bindless_samplers = registry->GetBindlessSamplers(); | ||
| 242 | params.disk_cache.SaveEntry(std::move(entry)); | ||
| 243 | 281 | ||
| 244 | return std::unique_ptr<Shader>(new Shader( | 282 | auto program = std::make_shared<ProgramHandle>(); |
| 245 | std::move(registry), MakeEntries(params.device, ir, shader_type), std::move(program))); | 283 | return std::unique_ptr<Shader>( |
| 284 | new Shader(std::move(registry), std::move(entries), std::move(program), false)); | ||
| 285 | } | ||
| 246 | } | 286 | } |
| 247 | 287 | ||
| 248 | std::unique_ptr<Shader> Shader::CreateKernelFromMemory(const ShaderParameters& params, | 288 | std::unique_ptr<Shader> Shader::CreateKernelFromMemory(const ShaderParameters& params, |
| 249 | ProgramCode code) { | 289 | ProgramCode code) { |
| 250 | const std::size_t size_in_bytes = code.size() * sizeof(u64); | 290 | const std::size_t size_in_bytes = code.size() * sizeof(u64); |
| 251 | 291 | ||
| 252 | auto& engine = params.system.GPU().KeplerCompute(); | 292 | auto& gpu = params.system.GPU(); |
| 293 | gpu.ShaderNotify().MarkSharderBuilding(); | ||
| 294 | |||
| 295 | auto& engine = gpu.KeplerCompute(); | ||
| 253 | auto registry = std::make_shared<Registry>(ShaderType::Compute, engine); | 296 | auto registry = std::make_shared<Registry>(ShaderType::Compute, engine); |
| 254 | const ShaderIR ir(code, KERNEL_MAIN_OFFSET, COMPILER_SETTINGS, *registry); | 297 | const ShaderIR ir(code, KERNEL_MAIN_OFFSET, COMPILER_SETTINGS, *registry); |
| 255 | const u64 uid = params.unique_identifier; | 298 | const u64 uid = params.unique_identifier; |
| @@ -266,6 +309,8 @@ std::unique_ptr<Shader> Shader::CreateKernelFromMemory(const ShaderParameters& p | |||
| 266 | entry.bindless_samplers = registry->GetBindlessSamplers(); | 309 | entry.bindless_samplers = registry->GetBindlessSamplers(); |
| 267 | params.disk_cache.SaveEntry(std::move(entry)); | 310 | params.disk_cache.SaveEntry(std::move(entry)); |
| 268 | 311 | ||
| 312 | gpu.ShaderNotify().MarkShaderComplete(); | ||
| 313 | |||
| 269 | return std::unique_ptr<Shader>(new Shader(std::move(registry), | 314 | return std::unique_ptr<Shader>(new Shader(std::move(registry), |
| 270 | MakeEntries(params.device, ir, ShaderType::Compute), | 315 | MakeEntries(params.device, ir, ShaderType::Compute), |
| 271 | std::move(program))); | 316 | std::move(program))); |
| @@ -436,14 +481,51 @@ ProgramSharedPtr ShaderCacheOpenGL::GeneratePrecompiledProgram( | |||
| 436 | return program; | 481 | return program; |
| 437 | } | 482 | } |
| 438 | 483 | ||
| 439 | Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { | 484 | Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program, |
| 485 | VideoCommon::Shader::AsyncShaders& async_shaders) { | ||
| 440 | if (!system.GPU().Maxwell3D().dirty.flags[Dirty::Shaders]) { | 486 | if (!system.GPU().Maxwell3D().dirty.flags[Dirty::Shaders]) { |
| 441 | return last_shaders[static_cast<std::size_t>(program)]; | 487 | auto* last_shader = last_shaders[static_cast<std::size_t>(program)]; |
| 488 | if (last_shader->IsBuilt()) { | ||
| 489 | return last_shader; | ||
| 490 | } | ||
| 442 | } | 491 | } |
| 443 | 492 | ||
| 444 | auto& memory_manager{system.GPU().MemoryManager()}; | 493 | auto& memory_manager{system.GPU().MemoryManager()}; |
| 445 | const GPUVAddr address{GetShaderAddress(system, program)}; | 494 | const GPUVAddr address{GetShaderAddress(system, program)}; |
| 446 | 495 | ||
| 496 | if (device.UseAsynchronousShaders() && async_shaders.HasCompletedWork()) { | ||
| 497 | auto completed_work = async_shaders.GetCompletedWork(); | ||
| 498 | for (auto& work : completed_work) { | ||
| 499 | Shader* shader = TryGet(work.cpu_address); | ||
| 500 | auto& gpu = system.GPU(); | ||
| 501 | gpu.ShaderNotify().MarkShaderComplete(); | ||
| 502 | if (shader == nullptr) { | ||
| 503 | continue; | ||
| 504 | } | ||
| 505 | using namespace VideoCommon::Shader; | ||
| 506 | if (work.backend == AsyncShaders::Backend::OpenGL) { | ||
| 507 | shader->AsyncOpenGLBuilt(std::move(work.program.opengl)); | ||
| 508 | } else if (work.backend == AsyncShaders::Backend::GLASM) { | ||
| 509 | shader->AsyncGLASMBuilt(std::move(work.program.glasm)); | ||
| 510 | } | ||
| 511 | |||
| 512 | ShaderDiskCacheEntry entry; | ||
| 513 | entry.type = work.shader_type; | ||
| 514 | entry.code = std::move(work.code); | ||
| 515 | entry.code_b = std::move(work.code_b); | ||
| 516 | entry.unique_identifier = work.uid; | ||
| 517 | |||
| 518 | auto& registry = shader->GetRegistry(); | ||
| 519 | |||
| 520 | entry.bound_buffer = registry.GetBoundBuffer(); | ||
| 521 | entry.graphics_info = registry.GetGraphicsInfo(); | ||
| 522 | entry.keys = registry.GetKeys(); | ||
| 523 | entry.bound_samplers = registry.GetBoundSamplers(); | ||
| 524 | entry.bindless_samplers = registry.GetBindlessSamplers(); | ||
| 525 | disk_cache.SaveEntry(std::move(entry)); | ||
| 526 | } | ||
| 527 | } | ||
| 528 | |||
| 447 | // Look up shader in the cache based on address | 529 | // Look up shader in the cache based on address |
| 448 | const auto cpu_addr{memory_manager.GpuToCpuAddress(address)}; | 530 | const auto cpu_addr{memory_manager.GpuToCpuAddress(address)}; |
| 449 | if (Shader* const shader{cpu_addr ? TryGet(*cpu_addr) : null_shader.get()}) { | 531 | if (Shader* const shader{cpu_addr ? TryGet(*cpu_addr) : null_shader.get()}) { |
| @@ -471,7 +553,8 @@ Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { | |||
| 471 | std::unique_ptr<Shader> shader; | 553 | std::unique_ptr<Shader> shader; |
| 472 | const auto found = runtime_cache.find(unique_identifier); | 554 | const auto found = runtime_cache.find(unique_identifier); |
| 473 | if (found == runtime_cache.end()) { | 555 | if (found == runtime_cache.end()) { |
| 474 | shader = Shader::CreateStageFromMemory(params, program, std::move(code), std::move(code_b)); | 556 | shader = Shader::CreateStageFromMemory(params, program, std::move(code), std::move(code_b), |
| 557 | async_shaders, cpu_addr.value_or(0)); | ||
| 475 | } else { | 558 | } else { |
| 476 | shader = Shader::CreateFromCache(params, found->second); | 559 | shader = Shader::CreateFromCache(params, found->second); |
| 477 | } | 560 | } |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 994aaeaf2..7528ac686 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -33,6 +33,10 @@ namespace Core::Frontend { | |||
| 33 | class EmuWindow; | 33 | class EmuWindow; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | namespace VideoCommon::Shader { | ||
| 37 | class AsyncShaders; | ||
| 38 | } | ||
| 39 | |||
| 36 | namespace OpenGL { | 40 | namespace OpenGL { |
| 37 | 41 | ||
| 38 | class Device; | 42 | class Device; |
| @@ -61,6 +65,11 @@ struct ShaderParameters { | |||
| 61 | u64 unique_identifier; | 65 | u64 unique_identifier; |
| 62 | }; | 66 | }; |
| 63 | 67 | ||
| 68 | ProgramSharedPtr BuildShader(const Device& device, Tegra::Engines::ShaderType shader_type, | ||
| 69 | u64 unique_identifier, const VideoCommon::Shader::ShaderIR& ir, | ||
| 70 | const VideoCommon::Shader::Registry& registry, | ||
| 71 | bool hint_retrievable = false); | ||
| 72 | |||
| 64 | class Shader final { | 73 | class Shader final { |
| 65 | public: | 74 | public: |
| 66 | ~Shader(); | 75 | ~Shader(); |
| @@ -68,15 +77,28 @@ public: | |||
| 68 | /// Gets the GL program handle for the shader | 77 | /// Gets the GL program handle for the shader |
| 69 | GLuint GetHandle() const; | 78 | GLuint GetHandle() const; |
| 70 | 79 | ||
| 80 | bool IsBuilt() const; | ||
| 81 | |||
| 71 | /// Gets the shader entries for the shader | 82 | /// Gets the shader entries for the shader |
| 72 | const ShaderEntries& GetEntries() const { | 83 | const ShaderEntries& GetEntries() const { |
| 73 | return entries; | 84 | return entries; |
| 74 | } | 85 | } |
| 75 | 86 | ||
| 76 | static std::unique_ptr<Shader> CreateStageFromMemory(const ShaderParameters& params, | 87 | const VideoCommon::Shader::Registry& GetRegistry() const { |
| 77 | Maxwell::ShaderProgram program_type, | 88 | return *registry; |
| 78 | ProgramCode program_code, | 89 | } |
| 79 | ProgramCode program_code_b); | 90 | |
| 91 | /// Mark a OpenGL shader as built | ||
| 92 | void AsyncOpenGLBuilt(OGLProgram new_program); | ||
| 93 | |||
| 94 | /// Mark a GLASM shader as built | ||
| 95 | void AsyncGLASMBuilt(OGLAssemblyProgram new_program); | ||
| 96 | |||
| 97 | static std::unique_ptr<Shader> CreateStageFromMemory( | ||
| 98 | const ShaderParameters& params, Maxwell::ShaderProgram program_type, | ||
| 99 | ProgramCode program_code, ProgramCode program_code_b, | ||
| 100 | VideoCommon::Shader::AsyncShaders& async_shaders, VAddr cpu_addr); | ||
| 101 | |||
| 80 | static std::unique_ptr<Shader> CreateKernelFromMemory(const ShaderParameters& params, | 102 | static std::unique_ptr<Shader> CreateKernelFromMemory(const ShaderParameters& params, |
| 81 | ProgramCode code); | 103 | ProgramCode code); |
| 82 | 104 | ||
| @@ -85,12 +107,13 @@ public: | |||
| 85 | 107 | ||
| 86 | private: | 108 | private: |
| 87 | explicit Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry, ShaderEntries entries, | 109 | explicit Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry, ShaderEntries entries, |
| 88 | ProgramSharedPtr program); | 110 | ProgramSharedPtr program, bool is_built = true); |
| 89 | 111 | ||
| 90 | std::shared_ptr<VideoCommon::Shader::Registry> registry; | 112 | std::shared_ptr<VideoCommon::Shader::Registry> registry; |
| 91 | ShaderEntries entries; | 113 | ShaderEntries entries; |
| 92 | ProgramSharedPtr program; | 114 | ProgramSharedPtr program; |
| 93 | GLuint handle = 0; | 115 | GLuint handle = 0; |
| 116 | bool is_built{}; | ||
| 94 | }; | 117 | }; |
| 95 | 118 | ||
| 96 | class ShaderCacheOpenGL final : public VideoCommon::ShaderCache<Shader> { | 119 | class ShaderCacheOpenGL final : public VideoCommon::ShaderCache<Shader> { |
| @@ -104,7 +127,8 @@ public: | |||
| 104 | const VideoCore::DiskResourceLoadCallback& callback); | 127 | const VideoCore::DiskResourceLoadCallback& callback); |
| 105 | 128 | ||
| 106 | /// Gets the current specified shader stage program | 129 | /// Gets the current specified shader stage program |
| 107 | Shader* GetStageProgram(Maxwell::ShaderProgram program); | 130 | Shader* GetStageProgram(Maxwell::ShaderProgram program, |
| 131 | VideoCommon::Shader::AsyncShaders& async_shaders); | ||
| 108 | 132 | ||
| 109 | /// Gets a compute kernel in the passed address | 133 | /// Gets a compute kernel in the passed address |
| 110 | Shader* GetComputeKernel(GPUVAddr code_addr); | 134 | Shader* GetComputeKernel(GPUVAddr code_addr); |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 8e754fa90..691c6c79b 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp | |||
| @@ -11,8 +11,30 @@ | |||
| 11 | 11 | ||
| 12 | namespace OpenGL { | 12 | namespace OpenGL { |
| 13 | 13 | ||
| 14 | ProgramManager::ProgramManager(const Device& device) { | 14 | namespace { |
| 15 | use_assembly_programs = device.UseAssemblyShaders(); | 15 | |
| 16 | void BindProgram(GLenum stage, GLuint current, GLuint old, bool& enabled) { | ||
| 17 | if (current == old) { | ||
| 18 | return; | ||
| 19 | } | ||
| 20 | if (current == 0) { | ||
| 21 | if (enabled) { | ||
| 22 | enabled = false; | ||
| 23 | glDisable(stage); | ||
| 24 | } | ||
| 25 | return; | ||
| 26 | } | ||
| 27 | if (!enabled) { | ||
| 28 | enabled = true; | ||
| 29 | glEnable(stage); | ||
| 30 | } | ||
| 31 | glBindProgramARB(stage, current); | ||
| 32 | } | ||
| 33 | |||
| 34 | } // Anonymous namespace | ||
| 35 | |||
| 36 | ProgramManager::ProgramManager(const Device& device) | ||
| 37 | : use_assembly_programs{device.UseAssemblyShaders()} { | ||
| 16 | if (use_assembly_programs) { | 38 | if (use_assembly_programs) { |
| 17 | glEnable(GL_COMPUTE_PROGRAM_NV); | 39 | glEnable(GL_COMPUTE_PROGRAM_NV); |
| 18 | } else { | 40 | } else { |
| @@ -33,9 +55,7 @@ void ProgramManager::BindCompute(GLuint program) { | |||
| 33 | } | 55 | } |
| 34 | 56 | ||
| 35 | void ProgramManager::BindGraphicsPipeline() { | 57 | void ProgramManager::BindGraphicsPipeline() { |
| 36 | if (use_assembly_programs) { | 58 | if (!use_assembly_programs) { |
| 37 | UpdateAssemblyPrograms(); | ||
| 38 | } else { | ||
| 39 | UpdateSourcePrograms(); | 59 | UpdateSourcePrograms(); |
| 40 | } | 60 | } |
| 41 | } | 61 | } |
| @@ -63,32 +83,25 @@ void ProgramManager::RestoreGuestPipeline() { | |||
| 63 | } | 83 | } |
| 64 | } | 84 | } |
| 65 | 85 | ||
| 66 | void ProgramManager::UpdateAssemblyPrograms() { | 86 | void ProgramManager::UseVertexShader(GLuint program) { |
| 67 | const auto update_state = [](GLenum stage, bool& enabled, GLuint current, GLuint old) { | 87 | if (use_assembly_programs) { |
| 68 | if (current == old) { | 88 | BindProgram(GL_VERTEX_PROGRAM_NV, program, current_state.vertex, vertex_enabled); |
| 69 | return; | 89 | } |
| 70 | } | 90 | current_state.vertex = program; |
| 71 | if (current == 0) { | 91 | } |
| 72 | if (enabled) { | ||
| 73 | enabled = false; | ||
| 74 | glDisable(stage); | ||
| 75 | } | ||
| 76 | return; | ||
| 77 | } | ||
| 78 | if (!enabled) { | ||
| 79 | enabled = true; | ||
| 80 | glEnable(stage); | ||
| 81 | } | ||
| 82 | glBindProgramARB(stage, current); | ||
| 83 | }; | ||
| 84 | 92 | ||
| 85 | update_state(GL_VERTEX_PROGRAM_NV, vertex_enabled, current_state.vertex, old_state.vertex); | 93 | void ProgramManager::UseGeometryShader(GLuint program) { |
| 86 | update_state(GL_GEOMETRY_PROGRAM_NV, geometry_enabled, current_state.geometry, | 94 | if (use_assembly_programs) { |
| 87 | old_state.geometry); | 95 | BindProgram(GL_GEOMETRY_PROGRAM_NV, program, current_state.vertex, geometry_enabled); |
| 88 | update_state(GL_FRAGMENT_PROGRAM_NV, fragment_enabled, current_state.fragment, | 96 | } |
| 89 | old_state.fragment); | 97 | current_state.geometry = program; |
| 98 | } | ||
| 90 | 99 | ||
| 91 | old_state = current_state; | 100 | void ProgramManager::UseFragmentShader(GLuint program) { |
| 101 | if (use_assembly_programs) { | ||
| 102 | BindProgram(GL_FRAGMENT_PROGRAM_NV, program, current_state.vertex, fragment_enabled); | ||
| 103 | } | ||
| 104 | current_state.fragment = program; | ||
| 92 | } | 105 | } |
| 93 | 106 | ||
| 94 | void ProgramManager::UpdateSourcePrograms() { | 107 | void ProgramManager::UpdateSourcePrograms() { |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 0f03b4f12..950e0dfcb 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h | |||
| @@ -45,17 +45,9 @@ public: | |||
| 45 | /// Rewinds BindHostPipeline state changes. | 45 | /// Rewinds BindHostPipeline state changes. |
| 46 | void RestoreGuestPipeline(); | 46 | void RestoreGuestPipeline(); |
| 47 | 47 | ||
| 48 | void UseVertexShader(GLuint program) { | 48 | void UseVertexShader(GLuint program); |
| 49 | current_state.vertex = program; | 49 | void UseGeometryShader(GLuint program); |
| 50 | } | 50 | void UseFragmentShader(GLuint program); |
| 51 | |||
| 52 | void UseGeometryShader(GLuint program) { | ||
| 53 | current_state.geometry = program; | ||
| 54 | } | ||
| 55 | |||
| 56 | void UseFragmentShader(GLuint program) { | ||
| 57 | current_state.fragment = program; | ||
| 58 | } | ||
| 59 | 51 | ||
| 60 | private: | 52 | private: |
| 61 | struct PipelineState { | 53 | struct PipelineState { |
| @@ -64,9 +56,6 @@ private: | |||
| 64 | GLuint fragment = 0; | 56 | GLuint fragment = 0; |
| 65 | }; | 57 | }; |
| 66 | 58 | ||
| 67 | /// Update NV_gpu_program5 programs. | ||
| 68 | void UpdateAssemblyPrograms(); | ||
| 69 | |||
| 70 | /// Update GLSL programs. | 59 | /// Update GLSL programs. |
| 71 | void UpdateSourcePrograms(); | 60 | void UpdateSourcePrograms(); |
| 72 | 61 | ||
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp index 3655ff629..887995cf4 100644 --- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp +++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp | |||
| @@ -35,7 +35,7 @@ OGLStreamBuffer::OGLStreamBuffer(const Device& device, GLsizeiptr size, bool ver | |||
| 35 | mapped_ptr = static_cast<u8*>( | 35 | mapped_ptr = static_cast<u8*>( |
| 36 | glMapNamedBufferRange(gl_buffer.handle, 0, buffer_size, flags | GL_MAP_FLUSH_EXPLICIT_BIT)); | 36 | glMapNamedBufferRange(gl_buffer.handle, 0, buffer_size, flags | GL_MAP_FLUSH_EXPLICIT_BIT)); |
| 37 | 37 | ||
| 38 | if (device.HasVertexBufferUnifiedMemory()) { | 38 | if (device.UseAssemblyShaders() || device.HasVertexBufferUnifiedMemory()) { |
| 39 | glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_ONLY); | 39 | glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_ONLY); |
| 40 | glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); | 40 | glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); |
| 41 | } | 41 | } |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 61505879b..0a7bc9e2b 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -41,91 +41,103 @@ struct FormatTuple { | |||
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex_format_tuples = {{ | 43 | constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex_format_tuples = {{ |
| 44 | {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, // ABGR8U | 44 | {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, // A8B8G8R8_UNORM |
| 45 | {GL_RGBA8_SNORM, GL_RGBA, GL_BYTE}, // ABGR8S | 45 | {GL_RGBA8_SNORM, GL_RGBA, GL_BYTE}, // A8B8G8R8_SNORM |
| 46 | {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}, // ABGR8UI | 46 | {GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE}, // A8B8G8R8_SINT |
| 47 | {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV}, // B5G6R5U | 47 | {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}, // A8B8G8R8_UINT |
| 48 | {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, // A2B10G10R10U | 48 | {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, // R5G6B5_UNORM |
| 49 | {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, // A1B5G5R5U | 49 | {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV}, // B5G6R5_UNORM |
| 50 | {GL_R8, GL_RED, GL_UNSIGNED_BYTE}, // R8U | 50 | {GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, // A1R5G5B5_UNORM |
| 51 | {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE}, // R8UI | 51 | {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, // A2B10G10R10_UNORM |
| 52 | {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT}, // RGBA16F | 52 | {GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV}, // A2B10G10R10_UINT |
| 53 | {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT}, // RGBA16U | 53 | {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, // A1B5G5R5_UNORM |
| 54 | {GL_RGBA16_SNORM, GL_RGBA, GL_SHORT}, // RGBA16S | 54 | {GL_R8, GL_RED, GL_UNSIGNED_BYTE}, // R8_UNORM |
| 55 | {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}, // RGBA16UI | 55 | {GL_R8_SNORM, GL_RED, GL_BYTE}, // R8_SNORM |
| 56 | {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV}, // R11FG11FB10F | 56 | {GL_R8I, GL_RED_INTEGER, GL_BYTE}, // R8_SINT |
| 57 | {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, // RGBA32UI | 57 | {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE}, // R8_UINT |
| 58 | {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT}, // DXT1 | 58 | {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT}, // R16G16B16A16_FLOAT |
| 59 | {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT}, // DXT23 | 59 | {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT}, // R16G16B16A16_UNORM |
| 60 | {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT}, // DXT45 | 60 | {GL_RGBA16_SNORM, GL_RGBA, GL_SHORT}, // R16G16B16A16_SNORM |
| 61 | {GL_COMPRESSED_RED_RGTC1}, // DXN1 | 61 | {GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT}, // R16G16B16A16_SINT |
| 62 | {GL_COMPRESSED_RG_RGTC2}, // DXN2UNORM | 62 | {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}, // R16G16B16A16_UINT |
| 63 | {GL_COMPRESSED_SIGNED_RG_RGTC2}, // DXN2SNORM | 63 | {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV}, // B10G11R11_FLOAT |
| 64 | {GL_COMPRESSED_RGBA_BPTC_UNORM}, // BC7U | 64 | {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, // R32G32B32A32_UINT |
| 65 | {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT}, // BC6H_UF16 | 65 | {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT}, // BC1_RGBA_UNORM |
| 66 | {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT}, // BC6H_SF16 | 66 | {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT}, // BC2_UNORM |
| 67 | {GL_COMPRESSED_RGBA_ASTC_4x4_KHR}, // ASTC_2D_4X4 | 67 | {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT}, // BC3_UNORM |
| 68 | {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE}, // BGRA8 | 68 | {GL_COMPRESSED_RED_RGTC1}, // BC4_UNORM |
| 69 | {GL_RGBA32F, GL_RGBA, GL_FLOAT}, // RGBA32F | 69 | {GL_COMPRESSED_SIGNED_RED_RGTC1}, // BC4_SNORM |
| 70 | {GL_RG32F, GL_RG, GL_FLOAT}, // RG32F | 70 | {GL_COMPRESSED_RG_RGTC2}, // BC5_UNORM |
| 71 | {GL_R32F, GL_RED, GL_FLOAT}, // R32F | 71 | {GL_COMPRESSED_SIGNED_RG_RGTC2}, // BC5_SNORM |
| 72 | {GL_R16F, GL_RED, GL_HALF_FLOAT}, // R16F | 72 | {GL_COMPRESSED_RGBA_BPTC_UNORM}, // BC7_UNORM |
| 73 | {GL_R16, GL_RED, GL_UNSIGNED_SHORT}, // R16U | 73 | {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT}, // BC6H_UFLOAT |
| 74 | {GL_R16_SNORM, GL_RED, GL_SHORT}, // R16S | 74 | {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT}, // BC6H_SFLOAT |
| 75 | {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT}, // R16UI | 75 | {GL_COMPRESSED_RGBA_ASTC_4x4_KHR}, // ASTC_2D_4X4_UNORM |
| 76 | {GL_R16I, GL_RED_INTEGER, GL_SHORT}, // R16I | 76 | {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE}, // B8G8R8A8_UNORM |
| 77 | {GL_RG16, GL_RG, GL_UNSIGNED_SHORT}, // RG16 | 77 | {GL_RGBA32F, GL_RGBA, GL_FLOAT}, // R32G32B32A32_FLOAT |
| 78 | {GL_RG16F, GL_RG, GL_HALF_FLOAT}, // RG16F | 78 | {GL_RGBA32I, GL_RGBA_INTEGER, GL_INT}, // R32G32B32A32_SINT |
| 79 | {GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT}, // RG16UI | 79 | {GL_RG32F, GL_RG, GL_FLOAT}, // R32G32_FLOAT |
| 80 | {GL_RG16I, GL_RG_INTEGER, GL_SHORT}, // RG16I | 80 | {GL_RG32I, GL_RG_INTEGER, GL_INT}, // R32G32_SINT |
| 81 | {GL_RG16_SNORM, GL_RG, GL_SHORT}, // RG16S | 81 | {GL_R32F, GL_RED, GL_FLOAT}, // R32_FLOAT |
| 82 | {GL_RGB32F, GL_RGB, GL_FLOAT}, // RGB32F | 82 | {GL_R16F, GL_RED, GL_HALF_FLOAT}, // R16_FLOAT |
| 83 | {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, // RGBA8_SRGB | 83 | {GL_R16, GL_RED, GL_UNSIGNED_SHORT}, // R16_UNORM |
| 84 | {GL_RG8, GL_RG, GL_UNSIGNED_BYTE}, // RG8U | 84 | {GL_R16_SNORM, GL_RED, GL_SHORT}, // R16_SNORM |
| 85 | {GL_RG8_SNORM, GL_RG, GL_BYTE}, // RG8S | 85 | {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT}, // R16_UINT |
| 86 | {GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, // RG8UI | 86 | {GL_R16I, GL_RED_INTEGER, GL_SHORT}, // R16_SINT |
| 87 | {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, // RG32UI | 87 | {GL_RG16, GL_RG, GL_UNSIGNED_SHORT}, // R16G16_UNORM |
| 88 | {GL_RGB16F, GL_RGBA, GL_HALF_FLOAT}, // RGBX16F | 88 | {GL_RG16F, GL_RG, GL_HALF_FLOAT}, // R16G16_FLOAT |
| 89 | {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, // R32UI | 89 | {GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT}, // R16G16_UINT |
| 90 | {GL_R32I, GL_RED_INTEGER, GL_INT}, // R32I | 90 | {GL_RG16I, GL_RG_INTEGER, GL_SHORT}, // R16G16_SINT |
| 91 | {GL_COMPRESSED_RGBA_ASTC_8x8_KHR}, // ASTC_2D_8X8 | 91 | {GL_RG16_SNORM, GL_RG, GL_SHORT}, // R16G16_SNORM |
| 92 | {GL_COMPRESSED_RGBA_ASTC_8x5_KHR}, // ASTC_2D_8X5 | 92 | {GL_RGB32F, GL_RGB, GL_FLOAT}, // R32G32B32_FLOAT |
| 93 | {GL_COMPRESSED_RGBA_ASTC_5x4_KHR}, // ASTC_2D_5X4 | 93 | {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, // A8B8G8R8_SRGB |
| 94 | {GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE}, // BGRA8 | 94 | {GL_RG8, GL_RG, GL_UNSIGNED_BYTE}, // R8G8_UNORM |
| 95 | {GL_RG8_SNORM, GL_RG, GL_BYTE}, // R8G8_SNORM | ||
| 96 | {GL_RG8I, GL_RG_INTEGER, GL_BYTE}, // R8G8_SINT | ||
| 97 | {GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE}, // R8G8_UINT | ||
| 98 | {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, // R32G32_UINT | ||
| 99 | {GL_RGB16F, GL_RGBA, GL_HALF_FLOAT}, // R16G16B16X16_FLOAT | ||
| 100 | {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, // R32_UINT | ||
| 101 | {GL_R32I, GL_RED_INTEGER, GL_INT}, // R32_SINT | ||
| 102 | {GL_COMPRESSED_RGBA_ASTC_8x8_KHR}, // ASTC_2D_8X8_UNORM | ||
| 103 | {GL_COMPRESSED_RGBA_ASTC_8x5_KHR}, // ASTC_2D_8X5_UNORM | ||
| 104 | {GL_COMPRESSED_RGBA_ASTC_5x4_KHR}, // ASTC_2D_5X4_UNORM | ||
| 105 | {GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE}, // B8G8R8A8_UNORM | ||
| 95 | // Compressed sRGB formats | 106 | // Compressed sRGB formats |
| 96 | {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT}, // DXT1_SRGB | 107 | {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT}, // BC1_RGBA_SRGB |
| 97 | {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT}, // DXT23_SRGB | 108 | {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT}, // BC2_SRGB |
| 98 | {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, // DXT45_SRGB | 109 | {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, // BC3_SRGB |
| 99 | {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM}, // BC7U_SRGB | 110 | {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM}, // BC7_SRGB |
| 100 | {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV}, // R4G4B4A4U | 111 | {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV}, // A4B4G4R4_UNORM |
| 101 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR}, // ASTC_2D_4X4_SRGB | 112 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR}, // ASTC_2D_4X4_SRGB |
| 102 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR}, // ASTC_2D_8X8_SRGB | 113 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR}, // ASTC_2D_8X8_SRGB |
| 103 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR}, // ASTC_2D_8X5_SRGB | 114 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR}, // ASTC_2D_8X5_SRGB |
| 104 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR}, // ASTC_2D_5X4_SRGB | 115 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR}, // ASTC_2D_5X4_SRGB |
| 105 | {GL_COMPRESSED_RGBA_ASTC_5x5_KHR}, // ASTC_2D_5X5 | 116 | {GL_COMPRESSED_RGBA_ASTC_5x5_KHR}, // ASTC_2D_5X5_UNORM |
| 106 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR}, // ASTC_2D_5X5_SRGB | 117 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR}, // ASTC_2D_5X5_SRGB |
| 107 | {GL_COMPRESSED_RGBA_ASTC_10x8_KHR}, // ASTC_2D_10X8 | 118 | {GL_COMPRESSED_RGBA_ASTC_10x8_KHR}, // ASTC_2D_10X8_UNORM |
| 108 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR}, // ASTC_2D_10X8_SRGB | 119 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR}, // ASTC_2D_10X8_SRGB |
| 109 | {GL_COMPRESSED_RGBA_ASTC_6x6_KHR}, // ASTC_2D_6X6 | 120 | {GL_COMPRESSED_RGBA_ASTC_6x6_KHR}, // ASTC_2D_6X6_UNORM |
| 110 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR}, // ASTC_2D_6X6_SRGB | 121 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR}, // ASTC_2D_6X6_SRGB |
| 111 | {GL_COMPRESSED_RGBA_ASTC_10x10_KHR}, // ASTC_2D_10X10 | 122 | {GL_COMPRESSED_RGBA_ASTC_10x10_KHR}, // ASTC_2D_10X10_UNORM |
| 112 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR}, // ASTC_2D_10X10_SRGB | 123 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR}, // ASTC_2D_10X10_SRGB |
| 113 | {GL_COMPRESSED_RGBA_ASTC_12x12_KHR}, // ASTC_2D_12X12 | 124 | {GL_COMPRESSED_RGBA_ASTC_12x12_KHR}, // ASTC_2D_12X12_UNORM |
| 114 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR}, // ASTC_2D_12X12_SRGB | 125 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR}, // ASTC_2D_12X12_SRGB |
| 115 | {GL_COMPRESSED_RGBA_ASTC_8x6_KHR}, // ASTC_2D_8X6 | 126 | {GL_COMPRESSED_RGBA_ASTC_8x6_KHR}, // ASTC_2D_8X6_UNORM |
| 116 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR}, // ASTC_2D_8X6_SRGB | 127 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR}, // ASTC_2D_8X6_SRGB |
| 117 | {GL_COMPRESSED_RGBA_ASTC_6x5_KHR}, // ASTC_2D_6X5 | 128 | {GL_COMPRESSED_RGBA_ASTC_6x5_KHR}, // ASTC_2D_6X5_UNORM |
| 118 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR}, // ASTC_2D_6X5_SRGB | 129 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR}, // ASTC_2D_6X5_SRGB |
| 119 | {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9F | 130 | {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9_FLOAT |
| 120 | 131 | ||
| 121 | // Depth formats | 132 | // Depth formats |
| 122 | {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // Z32F | 133 | {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // D32_FLOAT |
| 123 | {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // Z16 | 134 | {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16_UNORM |
| 124 | 135 | ||
| 125 | // DepthStencil formats | 136 | // DepthStencil formats |
| 126 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // Z24S8 | 137 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24_UNORM_S8_UINT |
| 127 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8Z24 | 138 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8_UINT_D24_UNORM |
| 128 | {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV}, // Z32FS8 | 139 | {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, |
| 140 | GL_FLOAT_32_UNSIGNED_INT_24_8_REV}, // D32_FLOAT_S8_UINT | ||
| 129 | }}; | 141 | }}; |
| 130 | 142 | ||
| 131 | const FormatTuple& GetFormatTuple(PixelFormat pixel_format) { | 143 | const FormatTuple& GetFormatTuple(PixelFormat pixel_format) { |
| @@ -178,10 +190,10 @@ GLint GetSwizzleSource(SwizzleSource source) { | |||
| 178 | 190 | ||
| 179 | GLenum GetComponent(PixelFormat format, bool is_first) { | 191 | GLenum GetComponent(PixelFormat format, bool is_first) { |
| 180 | switch (format) { | 192 | switch (format) { |
| 181 | case PixelFormat::Z24S8: | 193 | case PixelFormat::D24_UNORM_S8_UINT: |
| 182 | case PixelFormat::Z32FS8: | 194 | case PixelFormat::D32_FLOAT_S8_UINT: |
| 183 | return is_first ? GL_DEPTH_COMPONENT : GL_STENCIL_INDEX; | 195 | return is_first ? GL_DEPTH_COMPONENT : GL_STENCIL_INDEX; |
| 184 | case PixelFormat::S8Z24: | 196 | case PixelFormat::S8_UINT_D24_UNORM: |
| 185 | return is_first ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT; | 197 | return is_first ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT; |
| 186 | default: | 198 | default: |
| 187 | UNREACHABLE(); | 199 | UNREACHABLE(); |
| @@ -482,9 +494,9 @@ GLuint CachedSurfaceView::GetTexture(SwizzleSource x_source, SwizzleSource y_sou | |||
| 482 | std::array swizzle{x_source, y_source, z_source, w_source}; | 494 | std::array swizzle{x_source, y_source, z_source, w_source}; |
| 483 | 495 | ||
| 484 | switch (const PixelFormat format = GetSurfaceParams().pixel_format) { | 496 | switch (const PixelFormat format = GetSurfaceParams().pixel_format) { |
| 485 | case PixelFormat::Z24S8: | 497 | case PixelFormat::D24_UNORM_S8_UINT: |
| 486 | case PixelFormat::Z32FS8: | 498 | case PixelFormat::D32_FLOAT_S8_UINT: |
| 487 | case PixelFormat::S8Z24: | 499 | case PixelFormat::S8_UINT_D24_UNORM: |
| 488 | UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G); | 500 | UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G); |
| 489 | glTextureParameteri(view.handle, GL_DEPTH_STENCIL_TEXTURE_MODE, | 501 | glTextureParameteri(view.handle, GL_DEPTH_STENCIL_TEXTURE_MODE, |
| 490 | GetComponent(format, x_source == SwizzleSource::R)); | 502 | GetComponent(format, x_source == SwizzleSource::R)); |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index e66cdc083..52e9e8250 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -535,12 +535,12 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, | |||
| 535 | 535 | ||
| 536 | GLint internal_format; | 536 | GLint internal_format; |
| 537 | switch (framebuffer.pixel_format) { | 537 | switch (framebuffer.pixel_format) { |
| 538 | case Tegra::FramebufferConfig::PixelFormat::ABGR8: | 538 | case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM: |
| 539 | internal_format = GL_RGBA8; | 539 | internal_format = GL_RGBA8; |
| 540 | texture.gl_format = GL_RGBA; | 540 | texture.gl_format = GL_RGBA; |
| 541 | texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; | 541 | texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; |
| 542 | break; | 542 | break; |
| 543 | case Tegra::FramebufferConfig::PixelFormat::RGB565: | 543 | case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM: |
| 544 | internal_format = GL_RGB565; | 544 | internal_format = GL_RGB565; |
| 545 | texture.gl_format = GL_RGB; | 545 | texture.gl_format = GL_RGB; |
| 546 | texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; | 546 | texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; |
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index d7f1ae89f..f8c77f4fa 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -117,90 +117,101 @@ struct FormatTuple { | |||
| 117 | VkFormat format; ///< Vulkan format | 117 | VkFormat format; ///< Vulkan format |
| 118 | int usage = 0; ///< Describes image format usage | 118 | int usage = 0; ///< Describes image format usage |
| 119 | } constexpr tex_format_tuples[] = { | 119 | } constexpr tex_format_tuples[] = { |
| 120 | {VK_FORMAT_A8B8G8R8_UNORM_PACK32, Attachable | Storage}, // ABGR8U | 120 | {VK_FORMAT_A8B8G8R8_UNORM_PACK32, Attachable | Storage}, // A8B8G8R8_UNORM |
| 121 | {VK_FORMAT_A8B8G8R8_SNORM_PACK32, Attachable | Storage}, // ABGR8S | 121 | {VK_FORMAT_A8B8G8R8_SNORM_PACK32, Attachable | Storage}, // A8B8G8R8_SNORM |
| 122 | {VK_FORMAT_A8B8G8R8_UINT_PACK32, Attachable | Storage}, // ABGR8UI | 122 | {VK_FORMAT_A8B8G8R8_SINT_PACK32, Attachable | Storage}, // A8B8G8R8_SINT |
| 123 | {VK_FORMAT_B5G6R5_UNORM_PACK16}, // B5G6R5U | 123 | {VK_FORMAT_A8B8G8R8_UINT_PACK32, Attachable | Storage}, // A8B8G8R8_UINT |
| 124 | {VK_FORMAT_A2B10G10R10_UNORM_PACK32, Attachable | Storage}, // A2B10G10R10U | 124 | {VK_FORMAT_R5G6B5_UNORM_PACK16, Attachable}, // R5G6B5_UNORM |
| 125 | {VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1B5G5R5U (flipped with swizzle) | 125 | {VK_FORMAT_B5G6R5_UNORM_PACK16, Attachable}, // B5G6R5_UNORM |
| 126 | {VK_FORMAT_R8_UNORM, Attachable | Storage}, // R8U | 126 | {VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1R5G5B5_UNORM |
| 127 | {VK_FORMAT_R8_UINT, Attachable | Storage}, // R8UI | 127 | {VK_FORMAT_A2B10G10R10_UNORM_PACK32, Attachable | Storage}, // A2B10G10R10_UNORM |
| 128 | {VK_FORMAT_R16G16B16A16_SFLOAT, Attachable | Storage}, // RGBA16F | 128 | {VK_FORMAT_A2B10G10R10_UINT_PACK32, Attachable | Storage}, // A2B10G10R10_UINT |
| 129 | {VK_FORMAT_R16G16B16A16_UNORM, Attachable | Storage}, // RGBA16U | 129 | {VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1B5G5R5_UNORM (flipped with swizzle) |
| 130 | {VK_FORMAT_R16G16B16A16_SNORM, Attachable | Storage}, // RGBA16S | 130 | {VK_FORMAT_R8_UNORM, Attachable | Storage}, // R8_UNORM |
| 131 | {VK_FORMAT_R16G16B16A16_UINT, Attachable | Storage}, // RGBA16UI | 131 | {VK_FORMAT_R8_SNORM, Attachable | Storage}, // R8_SNORM |
| 132 | {VK_FORMAT_B10G11R11_UFLOAT_PACK32, Attachable | Storage}, // R11FG11FB10F | 132 | {VK_FORMAT_R8_SINT, Attachable | Storage}, // R8_SINT |
| 133 | {VK_FORMAT_R32G32B32A32_UINT, Attachable | Storage}, // RGBA32UI | 133 | {VK_FORMAT_R8_UINT, Attachable | Storage}, // R8_UINT |
| 134 | {VK_FORMAT_BC1_RGBA_UNORM_BLOCK}, // DXT1 | 134 | {VK_FORMAT_R16G16B16A16_SFLOAT, Attachable | Storage}, // R16G16B16A16_FLOAT |
| 135 | {VK_FORMAT_BC2_UNORM_BLOCK}, // DXT23 | 135 | {VK_FORMAT_R16G16B16A16_UNORM, Attachable | Storage}, // R16G16B16A16_UNORM |
| 136 | {VK_FORMAT_BC3_UNORM_BLOCK}, // DXT45 | 136 | {VK_FORMAT_R16G16B16A16_SNORM, Attachable | Storage}, // R16G16B16A16_SNORM |
| 137 | {VK_FORMAT_BC4_UNORM_BLOCK}, // DXN1 | 137 | {VK_FORMAT_R16G16B16A16_SINT, Attachable | Storage}, // R16G16B16A16_SINT |
| 138 | {VK_FORMAT_BC5_UNORM_BLOCK}, // DXN2UNORM | 138 | {VK_FORMAT_R16G16B16A16_UINT, Attachable | Storage}, // R16G16B16A16_UINT |
| 139 | {VK_FORMAT_BC5_SNORM_BLOCK}, // DXN2SNORM | 139 | {VK_FORMAT_B10G11R11_UFLOAT_PACK32, Attachable | Storage}, // B10G11R11_FLOAT |
| 140 | {VK_FORMAT_BC7_UNORM_BLOCK}, // BC7U | 140 | {VK_FORMAT_R32G32B32A32_UINT, Attachable | Storage}, // R32G32B32A32_UINT |
| 141 | {VK_FORMAT_BC6H_UFLOAT_BLOCK}, // BC6H_UF16 | 141 | {VK_FORMAT_BC1_RGBA_UNORM_BLOCK}, // BC1_RGBA_UNORM |
| 142 | {VK_FORMAT_BC6H_SFLOAT_BLOCK}, // BC6H_SF16 | 142 | {VK_FORMAT_BC2_UNORM_BLOCK}, // BC2_UNORM |
| 143 | {VK_FORMAT_ASTC_4x4_UNORM_BLOCK}, // ASTC_2D_4X4 | 143 | {VK_FORMAT_BC3_UNORM_BLOCK}, // BC3_UNORM |
| 144 | {VK_FORMAT_B8G8R8A8_UNORM, Attachable}, // BGRA8 | 144 | {VK_FORMAT_BC4_UNORM_BLOCK}, // BC4_UNORM |
| 145 | {VK_FORMAT_R32G32B32A32_SFLOAT, Attachable | Storage}, // RGBA32F | 145 | {VK_FORMAT_BC4_SNORM_BLOCK}, // BC4_SNORM |
| 146 | {VK_FORMAT_R32G32_SFLOAT, Attachable | Storage}, // RG32F | 146 | {VK_FORMAT_BC5_UNORM_BLOCK}, // BC5_UNORM |
| 147 | {VK_FORMAT_R32_SFLOAT, Attachable | Storage}, // R32F | 147 | {VK_FORMAT_BC5_SNORM_BLOCK}, // BC5_SNORM |
| 148 | {VK_FORMAT_R16_SFLOAT, Attachable | Storage}, // R16F | 148 | {VK_FORMAT_BC7_UNORM_BLOCK}, // BC7_UNORM |
| 149 | {VK_FORMAT_R16_UNORM, Attachable | Storage}, // R16U | 149 | {VK_FORMAT_BC6H_UFLOAT_BLOCK}, // BC6H_UFLOAT |
| 150 | {VK_FORMAT_UNDEFINED}, // R16S | 150 | {VK_FORMAT_BC6H_SFLOAT_BLOCK}, // BC6H_SFLOAT |
| 151 | {VK_FORMAT_R16_UINT, Attachable | Storage}, // R16UI | 151 | {VK_FORMAT_ASTC_4x4_UNORM_BLOCK}, // ASTC_2D_4X4_UNORM |
| 152 | {VK_FORMAT_UNDEFINED}, // R16I | 152 | {VK_FORMAT_B8G8R8A8_UNORM, Attachable}, // B8G8R8A8_UNORM |
| 153 | {VK_FORMAT_R16G16_UNORM, Attachable | Storage}, // RG16 | 153 | {VK_FORMAT_R32G32B32A32_SFLOAT, Attachable | Storage}, // R32G32B32A32_FLOAT |
| 154 | {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage}, // RG16F | 154 | {VK_FORMAT_R32G32B32A32_SINT, Attachable | Storage}, // R32G32B32A32_SINT |
| 155 | {VK_FORMAT_UNDEFINED}, // RG16UI | 155 | {VK_FORMAT_R32G32_SFLOAT, Attachable | Storage}, // R32G32_FLOAT |
| 156 | {VK_FORMAT_UNDEFINED}, // RG16I | 156 | {VK_FORMAT_R32G32_SINT, Attachable | Storage}, // R32G32_SINT |
| 157 | {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // RG16S | 157 | {VK_FORMAT_R32_SFLOAT, Attachable | Storage}, // R32_FLOAT |
| 158 | {VK_FORMAT_UNDEFINED}, // RGB32F | 158 | {VK_FORMAT_R16_SFLOAT, Attachable | Storage}, // R16_FLOAT |
| 159 | {VK_FORMAT_R8G8B8A8_SRGB, Attachable}, // RGBA8_SRGB | 159 | {VK_FORMAT_R16_UNORM, Attachable | Storage}, // R16_UNORM |
| 160 | {VK_FORMAT_R8G8_UNORM, Attachable | Storage}, // RG8U | 160 | {VK_FORMAT_UNDEFINED}, // R16_SNORM |
| 161 | {VK_FORMAT_R8G8_SNORM, Attachable | Storage}, // RG8S | 161 | {VK_FORMAT_R16_UINT, Attachable | Storage}, // R16_UINT |
| 162 | {VK_FORMAT_R8G8_UINT, Attachable | Storage}, // RG8UI | 162 | {VK_FORMAT_UNDEFINED}, // R16_SINT |
| 163 | {VK_FORMAT_R32G32_UINT, Attachable | Storage}, // RG32UI | 163 | {VK_FORMAT_R16G16_UNORM, Attachable | Storage}, // R16G16_UNORM |
| 164 | {VK_FORMAT_UNDEFINED}, // RGBX16F | 164 | {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage}, // R16G16_FLOAT |
| 165 | {VK_FORMAT_R32_UINT, Attachable | Storage}, // R32UI | 165 | {VK_FORMAT_UNDEFINED}, // R16G16_UINT |
| 166 | {VK_FORMAT_R32_SINT, Attachable | Storage}, // R32I | 166 | {VK_FORMAT_UNDEFINED}, // R16G16_SINT |
| 167 | {VK_FORMAT_ASTC_8x8_UNORM_BLOCK}, // ASTC_2D_8X8 | 167 | {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // R16G16_SNORM |
| 168 | {VK_FORMAT_UNDEFINED}, // ASTC_2D_8X5 | 168 | {VK_FORMAT_UNDEFINED}, // R32G32B32_FLOAT |
| 169 | {VK_FORMAT_UNDEFINED}, // ASTC_2D_5X4 | 169 | {VK_FORMAT_R8G8B8A8_SRGB, Attachable}, // A8B8G8R8_SRGB |
| 170 | {VK_FORMAT_B8G8R8A8_SRGB, Attachable}, // BGRA8_SRGB | 170 | {VK_FORMAT_R8G8_UNORM, Attachable | Storage}, // R8G8_UNORM |
| 171 | {VK_FORMAT_BC1_RGBA_SRGB_BLOCK}, // DXT1_SRGB | 171 | {VK_FORMAT_R8G8_SNORM, Attachable | Storage}, // R8G8_SNORM |
| 172 | {VK_FORMAT_BC2_SRGB_BLOCK}, // DXT23_SRGB | 172 | {VK_FORMAT_R8G8_SINT, Attachable | Storage}, // R8G8_SINT |
| 173 | {VK_FORMAT_BC3_SRGB_BLOCK}, // DXT45_SRGB | 173 | {VK_FORMAT_R8G8_UINT, Attachable | Storage}, // R8G8_UINT |
| 174 | {VK_FORMAT_BC7_SRGB_BLOCK}, // BC7U_SRGB | 174 | {VK_FORMAT_R32G32_UINT, Attachable | Storage}, // R32G32_UINT |
| 175 | {VK_FORMAT_R4G4B4A4_UNORM_PACK16, Attachable}, // R4G4B4A4U | 175 | {VK_FORMAT_UNDEFINED}, // R16G16B16X16_FLOAT |
| 176 | {VK_FORMAT_ASTC_4x4_SRGB_BLOCK}, // ASTC_2D_4X4_SRGB | 176 | {VK_FORMAT_R32_UINT, Attachable | Storage}, // R32_UINT |
| 177 | {VK_FORMAT_ASTC_8x8_SRGB_BLOCK}, // ASTC_2D_8X8_SRGB | 177 | {VK_FORMAT_R32_SINT, Attachable | Storage}, // R32_SINT |
| 178 | {VK_FORMAT_ASTC_8x5_SRGB_BLOCK}, // ASTC_2D_8X5_SRGB | 178 | {VK_FORMAT_ASTC_8x8_UNORM_BLOCK}, // ASTC_2D_8X8_UNORM |
| 179 | {VK_FORMAT_ASTC_5x4_SRGB_BLOCK}, // ASTC_2D_5X4_SRGB | 179 | {VK_FORMAT_UNDEFINED}, // ASTC_2D_8X5_UNORM |
| 180 | {VK_FORMAT_ASTC_5x5_UNORM_BLOCK}, // ASTC_2D_5X5 | 180 | {VK_FORMAT_UNDEFINED}, // ASTC_2D_5X4_UNORM |
| 181 | {VK_FORMAT_ASTC_5x5_SRGB_BLOCK}, // ASTC_2D_5X5_SRGB | 181 | {VK_FORMAT_B8G8R8A8_SRGB, Attachable}, // B8G8R8A8_SRGB |
| 182 | {VK_FORMAT_ASTC_10x8_UNORM_BLOCK}, // ASTC_2D_10X8 | 182 | {VK_FORMAT_BC1_RGBA_SRGB_BLOCK}, // BC1_RGBA_SRGB |
| 183 | {VK_FORMAT_ASTC_10x8_SRGB_BLOCK}, // ASTC_2D_10X8_SRGB | 183 | {VK_FORMAT_BC2_SRGB_BLOCK}, // BC2_SRGB |
| 184 | {VK_FORMAT_ASTC_6x6_UNORM_BLOCK}, // ASTC_2D_6X6 | 184 | {VK_FORMAT_BC3_SRGB_BLOCK}, // BC3_SRGB |
| 185 | {VK_FORMAT_ASTC_6x6_SRGB_BLOCK}, // ASTC_2D_6X6_SRGB | 185 | {VK_FORMAT_BC7_SRGB_BLOCK}, // BC7_SRGB |
| 186 | {VK_FORMAT_ASTC_10x10_UNORM_BLOCK}, // ASTC_2D_10X10 | 186 | {VK_FORMAT_R4G4B4A4_UNORM_PACK16, Attachable}, // A4B4G4R4_UNORM |
| 187 | {VK_FORMAT_ASTC_10x10_SRGB_BLOCK}, // ASTC_2D_10X10_SRGB | 187 | {VK_FORMAT_ASTC_4x4_SRGB_BLOCK}, // ASTC_2D_4X4_SRGB |
| 188 | {VK_FORMAT_ASTC_12x12_UNORM_BLOCK}, // ASTC_2D_12X12 | 188 | {VK_FORMAT_ASTC_8x8_SRGB_BLOCK}, // ASTC_2D_8X8_SRGB |
| 189 | {VK_FORMAT_ASTC_12x12_SRGB_BLOCK}, // ASTC_2D_12X12_SRGB | 189 | {VK_FORMAT_ASTC_8x5_SRGB_BLOCK}, // ASTC_2D_8X5_SRGB |
| 190 | {VK_FORMAT_ASTC_8x6_UNORM_BLOCK}, // ASTC_2D_8X6 | 190 | {VK_FORMAT_ASTC_5x4_SRGB_BLOCK}, // ASTC_2D_5X4_SRGB |
| 191 | {VK_FORMAT_ASTC_8x6_SRGB_BLOCK}, // ASTC_2D_8X6_SRGB | 191 | {VK_FORMAT_ASTC_5x5_UNORM_BLOCK}, // ASTC_2D_5X5_UNORM |
| 192 | {VK_FORMAT_ASTC_6x5_UNORM_BLOCK}, // ASTC_2D_6X5 | 192 | {VK_FORMAT_ASTC_5x5_SRGB_BLOCK}, // ASTC_2D_5X5_SRGB |
| 193 | {VK_FORMAT_ASTC_6x5_SRGB_BLOCK}, // ASTC_2D_6X5_SRGB | 193 | {VK_FORMAT_ASTC_10x8_UNORM_BLOCK}, // ASTC_2D_10X8_UNORM |
| 194 | {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32}, // E5B9G9R9F | 194 | {VK_FORMAT_ASTC_10x8_SRGB_BLOCK}, // ASTC_2D_10X8_SRGB |
| 195 | {VK_FORMAT_ASTC_6x6_UNORM_BLOCK}, // ASTC_2D_6X6_UNORM | ||
| 196 | {VK_FORMAT_ASTC_6x6_SRGB_BLOCK}, // ASTC_2D_6X6_SRGB | ||
| 197 | {VK_FORMAT_ASTC_10x10_UNORM_BLOCK}, // ASTC_2D_10X10_UNORM | ||
| 198 | {VK_FORMAT_ASTC_10x10_SRGB_BLOCK}, // ASTC_2D_10X10_SRGB | ||
| 199 | {VK_FORMAT_ASTC_12x12_UNORM_BLOCK}, // ASTC_2D_12X12_UNORM | ||
| 200 | {VK_FORMAT_ASTC_12x12_SRGB_BLOCK}, // ASTC_2D_12X12_SRGB | ||
| 201 | {VK_FORMAT_ASTC_8x6_UNORM_BLOCK}, // ASTC_2D_8X6_UNORM | ||
| 202 | {VK_FORMAT_ASTC_8x6_SRGB_BLOCK}, // ASTC_2D_8X6_SRGB | ||
| 203 | {VK_FORMAT_ASTC_6x5_UNORM_BLOCK}, // ASTC_2D_6X5_UNORM | ||
| 204 | {VK_FORMAT_ASTC_6x5_SRGB_BLOCK}, // ASTC_2D_6X5_SRGB | ||
| 205 | {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32}, // E5B9G9R9_FLOAT | ||
| 195 | 206 | ||
| 196 | // Depth formats | 207 | // Depth formats |
| 197 | {VK_FORMAT_D32_SFLOAT, Attachable}, // Z32F | 208 | {VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT |
| 198 | {VK_FORMAT_D16_UNORM, Attachable}, // Z16 | 209 | {VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM |
| 199 | 210 | ||
| 200 | // DepthStencil formats | 211 | // DepthStencil formats |
| 201 | {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // Z24S8 | 212 | {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // D24_UNORM_S8_UINT |
| 202 | {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // S8Z24 (emulated) | 213 | {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // S8_UINT_D24_UNORM (emulated) |
| 203 | {VK_FORMAT_D32_SFLOAT_S8_UINT, Attachable}, // Z32FS8 | 214 | {VK_FORMAT_D32_SFLOAT_S8_UINT, Attachable}, // D32_FLOAT_S8_UINT |
| 204 | }; | 215 | }; |
| 205 | static_assert(std::size(tex_format_tuples) == VideoCore::Surface::MaxPixelFormat); | 216 | static_assert(std::size(tex_format_tuples) == VideoCore::Surface::MaxPixelFormat); |
| 206 | 217 | ||
| @@ -221,7 +232,7 @@ FormatInfo SurfaceFormat(const VKDevice& device, FormatType format_type, PixelFo | |||
| 221 | return {VK_FORMAT_A8B8G8R8_UNORM_PACK32, true, true}; | 232 | return {VK_FORMAT_A8B8G8R8_UNORM_PACK32, true, true}; |
| 222 | } | 233 | } |
| 223 | 234 | ||
| 224 | // Use ABGR8 on hardware that doesn't support ASTC natively | 235 | // Use A8B8G8R8_UNORM on hardware that doesn't support ASTC natively |
| 225 | if (!device.IsOptimalAstcSupported() && VideoCore::Surface::IsPixelFormatASTC(pixel_format)) { | 236 | if (!device.IsOptimalAstcSupported() && VideoCore::Surface::IsPixelFormatASTC(pixel_format)) { |
| 226 | tuple.format = VideoCore::Surface::IsPixelFormatSRGB(pixel_format) | 237 | tuple.format = VideoCore::Surface::IsPixelFormatSRGB(pixel_format) |
| 227 | ? VK_FORMAT_A8B8G8R8_SRGB_PACK32 | 238 | ? VK_FORMAT_A8B8G8R8_SRGB_PACK32 |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 866813465..ce53e5a6b 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -187,9 +187,9 @@ std::size_t GetSizeInBytes(const Tegra::FramebufferConfig& framebuffer) { | |||
| 187 | 187 | ||
| 188 | VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { | 188 | VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { |
| 189 | switch (framebuffer.pixel_format) { | 189 | switch (framebuffer.pixel_format) { |
| 190 | case Tegra::FramebufferConfig::PixelFormat::ABGR8: | 190 | case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM: |
| 191 | return VK_FORMAT_A8B8G8R8_UNORM_PACK32; | 191 | return VK_FORMAT_A8B8G8R8_UNORM_PACK32; |
| 192 | case Tegra::FramebufferConfig::PixelFormat::RGB565: | 192 | case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM: |
| 193 | return VK_FORMAT_R5G6B5_UNORM_PACK16; | 193 | return VK_FORMAT_R5G6B5_UNORM_PACK16; |
| 194 | default: | 194 | default: |
| 195 | UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", | 195 | UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 2be38d419..1d2f8b557 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -39,16 +39,17 @@ std::unique_ptr<VKStreamBuffer> CreateStreamBuffer(const VKDevice& device, VKSch | |||
| 39 | 39 | ||
| 40 | Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler_, | 40 | Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler_, |
| 41 | VKStagingBufferPool& staging_pool_, VAddr cpu_addr, std::size_t size) | 41 | VKStagingBufferPool& staging_pool_, VAddr cpu_addr, std::size_t size) |
| 42 | : VideoCommon::BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} { | 42 | : BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} { |
| 43 | VkBufferCreateInfo ci; | 43 | const VkBufferCreateInfo ci{ |
| 44 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | 44 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| 45 | ci.pNext = nullptr; | 45 | .pNext = nullptr, |
| 46 | ci.flags = 0; | 46 | .flags = 0, |
| 47 | ci.size = static_cast<VkDeviceSize>(size); | 47 | .size = static_cast<VkDeviceSize>(size), |
| 48 | ci.usage = BUFFER_USAGE | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; | 48 | .usage = BUFFER_USAGE | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, |
| 49 | ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | 49 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 50 | ci.queueFamilyIndexCount = 0; | 50 | .queueFamilyIndexCount = 0, |
| 51 | ci.pQueueFamilyIndices = nullptr; | 51 | .pQueueFamilyIndices = nullptr, |
| 52 | }; | ||
| 52 | 53 | ||
| 53 | buffer.handle = device.GetLogical().CreateBuffer(ci); | 54 | buffer.handle = device.GetLogical().CreateBuffer(ci); |
| 54 | buffer.commit = memory_manager.Commit(buffer.handle, false); | 55 | buffer.commit = memory_manager.Commit(buffer.handle, false); |
| @@ -66,16 +67,17 @@ void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) { | |||
| 66 | scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { | 67 | scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { |
| 67 | cmdbuf.CopyBuffer(staging, handle, VkBufferCopy{0, offset, size}); | 68 | cmdbuf.CopyBuffer(staging, handle, VkBufferCopy{0, offset, size}); |
| 68 | 69 | ||
| 69 | VkBufferMemoryBarrier barrier; | 70 | const VkBufferMemoryBarrier barrier{ |
| 70 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; | 71 | .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, |
| 71 | barrier.pNext = nullptr; | 72 | .pNext = nullptr, |
| 72 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; | 73 | .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, |
| 73 | barrier.dstAccessMask = UPLOAD_ACCESS_BARRIERS; | 74 | .dstAccessMask = UPLOAD_ACCESS_BARRIERS, |
| 74 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 75 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, |
| 75 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 76 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, |
| 76 | barrier.buffer = handle; | 77 | .buffer = handle, |
| 77 | barrier.offset = offset; | 78 | .offset = offset, |
| 78 | barrier.size = size; | 79 | .size = size, |
| 80 | }; | ||
| 79 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {}, | 81 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {}, |
| 80 | barrier, {}); | 82 | barrier, {}); |
| 81 | }); | 83 | }); |
| @@ -87,16 +89,17 @@ void Buffer::Download(std::size_t offset, std::size_t size, u8* data) { | |||
| 87 | 89 | ||
| 88 | const VkBuffer handle = Handle(); | 90 | const VkBuffer handle = Handle(); |
| 89 | scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { | 91 | scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { |
| 90 | VkBufferMemoryBarrier barrier; | 92 | const VkBufferMemoryBarrier barrier{ |
| 91 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; | 93 | .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, |
| 92 | barrier.pNext = nullptr; | 94 | .pNext = nullptr, |
| 93 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; | 95 | .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, |
| 94 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; | 96 | .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, |
| 95 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 97 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, |
| 96 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 98 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, |
| 97 | barrier.buffer = handle; | 99 | .buffer = handle, |
| 98 | barrier.offset = offset; | 100 | .offset = offset, |
| 99 | barrier.size = size; | 101 | .size = size, |
| 102 | }; | ||
| 100 | 103 | ||
| 101 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | | 104 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | |
| 102 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | | 105 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index da71e710c..182461ed9 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp | |||
| @@ -115,32 +115,32 @@ constexpr u8 quad_array[] = { | |||
| 115 | 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00}; | 115 | 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00}; |
| 116 | 116 | ||
| 117 | VkDescriptorSetLayoutBinding BuildQuadArrayPassDescriptorSetLayoutBinding() { | 117 | VkDescriptorSetLayoutBinding BuildQuadArrayPassDescriptorSetLayoutBinding() { |
| 118 | VkDescriptorSetLayoutBinding binding; | 118 | return { |
| 119 | binding.binding = 0; | 119 | .binding = 0, |
| 120 | binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; | 120 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, |
| 121 | binding.descriptorCount = 1; | 121 | .descriptorCount = 1, |
| 122 | binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; | 122 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, |
| 123 | binding.pImmutableSamplers = nullptr; | 123 | .pImmutableSamplers = nullptr, |
| 124 | return binding; | 124 | }; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | VkDescriptorUpdateTemplateEntryKHR BuildQuadArrayPassDescriptorUpdateTemplateEntry() { | 127 | VkDescriptorUpdateTemplateEntryKHR BuildQuadArrayPassDescriptorUpdateTemplateEntry() { |
| 128 | VkDescriptorUpdateTemplateEntryKHR entry; | 128 | return { |
| 129 | entry.dstBinding = 0; | 129 | .dstBinding = 0, |
| 130 | entry.dstArrayElement = 0; | 130 | .dstArrayElement = 0, |
| 131 | entry.descriptorCount = 1; | 131 | .descriptorCount = 1, |
| 132 | entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; | 132 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, |
| 133 | entry.offset = 0; | 133 | .offset = 0, |
| 134 | entry.stride = sizeof(DescriptorUpdateEntry); | 134 | .stride = sizeof(DescriptorUpdateEntry), |
| 135 | return entry; | 135 | }; |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | VkPushConstantRange BuildComputePushConstantRange(std::size_t size) { | 138 | VkPushConstantRange BuildComputePushConstantRange(std::size_t size) { |
| 139 | VkPushConstantRange range; | 139 | return { |
| 140 | range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; | 140 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, |
| 141 | range.offset = 0; | 141 | .offset = 0, |
| 142 | range.size = static_cast<u32>(size); | 142 | .size = static_cast<u32>(size), |
| 143 | return range; | 143 | }; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | // Uint8 SPIR-V module. Generated from the "shaders/" directory. | 146 | // Uint8 SPIR-V module. Generated from the "shaders/" directory. |
| @@ -344,29 +344,33 @@ constexpr u8 QUAD_INDEXED_SPV[] = { | |||
| 344 | 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00}; | 344 | 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00}; |
| 345 | 345 | ||
| 346 | std::array<VkDescriptorSetLayoutBinding, 2> BuildInputOutputDescriptorSetBindings() { | 346 | std::array<VkDescriptorSetLayoutBinding, 2> BuildInputOutputDescriptorSetBindings() { |
| 347 | std::array<VkDescriptorSetLayoutBinding, 2> bindings; | 347 | return {{ |
| 348 | bindings[0].binding = 0; | 348 | { |
| 349 | bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; | 349 | .binding = 0, |
| 350 | bindings[0].descriptorCount = 1; | 350 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, |
| 351 | bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; | 351 | .descriptorCount = 1, |
| 352 | bindings[0].pImmutableSamplers = nullptr; | 352 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, |
| 353 | bindings[1].binding = 1; | 353 | .pImmutableSamplers = nullptr, |
| 354 | bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; | 354 | }, |
| 355 | bindings[1].descriptorCount = 1; | 355 | { |
| 356 | bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; | 356 | .binding = 1, |
| 357 | bindings[1].pImmutableSamplers = nullptr; | 357 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, |
| 358 | return bindings; | 358 | .descriptorCount = 1, |
| 359 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 360 | .pImmutableSamplers = nullptr, | ||
| 361 | }, | ||
| 362 | }}; | ||
| 359 | } | 363 | } |
| 360 | 364 | ||
| 361 | VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() { | 365 | VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() { |
| 362 | VkDescriptorUpdateTemplateEntryKHR entry; | 366 | return { |
| 363 | entry.dstBinding = 0; | 367 | .dstBinding = 0, |
| 364 | entry.dstArrayElement = 0; | 368 | .dstArrayElement = 0, |
| 365 | entry.descriptorCount = 2; | 369 | .descriptorCount = 2, |
| 366 | entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; | 370 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, |
| 367 | entry.offset = 0; | 371 | .offset = 0, |
| 368 | entry.stride = sizeof(DescriptorUpdateEntry); | 372 | .stride = sizeof(DescriptorUpdateEntry), |
| 369 | return entry; | 373 | }; |
| 370 | } | 374 | } |
| 371 | 375 | ||
| 372 | } // Anonymous namespace | 376 | } // Anonymous namespace |
| @@ -376,37 +380,37 @@ VKComputePass::VKComputePass(const VKDevice& device, VKDescriptorPool& descripto | |||
| 376 | vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates, | 380 | vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates, |
| 377 | vk::Span<VkPushConstantRange> push_constants, std::size_t code_size, | 381 | vk::Span<VkPushConstantRange> push_constants, std::size_t code_size, |
| 378 | const u8* code) { | 382 | const u8* code) { |
| 379 | VkDescriptorSetLayoutCreateInfo descriptor_layout_ci; | 383 | descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout({ |
| 380 | descriptor_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; | 384 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, |
| 381 | descriptor_layout_ci.pNext = nullptr; | 385 | .pNext = nullptr, |
| 382 | descriptor_layout_ci.flags = 0; | 386 | .flags = 0, |
| 383 | descriptor_layout_ci.bindingCount = bindings.size(); | 387 | .bindingCount = bindings.size(), |
| 384 | descriptor_layout_ci.pBindings = bindings.data(); | 388 | .pBindings = bindings.data(), |
| 385 | descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(descriptor_layout_ci); | 389 | }); |
| 386 | 390 | ||
| 387 | VkPipelineLayoutCreateInfo pipeline_layout_ci; | 391 | layout = device.GetLogical().CreatePipelineLayout({ |
| 388 | pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; | 392 | .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, |
| 389 | pipeline_layout_ci.pNext = nullptr; | 393 | .pNext = nullptr, |
| 390 | pipeline_layout_ci.flags = 0; | 394 | .flags = 0, |
| 391 | pipeline_layout_ci.setLayoutCount = 1; | 395 | .setLayoutCount = 1, |
| 392 | pipeline_layout_ci.pSetLayouts = descriptor_set_layout.address(); | 396 | .pSetLayouts = descriptor_set_layout.address(), |
| 393 | pipeline_layout_ci.pushConstantRangeCount = push_constants.size(); | 397 | .pushConstantRangeCount = push_constants.size(), |
| 394 | pipeline_layout_ci.pPushConstantRanges = push_constants.data(); | 398 | .pPushConstantRanges = push_constants.data(), |
| 395 | layout = device.GetLogical().CreatePipelineLayout(pipeline_layout_ci); | 399 | }); |
| 396 | 400 | ||
| 397 | if (!templates.empty()) { | 401 | if (!templates.empty()) { |
| 398 | VkDescriptorUpdateTemplateCreateInfoKHR template_ci; | 402 | descriptor_template = device.GetLogical().CreateDescriptorUpdateTemplateKHR({ |
| 399 | template_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR; | 403 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, |
| 400 | template_ci.pNext = nullptr; | 404 | .pNext = nullptr, |
| 401 | template_ci.flags = 0; | 405 | .flags = 0, |
| 402 | template_ci.descriptorUpdateEntryCount = templates.size(); | 406 | .descriptorUpdateEntryCount = templates.size(), |
| 403 | template_ci.pDescriptorUpdateEntries = templates.data(); | 407 | .pDescriptorUpdateEntries = templates.data(), |
| 404 | template_ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR; | 408 | .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, |
| 405 | template_ci.descriptorSetLayout = *descriptor_set_layout; | 409 | .descriptorSetLayout = *descriptor_set_layout, |
| 406 | template_ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; | 410 | .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 407 | template_ci.pipelineLayout = *layout; | 411 | .pipelineLayout = *layout, |
| 408 | template_ci.set = 0; | 412 | .set = 0, |
| 409 | descriptor_template = device.GetLogical().CreateDescriptorUpdateTemplateKHR(template_ci); | 413 | }); |
| 410 | 414 | ||
| 411 | descriptor_allocator.emplace(descriptor_pool, *descriptor_set_layout); | 415 | descriptor_allocator.emplace(descriptor_pool, *descriptor_set_layout); |
| 412 | } | 416 | } |
| @@ -414,32 +418,32 @@ VKComputePass::VKComputePass(const VKDevice& device, VKDescriptorPool& descripto | |||
| 414 | auto code_copy = std::make_unique<u32[]>(code_size / sizeof(u32) + 1); | 418 | auto code_copy = std::make_unique<u32[]>(code_size / sizeof(u32) + 1); |
| 415 | std::memcpy(code_copy.get(), code, code_size); | 419 | std::memcpy(code_copy.get(), code, code_size); |
| 416 | 420 | ||
| 417 | VkShaderModuleCreateInfo module_ci; | 421 | module = device.GetLogical().CreateShaderModule({ |
| 418 | module_ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; | 422 | .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, |
| 419 | module_ci.pNext = nullptr; | 423 | .pNext = nullptr, |
| 420 | module_ci.flags = 0; | 424 | .flags = 0, |
| 421 | module_ci.codeSize = code_size; | 425 | .codeSize = code_size, |
| 422 | module_ci.pCode = code_copy.get(); | 426 | .pCode = code_copy.get(), |
| 423 | module = device.GetLogical().CreateShaderModule(module_ci); | 427 | }); |
| 424 | 428 | ||
| 425 | VkComputePipelineCreateInfo pipeline_ci; | 429 | pipeline = device.GetLogical().CreateComputePipeline({ |
| 426 | pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; | 430 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, |
| 427 | pipeline_ci.pNext = nullptr; | 431 | .pNext = nullptr, |
| 428 | pipeline_ci.flags = 0; | 432 | .flags = 0, |
| 429 | pipeline_ci.layout = *layout; | 433 | .stage = |
| 430 | pipeline_ci.basePipelineHandle = nullptr; | 434 | { |
| 431 | pipeline_ci.basePipelineIndex = 0; | 435 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, |
| 432 | 436 | .pNext = nullptr, | |
| 433 | VkPipelineShaderStageCreateInfo& stage_ci = pipeline_ci.stage; | 437 | .flags = 0, |
| 434 | stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; | 438 | .stage = VK_SHADER_STAGE_COMPUTE_BIT, |
| 435 | stage_ci.pNext = nullptr; | 439 | .module = *module, |
| 436 | stage_ci.flags = 0; | 440 | .pName = "main", |
| 437 | stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT; | 441 | .pSpecializationInfo = nullptr, |
| 438 | stage_ci.module = *module; | 442 | }, |
| 439 | stage_ci.pName = "main"; | 443 | .layout = *layout, |
| 440 | stage_ci.pSpecializationInfo = nullptr; | 444 | .basePipelineHandle = nullptr, |
| 441 | 445 | .basePipelineIndex = 0, | |
| 442 | pipeline = device.GetLogical().CreateComputePipeline(pipeline_ci); | 446 | }); |
| 443 | } | 447 | } |
| 444 | 448 | ||
| 445 | VKComputePass::~VKComputePass() = default; | 449 | VKComputePass::~VKComputePass() = default; |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 281bf9ac3..ed9d2991c 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -43,12 +43,13 @@ vk::DescriptorSetLayout VKComputePipeline::CreateDescriptorSetLayout() const { | |||
| 43 | const auto add_bindings = [&](VkDescriptorType descriptor_type, std::size_t num_entries) { | 43 | const auto add_bindings = [&](VkDescriptorType descriptor_type, std::size_t num_entries) { |
| 44 | // TODO(Rodrigo): Maybe make individual bindings here? | 44 | // TODO(Rodrigo): Maybe make individual bindings here? |
| 45 | for (u32 bindpoint = 0; bindpoint < static_cast<u32>(num_entries); ++bindpoint) { | 45 | for (u32 bindpoint = 0; bindpoint < static_cast<u32>(num_entries); ++bindpoint) { |
| 46 | VkDescriptorSetLayoutBinding& entry = bindings.emplace_back(); | 46 | bindings.push_back({ |
| 47 | entry.binding = binding++; | 47 | .binding = binding++, |
| 48 | entry.descriptorType = descriptor_type; | 48 | .descriptorType = descriptor_type, |
| 49 | entry.descriptorCount = 1; | 49 | .descriptorCount = 1, |
| 50 | entry.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; | 50 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, |
| 51 | entry.pImmutableSamplers = nullptr; | 51 | .pImmutableSamplers = nullptr, |
| 52 | }); | ||
| 52 | } | 53 | } |
| 53 | }; | 54 | }; |
| 54 | add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, entries.const_buffers.size()); | 55 | add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, entries.const_buffers.size()); |
| @@ -58,25 +59,25 @@ vk::DescriptorSetLayout VKComputePipeline::CreateDescriptorSetLayout() const { | |||
| 58 | add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, entries.storage_texels.size()); | 59 | add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, entries.storage_texels.size()); |
| 59 | add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, entries.images.size()); | 60 | add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, entries.images.size()); |
| 60 | 61 | ||
| 61 | VkDescriptorSetLayoutCreateInfo ci; | 62 | return device.GetLogical().CreateDescriptorSetLayout({ |
| 62 | ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; | 63 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, |
| 63 | ci.pNext = nullptr; | 64 | .pNext = nullptr, |
| 64 | ci.flags = 0; | 65 | .flags = 0, |
| 65 | ci.bindingCount = static_cast<u32>(bindings.size()); | 66 | .bindingCount = static_cast<u32>(bindings.size()), |
| 66 | ci.pBindings = bindings.data(); | 67 | .pBindings = bindings.data(), |
| 67 | return device.GetLogical().CreateDescriptorSetLayout(ci); | 68 | }); |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | vk::PipelineLayout VKComputePipeline::CreatePipelineLayout() const { | 71 | vk::PipelineLayout VKComputePipeline::CreatePipelineLayout() const { |
| 71 | VkPipelineLayoutCreateInfo ci; | 72 | return device.GetLogical().CreatePipelineLayout({ |
| 72 | ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; | 73 | .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, |
| 73 | ci.pNext = nullptr; | 74 | .pNext = nullptr, |
| 74 | ci.flags = 0; | 75 | .flags = 0, |
| 75 | ci.setLayoutCount = 1; | 76 | .setLayoutCount = 1, |
| 76 | ci.pSetLayouts = descriptor_set_layout.address(); | 77 | .pSetLayouts = descriptor_set_layout.address(), |
| 77 | ci.pushConstantRangeCount = 0; | 78 | .pushConstantRangeCount = 0, |
| 78 | ci.pPushConstantRanges = nullptr; | 79 | .pPushConstantRanges = nullptr, |
| 79 | return device.GetLogical().CreatePipelineLayout(ci); | 80 | }); |
| 80 | } | 81 | } |
| 81 | 82 | ||
| 82 | vk::DescriptorUpdateTemplateKHR VKComputePipeline::CreateDescriptorUpdateTemplate() const { | 83 | vk::DescriptorUpdateTemplateKHR VKComputePipeline::CreateDescriptorUpdateTemplate() const { |
| @@ -89,59 +90,63 @@ vk::DescriptorUpdateTemplateKHR VKComputePipeline::CreateDescriptorUpdateTemplat | |||
| 89 | return {}; | 90 | return {}; |
| 90 | } | 91 | } |
| 91 | 92 | ||
| 92 | VkDescriptorUpdateTemplateCreateInfoKHR ci; | 93 | return device.GetLogical().CreateDescriptorUpdateTemplateKHR({ |
| 93 | ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR; | 94 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, |
| 94 | ci.pNext = nullptr; | 95 | .pNext = nullptr, |
| 95 | ci.flags = 0; | 96 | .flags = 0, |
| 96 | ci.descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()); | 97 | .descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()), |
| 97 | ci.pDescriptorUpdateEntries = template_entries.data(); | 98 | .pDescriptorUpdateEntries = template_entries.data(), |
| 98 | ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR; | 99 | .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, |
| 99 | ci.descriptorSetLayout = *descriptor_set_layout; | 100 | .descriptorSetLayout = *descriptor_set_layout, |
| 100 | ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; | 101 | .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 101 | ci.pipelineLayout = *layout; | 102 | .pipelineLayout = *layout, |
| 102 | ci.set = DESCRIPTOR_SET; | 103 | .set = DESCRIPTOR_SET, |
| 103 | return device.GetLogical().CreateDescriptorUpdateTemplateKHR(ci); | 104 | }); |
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | vk::ShaderModule VKComputePipeline::CreateShaderModule(const std::vector<u32>& code) const { | 107 | vk::ShaderModule VKComputePipeline::CreateShaderModule(const std::vector<u32>& code) const { |
| 107 | device.SaveShader(code); | 108 | device.SaveShader(code); |
| 108 | 109 | ||
| 109 | VkShaderModuleCreateInfo ci; | 110 | return device.GetLogical().CreateShaderModule({ |
| 110 | ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; | 111 | .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, |
| 111 | ci.pNext = nullptr; | 112 | .pNext = nullptr, |
| 112 | ci.flags = 0; | 113 | .flags = 0, |
| 113 | ci.codeSize = code.size() * sizeof(u32); | 114 | .codeSize = code.size() * sizeof(u32), |
| 114 | ci.pCode = code.data(); | 115 | .pCode = code.data(), |
| 115 | return device.GetLogical().CreateShaderModule(ci); | 116 | }); |
| 116 | } | 117 | } |
| 117 | 118 | ||
| 118 | vk::Pipeline VKComputePipeline::CreatePipeline() const { | 119 | vk::Pipeline VKComputePipeline::CreatePipeline() const { |
| 119 | VkComputePipelineCreateInfo ci; | 120 | |
| 120 | VkPipelineShaderStageCreateInfo& stage_ci = ci.stage; | 121 | VkComputePipelineCreateInfo ci{ |
| 121 | stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; | 122 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, |
| 122 | stage_ci.pNext = nullptr; | 123 | .pNext = nullptr, |
| 123 | stage_ci.flags = 0; | 124 | .flags = 0, |
| 124 | stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT; | 125 | .stage = |
| 125 | stage_ci.module = *shader_module; | 126 | { |
| 126 | stage_ci.pName = "main"; | 127 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, |
| 127 | stage_ci.pSpecializationInfo = nullptr; | 128 | .pNext = nullptr, |
| 128 | 129 | .flags = 0, | |
| 129 | VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci; | 130 | .stage = VK_SHADER_STAGE_COMPUTE_BIT, |
| 130 | subgroup_size_ci.sType = | 131 | .module = *shader_module, |
| 131 | VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT; | 132 | .pName = "main", |
| 132 | subgroup_size_ci.pNext = nullptr; | 133 | .pSpecializationInfo = nullptr, |
| 133 | subgroup_size_ci.requiredSubgroupSize = GuestWarpSize; | 134 | }, |
| 135 | .layout = *layout, | ||
| 136 | .basePipelineHandle = nullptr, | ||
| 137 | .basePipelineIndex = 0, | ||
| 138 | }; | ||
| 139 | |||
| 140 | const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{ | ||
| 141 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT, | ||
| 142 | .pNext = nullptr, | ||
| 143 | .requiredSubgroupSize = GuestWarpSize, | ||
| 144 | }; | ||
| 134 | 145 | ||
| 135 | if (entries.uses_warps && device.IsGuestWarpSizeSupported(VK_SHADER_STAGE_COMPUTE_BIT)) { | 146 | if (entries.uses_warps && device.IsGuestWarpSizeSupported(VK_SHADER_STAGE_COMPUTE_BIT)) { |
| 136 | stage_ci.pNext = &subgroup_size_ci; | 147 | ci.stage.pNext = &subgroup_size_ci; |
| 137 | } | 148 | } |
| 138 | 149 | ||
| 139 | ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; | ||
| 140 | ci.pNext = nullptr; | ||
| 141 | ci.flags = 0; | ||
| 142 | ci.layout = *layout; | ||
| 143 | ci.basePipelineHandle = nullptr; | ||
| 144 | ci.basePipelineIndex = 0; | ||
| 145 | return device.GetLogical().CreateComputePipeline(ci); | 150 | return device.GetLogical().CreateComputePipeline(ci); |
| 146 | } | 151 | } |
| 147 | 152 | ||
diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp index 9259b618d..ac4a0884e 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp | |||
| @@ -43,27 +43,30 @@ vk::DescriptorPool* VKDescriptorPool::AllocateNewPool() { | |||
| 43 | {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, num_sets * 64}, | 43 | {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, num_sets * 64}, |
| 44 | {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, num_sets * 64}, | 44 | {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, num_sets * 64}, |
| 45 | {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, num_sets * 64}, | 45 | {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, num_sets * 64}, |
| 46 | {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, num_sets * 40}}; | 46 | {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, num_sets * 40}, |
| 47 | 47 | }; | |
| 48 | VkDescriptorPoolCreateInfo ci; | 48 | |
| 49 | ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; | 49 | const VkDescriptorPoolCreateInfo ci{ |
| 50 | ci.pNext = nullptr; | 50 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, |
| 51 | ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; | 51 | .pNext = nullptr, |
| 52 | ci.maxSets = num_sets; | 52 | .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, |
| 53 | ci.poolSizeCount = static_cast<u32>(std::size(pool_sizes)); | 53 | .maxSets = num_sets, |
| 54 | ci.pPoolSizes = std::data(pool_sizes); | 54 | .poolSizeCount = static_cast<u32>(std::size(pool_sizes)), |
| 55 | .pPoolSizes = std::data(pool_sizes), | ||
| 56 | }; | ||
| 55 | return &pools.emplace_back(device.GetLogical().CreateDescriptorPool(ci)); | 57 | return &pools.emplace_back(device.GetLogical().CreateDescriptorPool(ci)); |
| 56 | } | 58 | } |
| 57 | 59 | ||
| 58 | vk::DescriptorSets VKDescriptorPool::AllocateDescriptors(VkDescriptorSetLayout layout, | 60 | vk::DescriptorSets VKDescriptorPool::AllocateDescriptors(VkDescriptorSetLayout layout, |
| 59 | std::size_t count) { | 61 | std::size_t count) { |
| 60 | const std::vector layout_copies(count, layout); | 62 | const std::vector layout_copies(count, layout); |
| 61 | VkDescriptorSetAllocateInfo ai; | 63 | VkDescriptorSetAllocateInfo ai{ |
| 62 | ai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; | 64 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, |
| 63 | ai.pNext = nullptr; | 65 | .pNext = nullptr, |
| 64 | ai.descriptorPool = **active_pool; | 66 | .descriptorPool = **active_pool, |
| 65 | ai.descriptorSetCount = static_cast<u32>(count); | 67 | .descriptorSetCount = static_cast<u32>(count), |
| 66 | ai.pSetLayouts = layout_copies.data(); | 68 | .pSetLayouts = layout_copies.data(), |
| 69 | }; | ||
| 67 | 70 | ||
| 68 | vk::DescriptorSets sets = active_pool->Allocate(ai); | 71 | vk::DescriptorSets sets = active_pool->Allocate(ai); |
| 69 | if (!sets.IsOutOfPoolMemory()) { | 72 | if (!sets.IsOutOfPoolMemory()) { |
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp index 9226e591c..6245e0d78 100644 --- a/src/video_core/renderer_vulkan/vk_device.cpp +++ b/src/video_core/renderer_vulkan/vk_device.cpp | |||
| @@ -84,14 +84,19 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties( | |||
| 84 | VK_FORMAT_A8B8G8R8_UNORM_PACK32, | 84 | VK_FORMAT_A8B8G8R8_UNORM_PACK32, |
| 85 | VK_FORMAT_A8B8G8R8_UINT_PACK32, | 85 | VK_FORMAT_A8B8G8R8_UINT_PACK32, |
| 86 | VK_FORMAT_A8B8G8R8_SNORM_PACK32, | 86 | VK_FORMAT_A8B8G8R8_SNORM_PACK32, |
| 87 | VK_FORMAT_A8B8G8R8_SINT_PACK32, | ||
| 87 | VK_FORMAT_A8B8G8R8_SRGB_PACK32, | 88 | VK_FORMAT_A8B8G8R8_SRGB_PACK32, |
| 88 | VK_FORMAT_B5G6R5_UNORM_PACK16, | 89 | VK_FORMAT_B5G6R5_UNORM_PACK16, |
| 89 | VK_FORMAT_A2B10G10R10_UNORM_PACK32, | 90 | VK_FORMAT_A2B10G10R10_UNORM_PACK32, |
| 91 | VK_FORMAT_A2B10G10R10_UINT_PACK32, | ||
| 90 | VK_FORMAT_A1R5G5B5_UNORM_PACK16, | 92 | VK_FORMAT_A1R5G5B5_UNORM_PACK16, |
| 91 | VK_FORMAT_R32G32B32A32_SFLOAT, | 93 | VK_FORMAT_R32G32B32A32_SFLOAT, |
| 94 | VK_FORMAT_R32G32B32A32_SINT, | ||
| 92 | VK_FORMAT_R32G32B32A32_UINT, | 95 | VK_FORMAT_R32G32B32A32_UINT, |
| 93 | VK_FORMAT_R32G32_SFLOAT, | 96 | VK_FORMAT_R32G32_SFLOAT, |
| 97 | VK_FORMAT_R32G32_SINT, | ||
| 94 | VK_FORMAT_R32G32_UINT, | 98 | VK_FORMAT_R32G32_UINT, |
| 99 | VK_FORMAT_R16G16B16A16_SINT, | ||
| 95 | VK_FORMAT_R16G16B16A16_UINT, | 100 | VK_FORMAT_R16G16B16A16_UINT, |
| 96 | VK_FORMAT_R16G16B16A16_SNORM, | 101 | VK_FORMAT_R16G16B16A16_SNORM, |
| 97 | VK_FORMAT_R16G16B16A16_UNORM, | 102 | VK_FORMAT_R16G16B16A16_UNORM, |
| @@ -103,8 +108,11 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties( | |||
| 103 | VK_FORMAT_R8G8B8A8_SRGB, | 108 | VK_FORMAT_R8G8B8A8_SRGB, |
| 104 | VK_FORMAT_R8G8_UNORM, | 109 | VK_FORMAT_R8G8_UNORM, |
| 105 | VK_FORMAT_R8G8_SNORM, | 110 | VK_FORMAT_R8G8_SNORM, |
| 111 | VK_FORMAT_R8G8_SINT, | ||
| 106 | VK_FORMAT_R8G8_UINT, | 112 | VK_FORMAT_R8G8_UINT, |
| 107 | VK_FORMAT_R8_UNORM, | 113 | VK_FORMAT_R8_UNORM, |
| 114 | VK_FORMAT_R8_SNORM, | ||
| 115 | VK_FORMAT_R8_SINT, | ||
| 108 | VK_FORMAT_R8_UINT, | 116 | VK_FORMAT_R8_UINT, |
| 109 | VK_FORMAT_B10G11R11_UFLOAT_PACK32, | 117 | VK_FORMAT_B10G11R11_UFLOAT_PACK32, |
| 110 | VK_FORMAT_R32_SFLOAT, | 118 | VK_FORMAT_R32_SFLOAT, |
| @@ -124,6 +132,7 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties( | |||
| 124 | VK_FORMAT_BC2_UNORM_BLOCK, | 132 | VK_FORMAT_BC2_UNORM_BLOCK, |
| 125 | VK_FORMAT_BC3_UNORM_BLOCK, | 133 | VK_FORMAT_BC3_UNORM_BLOCK, |
| 126 | VK_FORMAT_BC4_UNORM_BLOCK, | 134 | VK_FORMAT_BC4_UNORM_BLOCK, |
| 135 | VK_FORMAT_BC4_SNORM_BLOCK, | ||
| 127 | VK_FORMAT_BC5_UNORM_BLOCK, | 136 | VK_FORMAT_BC5_UNORM_BLOCK, |
| 128 | VK_FORMAT_BC5_SNORM_BLOCK, | 137 | VK_FORMAT_BC5_SNORM_BLOCK, |
| 129 | VK_FORMAT_BC7_UNORM_BLOCK, | 138 | VK_FORMAT_BC7_UNORM_BLOCK, |
| @@ -757,14 +766,14 @@ std::vector<VkDeviceQueueCreateInfo> VKDevice::GetDeviceQueueCreateInfos() const | |||
| 757 | queue_cis.reserve(unique_queue_families.size()); | 766 | queue_cis.reserve(unique_queue_families.size()); |
| 758 | 767 | ||
| 759 | for (const u32 queue_family : unique_queue_families) { | 768 | for (const u32 queue_family : unique_queue_families) { |
| 760 | queue_cis.push_back({ | 769 | auto& ci = queue_cis.emplace_back(VkDeviceQueueCreateInfo{ |
| 761 | .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, | 770 | .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, |
| 762 | .pNext = nullptr, | 771 | .pNext = nullptr, |
| 763 | .flags = 0, | 772 | .flags = 0, |
| 764 | .queueFamilyIndex = queue_family, | 773 | .queueFamilyIndex = queue_family, |
| 765 | .queueCount = 1, | ||
| 766 | .pQueuePriorities = &QUEUE_PRIORITY, | ||
| 767 | }); | 774 | }); |
| 775 | ci.queueCount = 1; | ||
| 776 | ci.pQueuePriorities = &QUEUE_PRIORITY; | ||
| 768 | } | 777 | } |
| 769 | 778 | ||
| 770 | return queue_cis; | 779 | return queue_cis; |
diff --git a/src/video_core/renderer_vulkan/vk_image.cpp b/src/video_core/renderer_vulkan/vk_image.cpp index 9bceb3861..1c418ea17 100644 --- a/src/video_core/renderer_vulkan/vk_image.cpp +++ b/src/video_core/renderer_vulkan/vk_image.cpp | |||
| @@ -102,21 +102,29 @@ bool VKImage::HasChanged(u32 base_layer, u32 num_layers, u32 base_level, u32 num | |||
| 102 | 102 | ||
| 103 | void VKImage::CreatePresentView() { | 103 | void VKImage::CreatePresentView() { |
| 104 | // Image type has to be 2D to be presented. | 104 | // Image type has to be 2D to be presented. |
| 105 | VkImageViewCreateInfo image_view_ci; | 105 | present_view = device.GetLogical().CreateImageView({ |
| 106 | image_view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; | 106 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| 107 | image_view_ci.pNext = nullptr; | 107 | .pNext = nullptr, |
| 108 | image_view_ci.flags = 0; | 108 | .flags = 0, |
| 109 | image_view_ci.image = *image; | 109 | .image = *image, |
| 110 | image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D; | 110 | .viewType = VK_IMAGE_VIEW_TYPE_2D, |
| 111 | image_view_ci.format = format; | 111 | .format = format, |
| 112 | image_view_ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, | 112 | .components = |
| 113 | VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; | 113 | { |
| 114 | image_view_ci.subresourceRange.aspectMask = aspect_mask; | 114 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 115 | image_view_ci.subresourceRange.baseMipLevel = 0; | 115 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 116 | image_view_ci.subresourceRange.levelCount = 1; | 116 | .b = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 117 | image_view_ci.subresourceRange.baseArrayLayer = 0; | 117 | .a = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 118 | image_view_ci.subresourceRange.layerCount = 1; | 118 | }, |
| 119 | present_view = device.GetLogical().CreateImageView(image_view_ci); | 119 | .subresourceRange = |
| 120 | { | ||
| 121 | .aspectMask = aspect_mask, | ||
| 122 | .baseMipLevel = 0, | ||
| 123 | .levelCount = 1, | ||
| 124 | .baseArrayLayer = 0, | ||
| 125 | .layerCount = 1, | ||
| 126 | }, | ||
| 127 | }); | ||
| 120 | } | 128 | } |
| 121 | 129 | ||
| 122 | VKImage::SubrangeState& VKImage::GetSubrangeState(u32 layer, u32 level) noexcept { | 130 | VKImage::SubrangeState& VKImage::GetSubrangeState(u32 layer, u32 level) noexcept { |
diff --git a/src/video_core/renderer_vulkan/vk_memory_manager.cpp b/src/video_core/renderer_vulkan/vk_memory_manager.cpp index b4c650a63..24c8960ac 100644 --- a/src/video_core/renderer_vulkan/vk_memory_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_memory_manager.cpp | |||
| @@ -178,13 +178,12 @@ bool VKMemoryManager::AllocMemory(VkMemoryPropertyFlags wanted_properties, u32 t | |||
| 178 | }(); | 178 | }(); |
| 179 | 179 | ||
| 180 | // Try to allocate found type. | 180 | // Try to allocate found type. |
| 181 | VkMemoryAllocateInfo memory_ai; | 181 | vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({ |
| 182 | memory_ai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; | 182 | .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, |
| 183 | memory_ai.pNext = nullptr; | 183 | .pNext = nullptr, |
| 184 | memory_ai.allocationSize = size; | 184 | .allocationSize = size, |
| 185 | memory_ai.memoryTypeIndex = type; | 185 | .memoryTypeIndex = type, |
| 186 | 186 | }); | |
| 187 | vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory(memory_ai); | ||
| 188 | if (!memory) { | 187 | if (!memory) { |
| 189 | LOG_CRITICAL(Render_Vulkan, "Device allocation failed!"); | 188 | LOG_CRITICAL(Render_Vulkan, "Device allocation failed!"); |
| 190 | return false; | 189 | return false; |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 3da835324..42b3a744c 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -88,12 +88,13 @@ void AddBindings(std::vector<VkDescriptorSetLayoutBinding>& bindings, u32& bindi | |||
| 88 | // Combined image samplers can be arrayed. | 88 | // Combined image samplers can be arrayed. |
| 89 | count = container[i].size; | 89 | count = container[i].size; |
| 90 | } | 90 | } |
| 91 | VkDescriptorSetLayoutBinding& entry = bindings.emplace_back(); | 91 | bindings.push_back({ |
| 92 | entry.binding = binding++; | 92 | .binding = binding++, |
| 93 | entry.descriptorType = descriptor_type; | 93 | .descriptorType = descriptor_type, |
| 94 | entry.descriptorCount = count; | 94 | .descriptorCount = count, |
| 95 | entry.stageFlags = stage_flags; | 95 | .stageFlags = stage_flags, |
| 96 | entry.pImmutableSamplers = nullptr; | 96 | .pImmutableSamplers = nullptr, |
| 97 | }); | ||
| 97 | } | 98 | } |
| 98 | } | 99 | } |
| 99 | 100 | ||
| @@ -259,10 +260,10 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach | |||
| 259 | } | 260 | } |
| 260 | } | 261 | } |
| 261 | 262 | ||
| 262 | Specialization specialization; | 263 | const Specialization specialization{ |
| 263 | specialization.workgroup_size = key.workgroup_size; | 264 | .workgroup_size = key.workgroup_size, |
| 264 | specialization.shared_memory_size = key.shared_memory_size; | 265 | .shared_memory_size = key.shared_memory_size, |
| 265 | 266 | }; | |
| 266 | const SPIRVShader spirv_shader{Decompile(device, shader->GetIR(), ShaderType::Compute, | 267 | const SPIRVShader spirv_shader{Decompile(device, shader->GetIR(), ShaderType::Compute, |
| 267 | shader->GetRegistry(), specialization), | 268 | shader->GetRegistry(), specialization), |
| 268 | shader->GetEntries()}; | 269 | shader->GetEntries()}; |
| @@ -370,13 +371,14 @@ void AddEntry(std::vector<VkDescriptorUpdateTemplateEntry>& template_entries, u3 | |||
| 370 | if constexpr (descriptor_type == COMBINED_IMAGE_SAMPLER) { | 371 | if constexpr (descriptor_type == COMBINED_IMAGE_SAMPLER) { |
| 371 | for (u32 i = 0; i < count; ++i) { | 372 | for (u32 i = 0; i < count; ++i) { |
| 372 | const u32 num_samplers = container[i].size; | 373 | const u32 num_samplers = container[i].size; |
| 373 | VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back(); | 374 | template_entries.push_back({ |
| 374 | entry.dstBinding = binding; | 375 | .dstBinding = binding, |
| 375 | entry.dstArrayElement = 0; | 376 | .dstArrayElement = 0, |
| 376 | entry.descriptorCount = num_samplers; | 377 | .descriptorCount = num_samplers, |
| 377 | entry.descriptorType = descriptor_type; | 378 | .descriptorType = descriptor_type, |
| 378 | entry.offset = offset; | 379 | .offset = offset, |
| 379 | entry.stride = entry_size; | 380 | .stride = entry_size, |
| 381 | }); | ||
| 380 | 382 | ||
| 381 | ++binding; | 383 | ++binding; |
| 382 | offset += num_samplers * entry_size; | 384 | offset += num_samplers * entry_size; |
| @@ -389,22 +391,24 @@ void AddEntry(std::vector<VkDescriptorUpdateTemplateEntry>& template_entries, u3 | |||
| 389 | // Nvidia has a bug where updating multiple texels at once causes the driver to crash. | 391 | // Nvidia has a bug where updating multiple texels at once causes the driver to crash. |
| 390 | // Note: Fixed in driver Windows 443.24, Linux 440.66.15 | 392 | // Note: Fixed in driver Windows 443.24, Linux 440.66.15 |
| 391 | for (u32 i = 0; i < count; ++i) { | 393 | for (u32 i = 0; i < count; ++i) { |
| 392 | VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back(); | 394 | template_entries.push_back({ |
| 393 | entry.dstBinding = binding + i; | 395 | .dstBinding = binding + i, |
| 394 | entry.dstArrayElement = 0; | 396 | .dstArrayElement = 0, |
| 395 | entry.descriptorCount = 1; | 397 | .descriptorCount = 1, |
| 396 | entry.descriptorType = descriptor_type; | 398 | .descriptorType = descriptor_type, |
| 397 | entry.offset = static_cast<std::size_t>(offset + i * entry_size); | 399 | .offset = static_cast<std::size_t>(offset + i * entry_size), |
| 398 | entry.stride = entry_size; | 400 | .stride = entry_size, |
| 401 | }); | ||
| 399 | } | 402 | } |
| 400 | } else if (count > 0) { | 403 | } else if (count > 0) { |
| 401 | VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back(); | 404 | template_entries.push_back({ |
| 402 | entry.dstBinding = binding; | 405 | .dstBinding = binding, |
| 403 | entry.dstArrayElement = 0; | 406 | .dstArrayElement = 0, |
| 404 | entry.descriptorCount = count; | 407 | .descriptorCount = count, |
| 405 | entry.descriptorType = descriptor_type; | 408 | .descriptorType = descriptor_type, |
| 406 | entry.offset = offset; | 409 | .offset = offset, |
| 407 | entry.stride = entry_size; | 410 | .stride = entry_size, |
| 411 | }); | ||
| 408 | } | 412 | } |
| 409 | offset += count * entry_size; | 413 | offset += count * entry_size; |
| 410 | binding += count; | 414 | binding += count; |
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index bc91c48cc..6cd63d090 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp | |||
| @@ -47,14 +47,14 @@ std::pair<VkQueryPool, u32> QueryPool::Commit(VKFence& fence) { | |||
| 47 | void QueryPool::Allocate(std::size_t begin, std::size_t end) { | 47 | void QueryPool::Allocate(std::size_t begin, std::size_t end) { |
| 48 | usage.resize(end); | 48 | usage.resize(end); |
| 49 | 49 | ||
| 50 | VkQueryPoolCreateInfo query_pool_ci; | 50 | pools.push_back(device->GetLogical().CreateQueryPool({ |
| 51 | query_pool_ci.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; | 51 | .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, |
| 52 | query_pool_ci.pNext = nullptr; | 52 | .pNext = nullptr, |
| 53 | query_pool_ci.flags = 0; | 53 | .flags = 0, |
| 54 | query_pool_ci.queryType = GetTarget(type); | 54 | .queryType = GetTarget(type), |
| 55 | query_pool_ci.queryCount = static_cast<u32>(end - begin); | 55 | .queryCount = static_cast<u32>(end - begin), |
| 56 | query_pool_ci.pipelineStatistics = 0; | 56 | .pipelineStatistics = 0, |
| 57 | pools.push_back(device->GetLogical().CreateQueryPool(query_pool_ci)); | 57 | })); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | void QueryPool::Reserve(std::pair<VkQueryPool, u32> query) { | 60 | void QueryPool::Reserve(std::pair<VkQueryPool, u32> query) { |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 7625871c2..31e44aa2b 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -64,20 +64,22 @@ VkViewport GetViewportState(const VKDevice& device, const Maxwell& regs, std::si | |||
| 64 | const auto& src = regs.viewport_transform[index]; | 64 | const auto& src = regs.viewport_transform[index]; |
| 65 | const float width = src.scale_x * 2.0f; | 65 | const float width = src.scale_x * 2.0f; |
| 66 | const float height = src.scale_y * 2.0f; | 66 | const float height = src.scale_y * 2.0f; |
| 67 | const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f; | ||
| 67 | 68 | ||
| 68 | VkViewport viewport; | 69 | VkViewport viewport{ |
| 69 | viewport.x = src.translate_x - src.scale_x; | 70 | .x = src.translate_x - src.scale_x, |
| 70 | viewport.y = src.translate_y - src.scale_y; | 71 | .y = src.translate_y - src.scale_y, |
| 71 | viewport.width = width != 0.0f ? width : 1.0f; | 72 | .width = width != 0.0f ? width : 1.0f, |
| 72 | viewport.height = height != 0.0f ? height : 1.0f; | 73 | .height = height != 0.0f ? height : 1.0f, |
| 74 | .minDepth = src.translate_z - src.scale_z * reduce_z, | ||
| 75 | .maxDepth = src.translate_z + src.scale_z, | ||
| 76 | }; | ||
| 73 | 77 | ||
| 74 | const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f; | ||
| 75 | viewport.minDepth = src.translate_z - src.scale_z * reduce_z; | ||
| 76 | viewport.maxDepth = src.translate_z + src.scale_z; | ||
| 77 | if (!device.IsExtDepthRangeUnrestrictedSupported()) { | 78 | if (!device.IsExtDepthRangeUnrestrictedSupported()) { |
| 78 | viewport.minDepth = std::clamp(viewport.minDepth, 0.0f, 1.0f); | 79 | viewport.minDepth = std::clamp(viewport.minDepth, 0.0f, 1.0f); |
| 79 | viewport.maxDepth = std::clamp(viewport.maxDepth, 0.0f, 1.0f); | 80 | viewport.maxDepth = std::clamp(viewport.maxDepth, 0.0f, 1.0f); |
| 80 | } | 81 | } |
| 82 | |||
| 81 | return viewport; | 83 | return viewport; |
| 82 | } | 84 | } |
| 83 | 85 | ||
| @@ -508,10 +510,11 @@ void RasterizerVulkan::Clear() { | |||
| 508 | 510 | ||
| 509 | const u32 color_attachment = regs.clear_buffers.RT; | 511 | const u32 color_attachment = regs.clear_buffers.RT; |
| 510 | scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) { | 512 | scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) { |
| 511 | VkClearAttachment attachment; | 513 | const VkClearAttachment attachment{ |
| 512 | attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | 514 | .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, |
| 513 | attachment.colorAttachment = color_attachment; | 515 | .colorAttachment = color_attachment, |
| 514 | attachment.clearValue = clear_value; | 516 | .clearValue = clear_value, |
| 517 | }; | ||
| 515 | cmdbuf.ClearAttachments(attachment, clear_rect); | 518 | cmdbuf.ClearAttachments(attachment, clear_rect); |
| 516 | }); | 519 | }); |
| 517 | } | 520 | } |
| @@ -551,13 +554,16 @@ void RasterizerVulkan::DispatchCompute(GPUVAddr code_addr) { | |||
| 551 | query_cache.UpdateCounters(); | 554 | query_cache.UpdateCounters(); |
| 552 | 555 | ||
| 553 | const auto& launch_desc = system.GPU().KeplerCompute().launch_description; | 556 | const auto& launch_desc = system.GPU().KeplerCompute().launch_description; |
| 554 | ComputePipelineCacheKey key; | 557 | auto& pipeline = pipeline_cache.GetComputePipeline({ |
| 555 | key.shader = code_addr; | 558 | .shader = code_addr, |
| 556 | key.shared_memory_size = launch_desc.shared_alloc; | 559 | .shared_memory_size = launch_desc.shared_alloc, |
| 557 | key.workgroup_size = {launch_desc.block_dim_x, launch_desc.block_dim_y, | 560 | .workgroup_size = |
| 558 | launch_desc.block_dim_z}; | 561 | { |
| 559 | 562 | launch_desc.block_dim_x, | |
| 560 | auto& pipeline = pipeline_cache.GetComputePipeline(key); | 563 | launch_desc.block_dim_y, |
| 564 | launch_desc.block_dim_z, | ||
| 565 | }, | ||
| 566 | }); | ||
| 561 | 567 | ||
| 562 | // Compute dispatches can't be executed inside a renderpass | 568 | // Compute dispatches can't be executed inside a renderpass |
| 563 | scheduler.RequestOutsideRenderPassOperationContext(); | 569 | scheduler.RequestOutsideRenderPassOperationContext(); |
| @@ -841,17 +847,17 @@ std::tuple<VkFramebuffer, VkExtent2D> RasterizerVulkan::ConfigureFramebuffers( | |||
| 841 | const auto [fbentry, is_cache_miss] = framebuffer_cache.try_emplace(key); | 847 | const auto [fbentry, is_cache_miss] = framebuffer_cache.try_emplace(key); |
| 842 | auto& framebuffer = fbentry->second; | 848 | auto& framebuffer = fbentry->second; |
| 843 | if (is_cache_miss) { | 849 | if (is_cache_miss) { |
| 844 | VkFramebufferCreateInfo framebuffer_ci; | 850 | framebuffer = device.GetLogical().CreateFramebuffer({ |
| 845 | framebuffer_ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; | 851 | .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, |
| 846 | framebuffer_ci.pNext = nullptr; | 852 | .pNext = nullptr, |
| 847 | framebuffer_ci.flags = 0; | 853 | .flags = 0, |
| 848 | framebuffer_ci.renderPass = key.renderpass; | 854 | .renderPass = key.renderpass, |
| 849 | framebuffer_ci.attachmentCount = static_cast<u32>(key.views.size()); | 855 | .attachmentCount = static_cast<u32>(key.views.size()), |
| 850 | framebuffer_ci.pAttachments = key.views.data(); | 856 | .pAttachments = key.views.data(), |
| 851 | framebuffer_ci.width = key.width; | 857 | .width = key.width, |
| 852 | framebuffer_ci.height = key.height; | 858 | .height = key.height, |
| 853 | framebuffer_ci.layers = key.layers; | 859 | .layers = key.layers, |
| 854 | framebuffer = device.GetLogical().CreateFramebuffer(framebuffer_ci); | 860 | }); |
| 855 | } | 861 | } |
| 856 | 862 | ||
| 857 | return {*framebuffer, VkExtent2D{key.width, key.height}}; | 863 | return {*framebuffer, VkExtent2D{key.width, key.height}}; |
| @@ -1553,17 +1559,17 @@ VkBuffer RasterizerVulkan::DefaultBuffer() { | |||
| 1553 | return *default_buffer; | 1559 | return *default_buffer; |
| 1554 | } | 1560 | } |
| 1555 | 1561 | ||
| 1556 | VkBufferCreateInfo ci; | 1562 | default_buffer = device.GetLogical().CreateBuffer({ |
| 1557 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | 1563 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| 1558 | ci.pNext = nullptr; | 1564 | .pNext = nullptr, |
| 1559 | ci.flags = 0; | 1565 | .flags = 0, |
| 1560 | ci.size = DEFAULT_BUFFER_SIZE; | 1566 | .size = DEFAULT_BUFFER_SIZE, |
| 1561 | ci.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | | 1567 | .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | |
| 1562 | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; | 1568 | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, |
| 1563 | ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | 1569 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 1564 | ci.queueFamilyIndexCount = 0; | 1570 | .queueFamilyIndexCount = 0, |
| 1565 | ci.pQueueFamilyIndices = nullptr; | 1571 | .pQueueFamilyIndices = nullptr, |
| 1566 | default_buffer = device.GetLogical().CreateBuffer(ci); | 1572 | }); |
| 1567 | default_buffer_commit = memory_manager.Commit(default_buffer, false); | 1573 | default_buffer_commit = memory_manager.Commit(default_buffer, false); |
| 1568 | 1574 | ||
| 1569 | scheduler.RequestOutsideRenderPassOperationContext(); | 1575 | scheduler.RequestOutsideRenderPassOperationContext(); |
diff --git a/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp b/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp index 3f71d005e..80284cf92 100644 --- a/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp | |||
| @@ -39,10 +39,14 @@ VkRenderPass VKRenderPassCache::GetRenderPass(const RenderPassParams& params) { | |||
| 39 | 39 | ||
| 40 | vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& params) const { | 40 | vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& params) const { |
| 41 | using namespace VideoCore::Surface; | 41 | using namespace VideoCore::Surface; |
| 42 | const std::size_t num_attachments = static_cast<std::size_t>(params.num_color_attachments); | ||
| 43 | |||
| 42 | std::vector<VkAttachmentDescription> descriptors; | 44 | std::vector<VkAttachmentDescription> descriptors; |
| 45 | descriptors.reserve(num_attachments); | ||
| 46 | |||
| 43 | std::vector<VkAttachmentReference> color_references; | 47 | std::vector<VkAttachmentReference> color_references; |
| 48 | color_references.reserve(num_attachments); | ||
| 44 | 49 | ||
| 45 | const std::size_t num_attachments = static_cast<std::size_t>(params.num_color_attachments); | ||
| 46 | for (std::size_t rt = 0; rt < num_attachments; ++rt) { | 50 | for (std::size_t rt = 0; rt < num_attachments; ++rt) { |
| 47 | const auto guest_format = static_cast<Tegra::RenderTargetFormat>(params.color_formats[rt]); | 51 | const auto guest_format = static_cast<Tegra::RenderTargetFormat>(params.color_formats[rt]); |
| 48 | const PixelFormat pixel_format = PixelFormatFromRenderTargetFormat(guest_format); | 52 | const PixelFormat pixel_format = PixelFormatFromRenderTargetFormat(guest_format); |
| @@ -54,20 +58,22 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param | |||
| 54 | const VkImageLayout color_layout = ((params.texceptions >> rt) & 1) != 0 | 58 | const VkImageLayout color_layout = ((params.texceptions >> rt) & 1) != 0 |
| 55 | ? VK_IMAGE_LAYOUT_GENERAL | 59 | ? VK_IMAGE_LAYOUT_GENERAL |
| 56 | : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; | 60 | : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| 57 | VkAttachmentDescription& descriptor = descriptors.emplace_back(); | 61 | descriptors.push_back({ |
| 58 | descriptor.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT; | 62 | .flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT, |
| 59 | descriptor.format = format.format; | 63 | .format = format.format, |
| 60 | descriptor.samples = VK_SAMPLE_COUNT_1_BIT; | 64 | .samples = VK_SAMPLE_COUNT_1_BIT, |
| 61 | descriptor.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; | 65 | .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, |
| 62 | descriptor.storeOp = VK_ATTACHMENT_STORE_OP_STORE; | 66 | .storeOp = VK_ATTACHMENT_STORE_OP_STORE, |
| 63 | descriptor.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; | 67 | .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| 64 | descriptor.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; | 68 | .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| 65 | descriptor.initialLayout = color_layout; | 69 | .initialLayout = color_layout, |
| 66 | descriptor.finalLayout = color_layout; | 70 | .finalLayout = color_layout, |
| 67 | 71 | }); | |
| 68 | VkAttachmentReference& reference = color_references.emplace_back(); | 72 | |
| 69 | reference.attachment = static_cast<u32>(rt); | 73 | color_references.push_back({ |
| 70 | reference.layout = color_layout; | 74 | .attachment = static_cast<u32>(rt), |
| 75 | .layout = color_layout, | ||
| 76 | }); | ||
| 71 | } | 77 | } |
| 72 | 78 | ||
| 73 | VkAttachmentReference zeta_attachment_ref; | 79 | VkAttachmentReference zeta_attachment_ref; |
| @@ -82,32 +88,36 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param | |||
| 82 | const VkImageLayout zeta_layout = params.zeta_texception != 0 | 88 | const VkImageLayout zeta_layout = params.zeta_texception != 0 |
| 83 | ? VK_IMAGE_LAYOUT_GENERAL | 89 | ? VK_IMAGE_LAYOUT_GENERAL |
| 84 | : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; | 90 | : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
| 85 | VkAttachmentDescription& descriptor = descriptors.emplace_back(); | 91 | descriptors.push_back({ |
| 86 | descriptor.flags = 0; | 92 | .flags = 0, |
| 87 | descriptor.format = format.format; | 93 | .format = format.format, |
| 88 | descriptor.samples = VK_SAMPLE_COUNT_1_BIT; | 94 | .samples = VK_SAMPLE_COUNT_1_BIT, |
| 89 | descriptor.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; | 95 | .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, |
| 90 | descriptor.storeOp = VK_ATTACHMENT_STORE_OP_STORE; | 96 | .storeOp = VK_ATTACHMENT_STORE_OP_STORE, |
| 91 | descriptor.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; | 97 | .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD, |
| 92 | descriptor.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; | 98 | .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE, |
| 93 | descriptor.initialLayout = zeta_layout; | 99 | .initialLayout = zeta_layout, |
| 94 | descriptor.finalLayout = zeta_layout; | 100 | .finalLayout = zeta_layout, |
| 95 | 101 | }); | |
| 96 | zeta_attachment_ref.attachment = static_cast<u32>(num_attachments); | 102 | |
| 97 | zeta_attachment_ref.layout = zeta_layout; | 103 | zeta_attachment_ref = { |
| 104 | .attachment = static_cast<u32>(num_attachments), | ||
| 105 | .layout = zeta_layout, | ||
| 106 | }; | ||
| 98 | } | 107 | } |
| 99 | 108 | ||
| 100 | VkSubpassDescription subpass_description; | 109 | const VkSubpassDescription subpass_description{ |
| 101 | subpass_description.flags = 0; | 110 | .flags = 0, |
| 102 | subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; | 111 | .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 103 | subpass_description.inputAttachmentCount = 0; | 112 | .inputAttachmentCount = 0, |
| 104 | subpass_description.pInputAttachments = nullptr; | 113 | .pInputAttachments = nullptr, |
| 105 | subpass_description.colorAttachmentCount = static_cast<u32>(color_references.size()); | 114 | .colorAttachmentCount = static_cast<u32>(color_references.size()), |
| 106 | subpass_description.pColorAttachments = color_references.data(); | 115 | .pColorAttachments = color_references.data(), |
| 107 | subpass_description.pResolveAttachments = nullptr; | 116 | .pResolveAttachments = nullptr, |
| 108 | subpass_description.pDepthStencilAttachment = has_zeta ? &zeta_attachment_ref : nullptr; | 117 | .pDepthStencilAttachment = has_zeta ? &zeta_attachment_ref : nullptr, |
| 109 | subpass_description.preserveAttachmentCount = 0; | 118 | .preserveAttachmentCount = 0, |
| 110 | subpass_description.pPreserveAttachments = nullptr; | 119 | .pPreserveAttachments = nullptr, |
| 120 | }; | ||
| 111 | 121 | ||
| 112 | VkAccessFlags access = 0; | 122 | VkAccessFlags access = 0; |
| 113 | VkPipelineStageFlags stage = 0; | 123 | VkPipelineStageFlags stage = 0; |
| @@ -122,26 +132,27 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param | |||
| 122 | stage |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; | 132 | stage |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; |
| 123 | } | 133 | } |
| 124 | 134 | ||
| 125 | VkSubpassDependency subpass_dependency; | 135 | const VkSubpassDependency subpass_dependency{ |
| 126 | subpass_dependency.srcSubpass = VK_SUBPASS_EXTERNAL; | 136 | .srcSubpass = VK_SUBPASS_EXTERNAL, |
| 127 | subpass_dependency.dstSubpass = 0; | 137 | .dstSubpass = 0, |
| 128 | subpass_dependency.srcStageMask = stage; | 138 | .srcStageMask = stage, |
| 129 | subpass_dependency.dstStageMask = stage; | 139 | .dstStageMask = stage, |
| 130 | subpass_dependency.srcAccessMask = 0; | 140 | .srcAccessMask = 0, |
| 131 | subpass_dependency.dstAccessMask = access; | 141 | .dstAccessMask = access, |
| 132 | subpass_dependency.dependencyFlags = 0; | 142 | .dependencyFlags = 0, |
| 133 | 143 | }; | |
| 134 | VkRenderPassCreateInfo ci; | 144 | |
| 135 | ci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; | 145 | return device.GetLogical().CreateRenderPass({ |
| 136 | ci.pNext = nullptr; | 146 | .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, |
| 137 | ci.flags = 0; | 147 | .pNext = nullptr, |
| 138 | ci.attachmentCount = static_cast<u32>(descriptors.size()); | 148 | .flags = 0, |
| 139 | ci.pAttachments = descriptors.data(); | 149 | .attachmentCount = static_cast<u32>(descriptors.size()), |
| 140 | ci.subpassCount = 1; | 150 | .pAttachments = descriptors.data(), |
| 141 | ci.pSubpasses = &subpass_description; | 151 | .subpassCount = 1, |
| 142 | ci.dependencyCount = 1; | 152 | .pSubpasses = &subpass_description, |
| 143 | ci.pDependencies = &subpass_dependency; | 153 | .dependencyCount = 1, |
| 144 | return device.GetLogical().CreateRenderPass(ci); | 154 | .pDependencies = &subpass_dependency, |
| 155 | }); | ||
| 145 | } | 156 | } |
| 146 | 157 | ||
| 147 | } // namespace Vulkan | 158 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_resource_manager.cpp b/src/video_core/renderer_vulkan/vk_resource_manager.cpp index dc06f545a..f19330a36 100644 --- a/src/video_core/renderer_vulkan/vk_resource_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_resource_manager.cpp | |||
| @@ -18,33 +18,32 @@ namespace { | |||
| 18 | constexpr std::size_t COMMAND_BUFFER_POOL_SIZE = 0x1000; | 18 | constexpr std::size_t COMMAND_BUFFER_POOL_SIZE = 0x1000; |
| 19 | constexpr std::size_t FENCES_GROW_STEP = 0x40; | 19 | constexpr std::size_t FENCES_GROW_STEP = 0x40; |
| 20 | 20 | ||
| 21 | VkFenceCreateInfo BuildFenceCreateInfo() { | 21 | constexpr VkFenceCreateInfo BuildFenceCreateInfo() { |
| 22 | VkFenceCreateInfo fence_ci; | 22 | return { |
| 23 | fence_ci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; | 23 | .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, |
| 24 | fence_ci.pNext = nullptr; | 24 | .pNext = nullptr, |
| 25 | fence_ci.flags = 0; | 25 | .flags = 0, |
| 26 | return fence_ci; | 26 | }; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | } // Anonymous namespace | 29 | } // Anonymous namespace |
| 30 | 30 | ||
| 31 | class CommandBufferPool final : public VKFencedPool { | 31 | class CommandBufferPool final : public VKFencedPool { |
| 32 | public: | 32 | public: |
| 33 | CommandBufferPool(const VKDevice& device) | 33 | explicit CommandBufferPool(const VKDevice& device) |
| 34 | : VKFencedPool(COMMAND_BUFFER_POOL_SIZE), device{device} {} | 34 | : VKFencedPool(COMMAND_BUFFER_POOL_SIZE), device{device} {} |
| 35 | 35 | ||
| 36 | void Allocate(std::size_t begin, std::size_t end) override { | 36 | void Allocate(std::size_t begin, std::size_t end) override { |
| 37 | // Command buffers are going to be commited, recorded, executed every single usage cycle. | 37 | // Command buffers are going to be commited, recorded, executed every single usage cycle. |
| 38 | // They are also going to be reseted when commited. | 38 | // They are also going to be reseted when commited. |
| 39 | VkCommandPoolCreateInfo command_pool_ci; | ||
| 40 | command_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; | ||
| 41 | command_pool_ci.pNext = nullptr; | ||
| 42 | command_pool_ci.flags = | ||
| 43 | VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; | ||
| 44 | command_pool_ci.queueFamilyIndex = device.GetGraphicsFamily(); | ||
| 45 | |||
| 46 | Pool& pool = pools.emplace_back(); | 39 | Pool& pool = pools.emplace_back(); |
| 47 | pool.handle = device.GetLogical().CreateCommandPool(command_pool_ci); | 40 | pool.handle = device.GetLogical().CreateCommandPool({ |
| 41 | .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, | ||
| 42 | .pNext = nullptr, | ||
| 43 | .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | | ||
| 44 | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, | ||
| 45 | .queueFamilyIndex = device.GetGraphicsFamily(), | ||
| 46 | }); | ||
| 48 | pool.cmdbufs = pool.handle.Allocate(COMMAND_BUFFER_POOL_SIZE); | 47 | pool.cmdbufs = pool.handle.Allocate(COMMAND_BUFFER_POOL_SIZE); |
| 49 | } | 48 | } |
| 50 | 49 | ||
diff --git a/src/video_core/renderer_vulkan/vk_sampler_cache.cpp b/src/video_core/renderer_vulkan/vk_sampler_cache.cpp index 616eacc36..2d5460776 100644 --- a/src/video_core/renderer_vulkan/vk_sampler_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_sampler_cache.cpp | |||
| @@ -44,32 +44,35 @@ vk::Sampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc) c | |||
| 44 | const bool arbitrary_borders = device.IsExtCustomBorderColorSupported(); | 44 | const bool arbitrary_borders = device.IsExtCustomBorderColorSupported(); |
| 45 | const std::array color = tsc.GetBorderColor(); | 45 | const std::array color = tsc.GetBorderColor(); |
| 46 | 46 | ||
| 47 | VkSamplerCustomBorderColorCreateInfoEXT border; | 47 | VkSamplerCustomBorderColorCreateInfoEXT border{ |
| 48 | border.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT; | 48 | .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT, |
| 49 | border.pNext = nullptr; | 49 | .pNext = nullptr, |
| 50 | border.format = VK_FORMAT_UNDEFINED; | 50 | .format = VK_FORMAT_UNDEFINED, |
| 51 | }; | ||
| 51 | std::memcpy(&border.customBorderColor, color.data(), sizeof(color)); | 52 | std::memcpy(&border.customBorderColor, color.data(), sizeof(color)); |
| 52 | 53 | ||
| 53 | VkSamplerCreateInfo ci; | 54 | return device.GetLogical().CreateSampler({ |
| 54 | ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; | 55 | .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, |
| 55 | ci.pNext = arbitrary_borders ? &border : nullptr; | 56 | .pNext = arbitrary_borders ? &border : nullptr, |
| 56 | ci.flags = 0; | 57 | .flags = 0, |
| 57 | ci.magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter); | 58 | .magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter), |
| 58 | ci.minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter); | 59 | .minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter), |
| 59 | ci.mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter); | 60 | .mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter), |
| 60 | ci.addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter); | 61 | .addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter), |
| 61 | ci.addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter); | 62 | .addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter), |
| 62 | ci.addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter); | 63 | .addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter), |
| 63 | ci.mipLodBias = tsc.GetLodBias(); | 64 | .mipLodBias = tsc.GetLodBias(), |
| 64 | ci.anisotropyEnable = tsc.GetMaxAnisotropy() > 1.0f ? VK_TRUE : VK_FALSE; | 65 | .anisotropyEnable = |
| 65 | ci.maxAnisotropy = tsc.GetMaxAnisotropy(); | 66 | static_cast<VkBool32>(tsc.GetMaxAnisotropy() > 1.0f ? VK_TRUE : VK_FALSE), |
| 66 | ci.compareEnable = tsc.depth_compare_enabled; | 67 | .maxAnisotropy = tsc.GetMaxAnisotropy(), |
| 67 | ci.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func); | 68 | .compareEnable = tsc.depth_compare_enabled, |
| 68 | ci.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.GetMinLod(); | 69 | .compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func), |
| 69 | ci.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.GetMaxLod(); | 70 | .minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.GetMinLod(), |
| 70 | ci.borderColor = arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color); | 71 | .maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.GetMaxLod(), |
| 71 | ci.unnormalizedCoordinates = VK_FALSE; | 72 | .borderColor = |
| 72 | return device.GetLogical().CreateSampler(ci); | 73 | arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color), |
| 74 | .unnormalizedCoordinates = VK_FALSE, | ||
| 75 | }); | ||
| 73 | } | 76 | } |
| 74 | 77 | ||
| 75 | VkSampler VKSamplerCache::ToSamplerType(const vk::Sampler& sampler) const { | 78 | VkSampler VKSamplerCache::ToSamplerType(const vk::Sampler& sampler) const { |
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 56524e6f3..dbbd0961a 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp | |||
| @@ -100,16 +100,19 @@ void VKScheduler::RequestRenderpass(VkRenderPass renderpass, VkFramebuffer frame | |||
| 100 | state.framebuffer = framebuffer; | 100 | state.framebuffer = framebuffer; |
| 101 | state.render_area = render_area; | 101 | state.render_area = render_area; |
| 102 | 102 | ||
| 103 | VkRenderPassBeginInfo renderpass_bi; | 103 | const VkRenderPassBeginInfo renderpass_bi{ |
| 104 | renderpass_bi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; | 104 | .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, |
| 105 | renderpass_bi.pNext = nullptr; | 105 | .pNext = nullptr, |
| 106 | renderpass_bi.renderPass = renderpass; | 106 | .renderPass = renderpass, |
| 107 | renderpass_bi.framebuffer = framebuffer; | 107 | .framebuffer = framebuffer, |
| 108 | renderpass_bi.renderArea.offset.x = 0; | 108 | .renderArea = |
| 109 | renderpass_bi.renderArea.offset.y = 0; | 109 | { |
| 110 | renderpass_bi.renderArea.extent = render_area; | 110 | .offset = {.x = 0, .y = 0}, |
| 111 | renderpass_bi.clearValueCount = 0; | 111 | .extent = render_area, |
| 112 | renderpass_bi.pClearValues = nullptr; | 112 | }, |
| 113 | .clearValueCount = 0, | ||
| 114 | .pClearValues = nullptr, | ||
| 115 | }; | ||
| 113 | 116 | ||
| 114 | Record([renderpass_bi, end_renderpass](vk::CommandBuffer cmdbuf) { | 117 | Record([renderpass_bi, end_renderpass](vk::CommandBuffer cmdbuf) { |
| 115 | if (end_renderpass) { | 118 | if (end_renderpass) { |
| @@ -157,16 +160,17 @@ void VKScheduler::SubmitExecution(VkSemaphore semaphore) { | |||
| 157 | 160 | ||
| 158 | current_cmdbuf.End(); | 161 | current_cmdbuf.End(); |
| 159 | 162 | ||
| 160 | VkSubmitInfo submit_info; | 163 | const VkSubmitInfo submit_info{ |
| 161 | submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; | 164 | .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, |
| 162 | submit_info.pNext = nullptr; | 165 | .pNext = nullptr, |
| 163 | submit_info.waitSemaphoreCount = 0; | 166 | .waitSemaphoreCount = 0, |
| 164 | submit_info.pWaitSemaphores = nullptr; | 167 | .pWaitSemaphores = nullptr, |
| 165 | submit_info.pWaitDstStageMask = nullptr; | 168 | .pWaitDstStageMask = nullptr, |
| 166 | submit_info.commandBufferCount = 1; | 169 | .commandBufferCount = 1, |
| 167 | submit_info.pCommandBuffers = current_cmdbuf.address(); | 170 | .pCommandBuffers = current_cmdbuf.address(), |
| 168 | submit_info.signalSemaphoreCount = semaphore ? 1 : 0; | 171 | .signalSemaphoreCount = semaphore ? 1U : 0U, |
| 169 | submit_info.pSignalSemaphores = &semaphore; | 172 | .pSignalSemaphores = &semaphore, |
| 173 | }; | ||
| 170 | switch (const VkResult result = device.GetGraphicsQueue().Submit(submit_info, *current_fence)) { | 174 | switch (const VkResult result = device.GetGraphicsQueue().Submit(submit_info, *current_fence)) { |
| 171 | case VK_SUCCESS: | 175 | case VK_SUCCESS: |
| 172 | break; | 176 | break; |
| @@ -181,19 +185,18 @@ void VKScheduler::SubmitExecution(VkSemaphore semaphore) { | |||
| 181 | void VKScheduler::AllocateNewContext() { | 185 | void VKScheduler::AllocateNewContext() { |
| 182 | ++ticks; | 186 | ++ticks; |
| 183 | 187 | ||
| 184 | VkCommandBufferBeginInfo cmdbuf_bi; | ||
| 185 | cmdbuf_bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; | ||
| 186 | cmdbuf_bi.pNext = nullptr; | ||
| 187 | cmdbuf_bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; | ||
| 188 | cmdbuf_bi.pInheritanceInfo = nullptr; | ||
| 189 | |||
| 190 | std::unique_lock lock{mutex}; | 188 | std::unique_lock lock{mutex}; |
| 191 | current_fence = next_fence; | 189 | current_fence = next_fence; |
| 192 | next_fence = &resource_manager.CommitFence(); | 190 | next_fence = &resource_manager.CommitFence(); |
| 193 | 191 | ||
| 194 | current_cmdbuf = vk::CommandBuffer(resource_manager.CommitCommandBuffer(*current_fence), | 192 | current_cmdbuf = vk::CommandBuffer(resource_manager.CommitCommandBuffer(*current_fence), |
| 195 | device.GetDispatchLoader()); | 193 | device.GetDispatchLoader()); |
| 196 | current_cmdbuf.Begin(cmdbuf_bi); | 194 | current_cmdbuf.Begin({ |
| 195 | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | ||
| 196 | .pNext = nullptr, | ||
| 197 | .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, | ||
| 198 | .pInheritanceInfo = nullptr, | ||
| 199 | }); | ||
| 197 | 200 | ||
| 198 | // Enable counters once again. These are disabled when a command buffer is finished. | 201 | // Enable counters once again. These are disabled when a command buffer is finished. |
| 199 | if (query_cache) { | 202 | if (query_cache) { |
diff --git a/src/video_core/renderer_vulkan/vk_shader_util.cpp b/src/video_core/renderer_vulkan/vk_shader_util.cpp index 112df9c71..c1a218d76 100644 --- a/src/video_core/renderer_vulkan/vk_shader_util.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_util.cpp | |||
| @@ -19,13 +19,13 @@ vk::ShaderModule BuildShader(const VKDevice& device, std::size_t code_size, cons | |||
| 19 | const auto data = std::make_unique<u32[]>(code_size / sizeof(u32)); | 19 | const auto data = std::make_unique<u32[]>(code_size / sizeof(u32)); |
| 20 | std::memcpy(data.get(), code_data, code_size); | 20 | std::memcpy(data.get(), code_data, code_size); |
| 21 | 21 | ||
| 22 | VkShaderModuleCreateInfo ci; | 22 | return device.GetLogical().CreateShaderModule({ |
| 23 | ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; | 23 | .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, |
| 24 | ci.pNext = nullptr; | 24 | .pNext = nullptr, |
| 25 | ci.flags = 0; | 25 | .flags = 0, |
| 26 | ci.codeSize = code_size; | 26 | .codeSize = code_size, |
| 27 | ci.pCode = data.get(); | 27 | .pCode = data.get(), |
| 28 | return device.GetLogical().CreateShaderModule(ci); | 28 | }); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | } // namespace Vulkan | 31 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp index 45c180221..5eca0ab91 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp | |||
| @@ -71,20 +71,19 @@ VKBuffer* VKStagingBufferPool::TryGetReservedBuffer(std::size_t size, bool host_ | |||
| 71 | VKBuffer& VKStagingBufferPool::CreateStagingBuffer(std::size_t size, bool host_visible) { | 71 | VKBuffer& VKStagingBufferPool::CreateStagingBuffer(std::size_t size, bool host_visible) { |
| 72 | const u32 log2 = Common::Log2Ceil64(size); | 72 | const u32 log2 = Common::Log2Ceil64(size); |
| 73 | 73 | ||
| 74 | VkBufferCreateInfo ci; | ||
| 75 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | ||
| 76 | ci.pNext = nullptr; | ||
| 77 | ci.flags = 0; | ||
| 78 | ci.size = 1ULL << log2; | ||
| 79 | ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | | ||
| 80 | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | | ||
| 81 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; | ||
| 82 | ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | ||
| 83 | ci.queueFamilyIndexCount = 0; | ||
| 84 | ci.pQueueFamilyIndices = nullptr; | ||
| 85 | |||
| 86 | auto buffer = std::make_unique<VKBuffer>(); | 74 | auto buffer = std::make_unique<VKBuffer>(); |
| 87 | buffer->handle = device.GetLogical().CreateBuffer(ci); | 75 | buffer->handle = device.GetLogical().CreateBuffer({ |
| 76 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | ||
| 77 | .pNext = nullptr, | ||
| 78 | .flags = 0, | ||
| 79 | .size = 1ULL << log2, | ||
| 80 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | | ||
| 81 | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | | ||
| 82 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, | ||
| 83 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||
| 84 | .queueFamilyIndexCount = 0, | ||
| 85 | .pQueueFamilyIndices = nullptr, | ||
| 86 | }); | ||
| 88 | buffer->commit = memory_manager.Commit(buffer->handle, host_visible); | 87 | buffer->commit = memory_manager.Commit(buffer->handle, host_visible); |
| 89 | 88 | ||
| 90 | auto& entries = GetCache(host_visible)[log2].entries; | 89 | auto& entries = GetCache(host_visible)[log2].entries; |
diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.cpp b/src/video_core/renderer_vulkan/vk_stream_buffer.cpp index 2d28a6c47..a5526a3f5 100644 --- a/src/video_core/renderer_vulkan/vk_stream_buffer.cpp +++ b/src/video_core/renderer_vulkan/vk_stream_buffer.cpp | |||
| @@ -122,30 +122,27 @@ void VKStreamBuffer::CreateBuffers(VkBufferUsageFlags usage) { | |||
| 122 | // Substract from the preferred heap size some bytes to avoid getting out of memory. | 122 | // Substract from the preferred heap size some bytes to avoid getting out of memory. |
| 123 | const VkDeviceSize heap_size = memory_properties.memoryHeaps[preferred_heap].size; | 123 | const VkDeviceSize heap_size = memory_properties.memoryHeaps[preferred_heap].size; |
| 124 | const VkDeviceSize allocable_size = heap_size - 9 * 1024 * 1024; | 124 | const VkDeviceSize allocable_size = heap_size - 9 * 1024 * 1024; |
| 125 | 125 | buffer = device.GetLogical().CreateBuffer({ | |
| 126 | VkBufferCreateInfo buffer_ci; | 126 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| 127 | buffer_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | 127 | .pNext = nullptr, |
| 128 | buffer_ci.pNext = nullptr; | 128 | .flags = 0, |
| 129 | buffer_ci.flags = 0; | 129 | .size = std::min(PREFERRED_STREAM_BUFFER_SIZE, allocable_size), |
| 130 | buffer_ci.size = std::min(PREFERRED_STREAM_BUFFER_SIZE, allocable_size); | 130 | .usage = usage, |
| 131 | buffer_ci.usage = usage; | 131 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 132 | buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | 132 | .queueFamilyIndexCount = 0, |
| 133 | buffer_ci.queueFamilyIndexCount = 0; | 133 | .pQueueFamilyIndices = nullptr, |
| 134 | buffer_ci.pQueueFamilyIndices = nullptr; | 134 | }); |
| 135 | |||
| 136 | buffer = device.GetLogical().CreateBuffer(buffer_ci); | ||
| 137 | 135 | ||
| 138 | const auto requirements = device.GetLogical().GetBufferMemoryRequirements(*buffer); | 136 | const auto requirements = device.GetLogical().GetBufferMemoryRequirements(*buffer); |
| 139 | const u32 required_flags = requirements.memoryTypeBits; | 137 | const u32 required_flags = requirements.memoryTypeBits; |
| 140 | stream_buffer_size = static_cast<u64>(requirements.size); | 138 | stream_buffer_size = static_cast<u64>(requirements.size); |
| 141 | 139 | ||
| 142 | VkMemoryAllocateInfo memory_ai; | 140 | memory = device.GetLogical().AllocateMemory({ |
| 143 | memory_ai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; | 141 | .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, |
| 144 | memory_ai.pNext = nullptr; | 142 | .pNext = nullptr, |
| 145 | memory_ai.allocationSize = requirements.size; | 143 | .allocationSize = requirements.size, |
| 146 | memory_ai.memoryTypeIndex = GetMemoryType(memory_properties, required_flags); | 144 | .memoryTypeIndex = GetMemoryType(memory_properties, required_flags), |
| 147 | 145 | }); | |
| 148 | memory = device.GetLogical().AllocateMemory(memory_ai); | ||
| 149 | buffer.BindMemory(*memory, 0); | 146 | buffer.BindMemory(*memory, 0); |
| 150 | } | 147 | } |
| 151 | 148 | ||
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index bffd8f32a..c25e312b6 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp | |||
| @@ -95,15 +95,16 @@ bool VKSwapchain::Present(VkSemaphore render_semaphore, VKFence& fence) { | |||
| 95 | const auto present_queue{device.GetPresentQueue()}; | 95 | const auto present_queue{device.GetPresentQueue()}; |
| 96 | bool recreated = false; | 96 | bool recreated = false; |
| 97 | 97 | ||
| 98 | VkPresentInfoKHR present_info; | 98 | const VkPresentInfoKHR present_info{ |
| 99 | present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; | 99 | .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, |
| 100 | present_info.pNext = nullptr; | 100 | .pNext = nullptr, |
| 101 | present_info.waitSemaphoreCount = render_semaphore ? 2U : 1U; | 101 | .waitSemaphoreCount = render_semaphore ? 2U : 1U, |
| 102 | present_info.pWaitSemaphores = semaphores.data(); | 102 | .pWaitSemaphores = semaphores.data(), |
| 103 | present_info.swapchainCount = 1; | 103 | .swapchainCount = 1, |
| 104 | present_info.pSwapchains = swapchain.address(); | 104 | .pSwapchains = swapchain.address(), |
| 105 | present_info.pImageIndices = &image_index; | 105 | .pImageIndices = &image_index, |
| 106 | present_info.pResults = nullptr; | 106 | .pResults = nullptr, |
| 107 | }; | ||
| 107 | 108 | ||
| 108 | switch (const VkResult result = present_queue.Present(present_info)) { | 109 | switch (const VkResult result = present_queue.Present(present_info)) { |
| 109 | case VK_SUCCESS: | 110 | case VK_SUCCESS: |
| @@ -147,24 +148,25 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, | |||
| 147 | requested_image_count = capabilities.maxImageCount; | 148 | requested_image_count = capabilities.maxImageCount; |
| 148 | } | 149 | } |
| 149 | 150 | ||
| 150 | VkSwapchainCreateInfoKHR swapchain_ci; | 151 | VkSwapchainCreateInfoKHR swapchain_ci{ |
| 151 | swapchain_ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; | 152 | .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, |
| 152 | swapchain_ci.pNext = nullptr; | 153 | .pNext = nullptr, |
| 153 | swapchain_ci.flags = 0; | 154 | .flags = 0, |
| 154 | swapchain_ci.surface = surface; | 155 | .surface = surface, |
| 155 | swapchain_ci.minImageCount = requested_image_count; | 156 | .minImageCount = requested_image_count, |
| 156 | swapchain_ci.imageFormat = surface_format.format; | 157 | .imageFormat = surface_format.format, |
| 157 | swapchain_ci.imageColorSpace = surface_format.colorSpace; | 158 | .imageColorSpace = surface_format.colorSpace, |
| 158 | swapchain_ci.imageArrayLayers = 1; | 159 | .imageArrayLayers = 1, |
| 159 | swapchain_ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; | 160 | .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, |
| 160 | swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; | 161 | .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 161 | swapchain_ci.queueFamilyIndexCount = 0; | 162 | .queueFamilyIndexCount = 0, |
| 162 | swapchain_ci.pQueueFamilyIndices = nullptr; | 163 | .pQueueFamilyIndices = nullptr, |
| 163 | swapchain_ci.preTransform = capabilities.currentTransform; | 164 | .preTransform = capabilities.currentTransform, |
| 164 | swapchain_ci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; | 165 | .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, |
| 165 | swapchain_ci.presentMode = present_mode; | 166 | .presentMode = present_mode, |
| 166 | swapchain_ci.clipped = VK_FALSE; | 167 | .clipped = VK_FALSE, |
| 167 | swapchain_ci.oldSwapchain = nullptr; | 168 | .oldSwapchain = nullptr, |
| 169 | }; | ||
| 168 | 170 | ||
| 169 | const u32 graphics_family{device.GetGraphicsFamily()}; | 171 | const u32 graphics_family{device.GetGraphicsFamily()}; |
| 170 | const u32 present_family{device.GetPresentFamily()}; | 172 | const u32 present_family{device.GetPresentFamily()}; |
| @@ -173,8 +175,6 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, | |||
| 173 | swapchain_ci.imageSharingMode = VK_SHARING_MODE_CONCURRENT; | 175 | swapchain_ci.imageSharingMode = VK_SHARING_MODE_CONCURRENT; |
| 174 | swapchain_ci.queueFamilyIndexCount = static_cast<u32>(queue_indices.size()); | 176 | swapchain_ci.queueFamilyIndexCount = static_cast<u32>(queue_indices.size()); |
| 175 | swapchain_ci.pQueueFamilyIndices = queue_indices.data(); | 177 | swapchain_ci.pQueueFamilyIndices = queue_indices.data(); |
| 176 | } else { | ||
| 177 | swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; | ||
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | // Request the size again to reduce the possibility of a TOCTOU race condition. | 180 | // Request the size again to reduce the possibility of a TOCTOU race condition. |
| @@ -200,20 +200,28 @@ void VKSwapchain::CreateSemaphores() { | |||
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | void VKSwapchain::CreateImageViews() { | 202 | void VKSwapchain::CreateImageViews() { |
| 203 | VkImageViewCreateInfo ci; | 203 | VkImageViewCreateInfo ci{ |
| 204 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; | 204 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| 205 | ci.pNext = nullptr; | 205 | .pNext = nullptr, |
| 206 | ci.flags = 0; | 206 | .flags = 0, |
| 207 | // ci.image | 207 | .viewType = VK_IMAGE_VIEW_TYPE_2D, |
| 208 | ci.viewType = VK_IMAGE_VIEW_TYPE_2D; | 208 | .format = image_format, |
| 209 | ci.format = image_format; | 209 | .components = |
| 210 | ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, | 210 | { |
| 211 | VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; | 211 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 212 | ci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | 212 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 213 | ci.subresourceRange.baseMipLevel = 0; | 213 | .b = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 214 | ci.subresourceRange.levelCount = 1; | 214 | .a = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 215 | ci.subresourceRange.baseArrayLayer = 0; | 215 | }, |
| 216 | ci.subresourceRange.layerCount = 1; | 216 | .subresourceRange = |
| 217 | { | ||
| 218 | .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | ||
| 219 | .baseMipLevel = 0, | ||
| 220 | .levelCount = 1, | ||
| 221 | .baseArrayLayer = 0, | ||
| 222 | .layerCount = 1, | ||
| 223 | }, | ||
| 224 | }; | ||
| 217 | 225 | ||
| 218 | image_views.resize(image_count); | 226 | image_views.resize(image_count); |
| 219 | for (std::size_t i = 0; i < image_count; i++) { | 227 | for (std::size_t i = 0; i < image_count; i++) { |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index bd93dcf20..d102e6d27 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -95,17 +95,18 @@ VkImageViewType GetImageViewType(SurfaceTarget target) { | |||
| 95 | vk::Buffer CreateBuffer(const VKDevice& device, const SurfaceParams& params, | 95 | vk::Buffer CreateBuffer(const VKDevice& device, const SurfaceParams& params, |
| 96 | std::size_t host_memory_size) { | 96 | std::size_t host_memory_size) { |
| 97 | // TODO(Rodrigo): Move texture buffer creation to the buffer cache | 97 | // TODO(Rodrigo): Move texture buffer creation to the buffer cache |
| 98 | VkBufferCreateInfo ci; | 98 | return device.GetLogical().CreateBuffer({ |
| 99 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | 99 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| 100 | ci.pNext = nullptr; | 100 | .pNext = nullptr, |
| 101 | ci.flags = 0; | 101 | .flags = 0, |
| 102 | ci.size = static_cast<VkDeviceSize>(host_memory_size); | 102 | .size = static_cast<VkDeviceSize>(host_memory_size), |
| 103 | ci.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | | 103 | .usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | |
| 104 | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; | 104 | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | |
| 105 | ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | 105 | VK_BUFFER_USAGE_TRANSFER_DST_BIT, |
| 106 | ci.queueFamilyIndexCount = 0; | 106 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 107 | ci.pQueueFamilyIndices = nullptr; | 107 | .queueFamilyIndexCount = 0, |
| 108 | return device.GetLogical().CreateBuffer(ci); | 108 | .pQueueFamilyIndices = nullptr, |
| 109 | }); | ||
| 109 | } | 110 | } |
| 110 | 111 | ||
| 111 | VkBufferViewCreateInfo GenerateBufferViewCreateInfo(const VKDevice& device, | 112 | VkBufferViewCreateInfo GenerateBufferViewCreateInfo(const VKDevice& device, |
| @@ -113,15 +114,16 @@ VkBufferViewCreateInfo GenerateBufferViewCreateInfo(const VKDevice& device, | |||
| 113 | std::size_t host_memory_size) { | 114 | std::size_t host_memory_size) { |
| 114 | ASSERT(params.IsBuffer()); | 115 | ASSERT(params.IsBuffer()); |
| 115 | 116 | ||
| 116 | VkBufferViewCreateInfo ci; | 117 | return { |
| 117 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; | 118 | .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, |
| 118 | ci.pNext = nullptr; | 119 | .pNext = nullptr, |
| 119 | ci.flags = 0; | 120 | .flags = 0, |
| 120 | ci.buffer = buffer; | 121 | .buffer = buffer, |
| 121 | ci.format = MaxwellToVK::SurfaceFormat(device, FormatType::Buffer, params.pixel_format).format; | 122 | .format = |
| 122 | ci.offset = 0; | 123 | MaxwellToVK::SurfaceFormat(device, FormatType::Buffer, params.pixel_format).format, |
| 123 | ci.range = static_cast<VkDeviceSize>(host_memory_size); | 124 | .offset = 0, |
| 124 | return ci; | 125 | .range = static_cast<VkDeviceSize>(host_memory_size), |
| 126 | }; | ||
| 125 | } | 127 | } |
| 126 | 128 | ||
| 127 | VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceParams& params) { | 129 | VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceParams& params) { |
| @@ -130,23 +132,23 @@ VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceP | |||
| 130 | const auto [format, attachable, storage] = | 132 | const auto [format, attachable, storage] = |
| 131 | MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, params.pixel_format); | 133 | MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, params.pixel_format); |
| 132 | 134 | ||
| 133 | VkImageCreateInfo ci; | 135 | VkImageCreateInfo ci{ |
| 134 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; | 136 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| 135 | ci.pNext = nullptr; | 137 | .pNext = nullptr, |
| 136 | ci.flags = 0; | 138 | .flags = 0, |
| 137 | ci.imageType = SurfaceTargetToImage(params.target); | 139 | .imageType = SurfaceTargetToImage(params.target), |
| 138 | ci.format = format; | 140 | .format = format, |
| 139 | ci.mipLevels = params.num_levels; | 141 | .mipLevels = params.num_levels, |
| 140 | ci.arrayLayers = static_cast<u32>(params.GetNumLayers()); | 142 | .arrayLayers = static_cast<u32>(params.GetNumLayers()), |
| 141 | ci.samples = VK_SAMPLE_COUNT_1_BIT; | 143 | .samples = VK_SAMPLE_COUNT_1_BIT, |
| 142 | ci.tiling = VK_IMAGE_TILING_OPTIMAL; | 144 | .tiling = VK_IMAGE_TILING_OPTIMAL, |
| 143 | ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | 145 | .usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | |
| 144 | ci.queueFamilyIndexCount = 0; | 146 | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, |
| 145 | ci.pQueueFamilyIndices = nullptr; | 147 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 146 | ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; | 148 | .queueFamilyIndexCount = 0, |
| 147 | 149 | .pQueueFamilyIndices = nullptr, | |
| 148 | ci.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | | 150 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, |
| 149 | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; | 151 | }; |
| 150 | if (attachable) { | 152 | if (attachable) { |
| 151 | ci.usage |= params.IsPixelFormatZeta() ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | 153 | ci.usage |= params.IsPixelFormatZeta() ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
| 152 | : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; | 154 | : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| @@ -233,7 +235,7 @@ void CachedSurface::UploadTexture(const std::vector<u8>& staging_buffer) { | |||
| 233 | void CachedSurface::DownloadTexture(std::vector<u8>& staging_buffer) { | 235 | void CachedSurface::DownloadTexture(std::vector<u8>& staging_buffer) { |
| 234 | UNIMPLEMENTED_IF(params.IsBuffer()); | 236 | UNIMPLEMENTED_IF(params.IsBuffer()); |
| 235 | 237 | ||
| 236 | if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) { | 238 | if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5_UNORM) { |
| 237 | LOG_WARNING(Render_Vulkan, "A1B5G5R5 flushing is stubbed"); | 239 | LOG_WARNING(Render_Vulkan, "A1B5G5R5 flushing is stubbed"); |
| 238 | } | 240 | } |
| 239 | 241 | ||
| @@ -321,22 +323,25 @@ void CachedSurface::UploadImage(const std::vector<u8>& staging_buffer) { | |||
| 321 | } | 323 | } |
| 322 | 324 | ||
| 323 | VkBufferImageCopy CachedSurface::GetBufferImageCopy(u32 level) const { | 325 | VkBufferImageCopy CachedSurface::GetBufferImageCopy(u32 level) const { |
| 324 | VkBufferImageCopy copy; | 326 | return { |
| 325 | copy.bufferOffset = params.GetHostMipmapLevelOffset(level, is_converted); | 327 | .bufferOffset = params.GetHostMipmapLevelOffset(level, is_converted), |
| 326 | copy.bufferRowLength = 0; | 328 | .bufferRowLength = 0, |
| 327 | copy.bufferImageHeight = 0; | 329 | .bufferImageHeight = 0, |
| 328 | copy.imageSubresource.aspectMask = image->GetAspectMask(); | 330 | .imageSubresource = |
| 329 | copy.imageSubresource.mipLevel = level; | 331 | { |
| 330 | copy.imageSubresource.baseArrayLayer = 0; | 332 | .aspectMask = image->GetAspectMask(), |
| 331 | copy.imageSubresource.layerCount = static_cast<u32>(params.GetNumLayers()); | 333 | .mipLevel = level, |
| 332 | copy.imageOffset.x = 0; | 334 | .baseArrayLayer = 0, |
| 333 | copy.imageOffset.y = 0; | 335 | .layerCount = static_cast<u32>(params.GetNumLayers()), |
| 334 | copy.imageOffset.z = 0; | 336 | }, |
| 335 | copy.imageExtent.width = params.GetMipWidth(level); | 337 | .imageOffset = {.x = 0, .y = 0, .z = 0}, |
| 336 | copy.imageExtent.height = params.GetMipHeight(level); | 338 | .imageExtent = |
| 337 | copy.imageExtent.depth = | 339 | { |
| 338 | params.target == SurfaceTarget::Texture3D ? params.GetMipDepth(level) : 1; | 340 | .width = params.GetMipWidth(level), |
| 339 | return copy; | 341 | .height = params.GetMipHeight(level), |
| 342 | .depth = params.target == SurfaceTarget::Texture3D ? params.GetMipDepth(level) : 1U, | ||
| 343 | }, | ||
| 344 | }; | ||
| 340 | } | 345 | } |
| 341 | 346 | ||
| 342 | VkImageSubresourceRange CachedSurface::GetImageSubresourceRange() const { | 347 | VkImageSubresourceRange CachedSurface::GetImageSubresourceRange() const { |
| @@ -380,7 +385,7 @@ VkImageView CachedSurfaceView::GetImageView(SwizzleSource x_source, SwizzleSourc | |||
| 380 | 385 | ||
| 381 | std::array swizzle{MaxwellToVK::SwizzleSource(x_source), MaxwellToVK::SwizzleSource(y_source), | 386 | std::array swizzle{MaxwellToVK::SwizzleSource(x_source), MaxwellToVK::SwizzleSource(y_source), |
| 382 | MaxwellToVK::SwizzleSource(z_source), MaxwellToVK::SwizzleSource(w_source)}; | 387 | MaxwellToVK::SwizzleSource(z_source), MaxwellToVK::SwizzleSource(w_source)}; |
| 383 | if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) { | 388 | if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5_UNORM) { |
| 384 | // A1B5G5R5 is implemented as A1R5G5B5, we have to change the swizzle here. | 389 | // A1B5G5R5 is implemented as A1R5G5B5, we have to change the swizzle here. |
| 385 | std::swap(swizzle[0], swizzle[2]); | 390 | std::swap(swizzle[0], swizzle[2]); |
| 386 | } | 391 | } |
| @@ -392,11 +397,11 @@ VkImageView CachedSurfaceView::GetImageView(SwizzleSource x_source, SwizzleSourc | |||
| 392 | UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G); | 397 | UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G); |
| 393 | const bool is_first = x_source == SwizzleSource::R; | 398 | const bool is_first = x_source == SwizzleSource::R; |
| 394 | switch (params.pixel_format) { | 399 | switch (params.pixel_format) { |
| 395 | case VideoCore::Surface::PixelFormat::Z24S8: | 400 | case VideoCore::Surface::PixelFormat::D24_UNORM_S8_UINT: |
| 396 | case VideoCore::Surface::PixelFormat::Z32FS8: | 401 | case VideoCore::Surface::PixelFormat::D32_FLOAT_S8_UINT: |
| 397 | aspect = is_first ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT; | 402 | aspect = is_first ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT; |
| 398 | break; | 403 | break; |
| 399 | case VideoCore::Surface::PixelFormat::S8Z24: | 404 | case VideoCore::Surface::PixelFormat::S8_UINT_D24_UNORM: |
| 400 | aspect = is_first ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; | 405 | aspect = is_first ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; |
| 401 | break; | 406 | break; |
| 402 | default: | 407 | default: |
| @@ -416,20 +421,29 @@ VkImageView CachedSurfaceView::GetImageView(SwizzleSource x_source, SwizzleSourc | |||
| 416 | ASSERT(num_slices == params.depth); | 421 | ASSERT(num_slices == params.depth); |
| 417 | } | 422 | } |
| 418 | 423 | ||
| 419 | VkImageViewCreateInfo ci; | 424 | image_view = device.GetLogical().CreateImageView({ |
| 420 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; | 425 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| 421 | ci.pNext = nullptr; | 426 | .pNext = nullptr, |
| 422 | ci.flags = 0; | 427 | .flags = 0, |
| 423 | ci.image = surface.GetImageHandle(); | 428 | .image = surface.GetImageHandle(), |
| 424 | ci.viewType = image_view_type; | 429 | .viewType = image_view_type, |
| 425 | ci.format = surface.GetImage().GetFormat(); | 430 | .format = surface.GetImage().GetFormat(), |
| 426 | ci.components = {swizzle[0], swizzle[1], swizzle[2], swizzle[3]}; | 431 | .components = |
| 427 | ci.subresourceRange.aspectMask = aspect; | 432 | { |
| 428 | ci.subresourceRange.baseMipLevel = base_level; | 433 | .r = swizzle[0], |
| 429 | ci.subresourceRange.levelCount = num_levels; | 434 | .g = swizzle[1], |
| 430 | ci.subresourceRange.baseArrayLayer = base_layer; | 435 | .b = swizzle[2], |
| 431 | ci.subresourceRange.layerCount = num_layers; | 436 | .a = swizzle[3], |
| 432 | image_view = device.GetLogical().CreateImageView(ci); | 437 | }, |
| 438 | .subresourceRange = | ||
| 439 | { | ||
| 440 | .aspectMask = aspect, | ||
| 441 | .baseMipLevel = base_level, | ||
| 442 | .levelCount = num_levels, | ||
| 443 | .baseArrayLayer = base_layer, | ||
| 444 | .layerCount = num_layers, | ||
| 445 | }, | ||
| 446 | }); | ||
| 433 | 447 | ||
| 434 | return last_image_view = *image_view; | 448 | return last_image_view = *image_view; |
| 435 | } | 449 | } |
| @@ -439,17 +453,26 @@ VkImageView CachedSurfaceView::GetAttachment() { | |||
| 439 | return *render_target; | 453 | return *render_target; |
| 440 | } | 454 | } |
| 441 | 455 | ||
| 442 | VkImageViewCreateInfo ci; | 456 | VkImageViewCreateInfo ci{ |
| 443 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; | 457 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| 444 | ci.pNext = nullptr; | 458 | .pNext = nullptr, |
| 445 | ci.flags = 0; | 459 | .flags = 0, |
| 446 | ci.image = surface.GetImageHandle(); | 460 | .image = surface.GetImageHandle(), |
| 447 | ci.format = surface.GetImage().GetFormat(); | 461 | .format = surface.GetImage().GetFormat(), |
| 448 | ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, | 462 | .components = |
| 449 | VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; | 463 | { |
| 450 | ci.subresourceRange.aspectMask = aspect_mask; | 464 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 451 | ci.subresourceRange.baseMipLevel = base_level; | 465 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 452 | ci.subresourceRange.levelCount = num_levels; | 466 | .b = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 467 | .a = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 468 | }, | ||
| 469 | .subresourceRange = | ||
| 470 | { | ||
| 471 | .aspectMask = aspect_mask, | ||
| 472 | .baseMipLevel = base_level, | ||
| 473 | .levelCount = num_levels, | ||
| 474 | }, | ||
| 475 | }; | ||
| 453 | if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) { | 476 | if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) { |
| 454 | ci.viewType = num_slices > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D; | 477 | ci.viewType = num_slices > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D; |
| 455 | ci.subresourceRange.baseArrayLayer = base_slice; | 478 | ci.subresourceRange.baseArrayLayer = base_slice; |
| @@ -502,24 +525,40 @@ void VKTextureCache::ImageCopy(Surface& src_surface, Surface& dst_surface, | |||
| 502 | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, | 525 | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, |
| 503 | VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); | 526 | VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); |
| 504 | 527 | ||
| 505 | VkImageCopy copy; | 528 | const VkImageCopy copy{ |
| 506 | copy.srcSubresource.aspectMask = src_surface->GetAspectMask(); | 529 | .srcSubresource = |
| 507 | copy.srcSubresource.mipLevel = copy_params.source_level; | 530 | { |
| 508 | copy.srcSubresource.baseArrayLayer = copy_params.source_z; | 531 | .aspectMask = src_surface->GetAspectMask(), |
| 509 | copy.srcSubresource.layerCount = num_layers; | 532 | .mipLevel = copy_params.source_level, |
| 510 | copy.srcOffset.x = copy_params.source_x; | 533 | .baseArrayLayer = copy_params.source_z, |
| 511 | copy.srcOffset.y = copy_params.source_y; | 534 | .layerCount = num_layers, |
| 512 | copy.srcOffset.z = 0; | 535 | }, |
| 513 | copy.dstSubresource.aspectMask = dst_surface->GetAspectMask(); | 536 | .srcOffset = |
| 514 | copy.dstSubresource.mipLevel = copy_params.dest_level; | 537 | { |
| 515 | copy.dstSubresource.baseArrayLayer = dst_base_layer; | 538 | .x = static_cast<s32>(copy_params.source_x), |
| 516 | copy.dstSubresource.layerCount = num_layers; | 539 | .y = static_cast<s32>(copy_params.source_y), |
| 517 | copy.dstOffset.x = copy_params.dest_x; | 540 | .z = 0, |
| 518 | copy.dstOffset.y = copy_params.dest_y; | 541 | }, |
| 519 | copy.dstOffset.z = dst_offset_z; | 542 | .dstSubresource = |
| 520 | copy.extent.width = copy_params.width; | 543 | { |
| 521 | copy.extent.height = copy_params.height; | 544 | .aspectMask = dst_surface->GetAspectMask(), |
| 522 | copy.extent.depth = extent_z; | 545 | .mipLevel = copy_params.dest_level, |
| 546 | .baseArrayLayer = dst_base_layer, | ||
| 547 | .layerCount = num_layers, | ||
| 548 | }, | ||
| 549 | .dstOffset = | ||
| 550 | { | ||
| 551 | .x = static_cast<s32>(copy_params.dest_x), | ||
| 552 | .y = static_cast<s32>(copy_params.dest_y), | ||
| 553 | .z = static_cast<s32>(dst_offset_z), | ||
| 554 | }, | ||
| 555 | .extent = | ||
| 556 | { | ||
| 557 | .width = copy_params.width, | ||
| 558 | .height = copy_params.height, | ||
| 559 | .depth = extent_z, | ||
| 560 | }, | ||
| 561 | }; | ||
| 523 | 562 | ||
| 524 | const VkImage src_image = src_surface->GetImageHandle(); | 563 | const VkImage src_image = src_surface->GetImageHandle(); |
| 525 | const VkImage dst_image = dst_surface->GetImageHandle(); | 564 | const VkImage dst_image = dst_surface->GetImageHandle(); |
diff --git a/src/video_core/renderer_vulkan/wrapper.cpp b/src/video_core/renderer_vulkan/wrapper.cpp index 051298cc8..14cac38ea 100644 --- a/src/video_core/renderer_vulkan/wrapper.cpp +++ b/src/video_core/renderer_vulkan/wrapper.cpp | |||
| @@ -377,24 +377,26 @@ VkResult Free(VkDevice device, VkCommandPool handle, Span<VkCommandBuffer> buffe | |||
| 377 | 377 | ||
| 378 | Instance Instance::Create(Span<const char*> layers, Span<const char*> extensions, | 378 | Instance Instance::Create(Span<const char*> layers, Span<const char*> extensions, |
| 379 | InstanceDispatch& dld) noexcept { | 379 | InstanceDispatch& dld) noexcept { |
| 380 | VkApplicationInfo application_info; | 380 | static constexpr VkApplicationInfo application_info{ |
| 381 | application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; | 381 | .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, |
| 382 | application_info.pNext = nullptr; | 382 | .pNext = nullptr, |
| 383 | application_info.pApplicationName = "yuzu Emulator"; | 383 | .pApplicationName = "yuzu Emulator", |
| 384 | application_info.applicationVersion = VK_MAKE_VERSION(0, 1, 0); | 384 | .applicationVersion = VK_MAKE_VERSION(0, 1, 0), |
| 385 | application_info.pEngineName = "yuzu Emulator"; | 385 | .pEngineName = "yuzu Emulator", |
| 386 | application_info.engineVersion = VK_MAKE_VERSION(0, 1, 0); | 386 | .engineVersion = VK_MAKE_VERSION(0, 1, 0), |
| 387 | application_info.apiVersion = VK_API_VERSION_1_1; | 387 | .apiVersion = VK_API_VERSION_1_1, |
| 388 | 388 | }; | |
| 389 | VkInstanceCreateInfo ci; | 389 | |
| 390 | ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; | 390 | const VkInstanceCreateInfo ci{ |
| 391 | ci.pNext = nullptr; | 391 | .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, |
| 392 | ci.flags = 0; | 392 | .pNext = nullptr, |
| 393 | ci.pApplicationInfo = &application_info; | 393 | .flags = 0, |
| 394 | ci.enabledLayerCount = layers.size(); | 394 | .pApplicationInfo = &application_info, |
| 395 | ci.ppEnabledLayerNames = layers.data(); | 395 | .enabledLayerCount = layers.size(), |
| 396 | ci.enabledExtensionCount = extensions.size(); | 396 | .ppEnabledLayerNames = layers.data(), |
| 397 | ci.ppEnabledExtensionNames = extensions.data(); | 397 | .enabledExtensionCount = extensions.size(), |
| 398 | .ppEnabledExtensionNames = extensions.data(), | ||
| 399 | }; | ||
| 398 | 400 | ||
| 399 | VkInstance instance; | 401 | VkInstance instance; |
| 400 | if (dld.vkCreateInstance(&ci, nullptr, &instance) != VK_SUCCESS) { | 402 | if (dld.vkCreateInstance(&ci, nullptr, &instance) != VK_SUCCESS) { |
| @@ -425,19 +427,20 @@ std::optional<std::vector<VkPhysicalDevice>> Instance::EnumeratePhysicalDevices( | |||
| 425 | 427 | ||
| 426 | DebugCallback Instance::TryCreateDebugCallback( | 428 | DebugCallback Instance::TryCreateDebugCallback( |
| 427 | PFN_vkDebugUtilsMessengerCallbackEXT callback) noexcept { | 429 | PFN_vkDebugUtilsMessengerCallbackEXT callback) noexcept { |
| 428 | VkDebugUtilsMessengerCreateInfoEXT ci; | 430 | const VkDebugUtilsMessengerCreateInfoEXT ci{ |
| 429 | ci.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; | 431 | .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, |
| 430 | ci.pNext = nullptr; | 432 | .pNext = nullptr, |
| 431 | ci.flags = 0; | 433 | .flags = 0, |
| 432 | ci.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | | 434 | .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | |
| 433 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | | 435 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | |
| 434 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | | 436 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | |
| 435 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT; | 437 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, |
| 436 | ci.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | | 438 | .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | |
| 437 | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | | 439 | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | |
| 438 | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; | 440 | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, |
| 439 | ci.pfnUserCallback = callback; | 441 | .pfnUserCallback = callback, |
| 440 | ci.pUserData = nullptr; | 442 | .pUserData = nullptr, |
| 443 | }; | ||
| 441 | 444 | ||
| 442 | VkDebugUtilsMessengerEXT messenger; | 445 | VkDebugUtilsMessengerEXT messenger; |
| 443 | if (dld->vkCreateDebugUtilsMessengerEXT(handle, &ci, nullptr, &messenger) != VK_SUCCESS) { | 446 | if (dld->vkCreateDebugUtilsMessengerEXT(handle, &ci, nullptr, &messenger) != VK_SUCCESS) { |
| @@ -468,12 +471,13 @@ DescriptorSets DescriptorPool::Allocate(const VkDescriptorSetAllocateInfo& ai) c | |||
| 468 | } | 471 | } |
| 469 | 472 | ||
| 470 | CommandBuffers CommandPool::Allocate(std::size_t num_buffers, VkCommandBufferLevel level) const { | 473 | CommandBuffers CommandPool::Allocate(std::size_t num_buffers, VkCommandBufferLevel level) const { |
| 471 | VkCommandBufferAllocateInfo ai; | 474 | const VkCommandBufferAllocateInfo ai{ |
| 472 | ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; | 475 | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, |
| 473 | ai.pNext = nullptr; | 476 | .pNext = nullptr, |
| 474 | ai.commandPool = handle; | 477 | .commandPool = handle, |
| 475 | ai.level = level; | 478 | .level = level, |
| 476 | ai.commandBufferCount = static_cast<u32>(num_buffers); | 479 | .commandBufferCount = static_cast<u32>(num_buffers), |
| 480 | }; | ||
| 477 | 481 | ||
| 478 | std::unique_ptr buffers = std::make_unique<VkCommandBuffer[]>(num_buffers); | 482 | std::unique_ptr buffers = std::make_unique<VkCommandBuffer[]>(num_buffers); |
| 479 | switch (const VkResult result = dld->vkAllocateCommandBuffers(owner, &ai, buffers.get())) { | 483 | switch (const VkResult result = dld->vkAllocateCommandBuffers(owner, &ai, buffers.get())) { |
| @@ -497,17 +501,18 @@ std::vector<VkImage> SwapchainKHR::GetImages() const { | |||
| 497 | Device Device::Create(VkPhysicalDevice physical_device, Span<VkDeviceQueueCreateInfo> queues_ci, | 501 | Device Device::Create(VkPhysicalDevice physical_device, Span<VkDeviceQueueCreateInfo> queues_ci, |
| 498 | Span<const char*> enabled_extensions, const void* next, | 502 | Span<const char*> enabled_extensions, const void* next, |
| 499 | DeviceDispatch& dld) noexcept { | 503 | DeviceDispatch& dld) noexcept { |
| 500 | VkDeviceCreateInfo ci; | 504 | const VkDeviceCreateInfo ci{ |
| 501 | ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; | 505 | .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, |
| 502 | ci.pNext = next; | 506 | .pNext = next, |
| 503 | ci.flags = 0; | 507 | .flags = 0, |
| 504 | ci.queueCreateInfoCount = queues_ci.size(); | 508 | .queueCreateInfoCount = queues_ci.size(), |
| 505 | ci.pQueueCreateInfos = queues_ci.data(); | 509 | .pQueueCreateInfos = queues_ci.data(), |
| 506 | ci.enabledLayerCount = 0; | 510 | .enabledLayerCount = 0, |
| 507 | ci.ppEnabledLayerNames = nullptr; | 511 | .ppEnabledLayerNames = nullptr, |
| 508 | ci.enabledExtensionCount = enabled_extensions.size(); | 512 | .enabledExtensionCount = enabled_extensions.size(), |
| 509 | ci.ppEnabledExtensionNames = enabled_extensions.data(); | 513 | .ppEnabledExtensionNames = enabled_extensions.data(), |
| 510 | ci.pEnabledFeatures = nullptr; | 514 | .pEnabledFeatures = nullptr, |
| 515 | }; | ||
| 511 | 516 | ||
| 512 | VkDevice device; | 517 | VkDevice device; |
| 513 | if (dld.vkCreateDevice(physical_device, &ci, nullptr, &device) != VK_SUCCESS) { | 518 | if (dld.vkCreateDevice(physical_device, &ci, nullptr, &device) != VK_SUCCESS) { |
| @@ -548,10 +553,11 @@ ImageView Device::CreateImageView(const VkImageViewCreateInfo& ci) const { | |||
| 548 | } | 553 | } |
| 549 | 554 | ||
| 550 | Semaphore Device::CreateSemaphore() const { | 555 | Semaphore Device::CreateSemaphore() const { |
| 551 | VkSemaphoreCreateInfo ci; | 556 | static constexpr VkSemaphoreCreateInfo ci{ |
| 552 | ci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; | 557 | .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, |
| 553 | ci.pNext = nullptr; | 558 | .pNext = nullptr, |
| 554 | ci.flags = 0; | 559 | .flags = 0, |
| 560 | }; | ||
| 555 | 561 | ||
| 556 | VkSemaphore object; | 562 | VkSemaphore object; |
| 557 | Check(dld->vkCreateSemaphore(handle, &ci, nullptr, &object)); | 563 | Check(dld->vkCreateSemaphore(handle, &ci, nullptr, &object)); |
| @@ -639,10 +645,12 @@ ShaderModule Device::CreateShaderModule(const VkShaderModuleCreateInfo& ci) cons | |||
| 639 | } | 645 | } |
| 640 | 646 | ||
| 641 | Event Device::CreateEvent() const { | 647 | Event Device::CreateEvent() const { |
| 642 | VkEventCreateInfo ci; | 648 | static constexpr VkEventCreateInfo ci{ |
| 643 | ci.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; | 649 | .sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, |
| 644 | ci.pNext = nullptr; | 650 | .pNext = nullptr, |
| 645 | ci.flags = 0; | 651 | .flags = 0, |
| 652 | }; | ||
| 653 | |||
| 646 | VkEvent object; | 654 | VkEvent object; |
| 647 | Check(dld->vkCreateEvent(handle, &ci, nullptr, &object)); | 655 | Check(dld->vkCreateEvent(handle, &ci, nullptr, &object)); |
| 648 | return Event(object, handle, *dld); | 656 | return Event(object, handle, *dld); |
diff --git a/src/video_core/shader/async_shaders.cpp b/src/video_core/shader/async_shaders.cpp new file mode 100644 index 000000000..b7f66d7ee --- /dev/null +++ b/src/video_core/shader/async_shaders.cpp | |||
| @@ -0,0 +1,181 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <chrono> | ||
| 6 | #include <condition_variable> | ||
| 7 | #include <mutex> | ||
| 8 | #include <thread> | ||
| 9 | #include <vector> | ||
| 10 | #include "video_core/engines/maxwell_3d.h" | ||
| 11 | #include "video_core/renderer_base.h" | ||
| 12 | #include "video_core/renderer_opengl/gl_shader_cache.h" | ||
| 13 | #include "video_core/shader/async_shaders.h" | ||
| 14 | |||
| 15 | namespace VideoCommon::Shader { | ||
| 16 | |||
| 17 | AsyncShaders::AsyncShaders(Core::Frontend::EmuWindow& emu_window) : emu_window(emu_window) {} | ||
| 18 | |||
| 19 | AsyncShaders::~AsyncShaders() { | ||
| 20 | KillWorkers(); | ||
| 21 | } | ||
| 22 | |||
| 23 | void AsyncShaders::AllocateWorkers(std::size_t num_workers) { | ||
| 24 | // If we're already have workers queued or don't want to queue workers, ignore | ||
| 25 | if (num_workers == worker_threads.size() || num_workers == 0) { | ||
| 26 | return; | ||
| 27 | } | ||
| 28 | |||
| 29 | // If workers already exist, clear them | ||
| 30 | if (!worker_threads.empty()) { | ||
| 31 | FreeWorkers(); | ||
| 32 | } | ||
| 33 | |||
| 34 | // Create workers | ||
| 35 | for (std::size_t i = 0; i < num_workers; i++) { | ||
| 36 | context_list.push_back(emu_window.CreateSharedContext()); | ||
| 37 | worker_threads.push_back(std::move( | ||
| 38 | std::thread(&AsyncShaders::ShaderCompilerThread, this, context_list[i].get()))); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | void AsyncShaders::FreeWorkers() { | ||
| 43 | // Mark all threads to quit | ||
| 44 | is_thread_exiting.store(true); | ||
| 45 | cv.notify_all(); | ||
| 46 | for (auto& thread : worker_threads) { | ||
| 47 | thread.join(); | ||
| 48 | } | ||
| 49 | // Clear our shared contexts | ||
| 50 | context_list.clear(); | ||
| 51 | |||
| 52 | // Clear our worker threads | ||
| 53 | worker_threads.clear(); | ||
| 54 | } | ||
| 55 | |||
| 56 | void AsyncShaders::KillWorkers() { | ||
| 57 | is_thread_exiting.store(true); | ||
| 58 | for (auto& thread : worker_threads) { | ||
| 59 | thread.detach(); | ||
| 60 | } | ||
| 61 | // Clear our shared contexts | ||
| 62 | context_list.clear(); | ||
| 63 | |||
| 64 | // Clear our worker threads | ||
| 65 | worker_threads.clear(); | ||
| 66 | } | ||
| 67 | |||
| 68 | bool AsyncShaders::HasWorkQueued() { | ||
| 69 | return !pending_queue.empty(); | ||
| 70 | } | ||
| 71 | |||
| 72 | bool AsyncShaders::HasCompletedWork() { | ||
| 73 | std::shared_lock lock{completed_mutex}; | ||
| 74 | return !finished_work.empty(); | ||
| 75 | } | ||
| 76 | |||
| 77 | bool AsyncShaders::IsShaderAsync(const Tegra::GPU& gpu) const { | ||
| 78 | const auto& regs = gpu.Maxwell3D().regs; | ||
| 79 | |||
| 80 | // If something is using depth, we can assume that games are not rendering anything which will | ||
| 81 | // be used one time. | ||
| 82 | if (regs.zeta_enable) { | ||
| 83 | return true; | ||
| 84 | } | ||
| 85 | |||
| 86 | // If games are using a small index count, we can assume these are full screen quads. Usually | ||
| 87 | // these shaders are only used once for building textures so we can assume they can't be built | ||
| 88 | // async | ||
| 89 | if (regs.index_array.count <= 6 || regs.vertex_buffer.count <= 6) { | ||
| 90 | return false; | ||
| 91 | } | ||
| 92 | |||
| 93 | return true; | ||
| 94 | } | ||
| 95 | |||
| 96 | std::vector<AsyncShaders::Result> AsyncShaders::GetCompletedWork() { | ||
| 97 | std::vector<AsyncShaders::Result> results; | ||
| 98 | { | ||
| 99 | std::unique_lock lock{completed_mutex}; | ||
| 100 | results.assign(std::make_move_iterator(finished_work.begin()), | ||
| 101 | std::make_move_iterator(finished_work.end())); | ||
| 102 | finished_work.clear(); | ||
| 103 | } | ||
| 104 | return results; | ||
| 105 | } | ||
| 106 | |||
| 107 | void AsyncShaders::QueueOpenGLShader(const OpenGL::Device& device, | ||
| 108 | Tegra::Engines::ShaderType shader_type, u64 uid, | ||
| 109 | std::vector<u64> code, std::vector<u64> code_b, | ||
| 110 | u32 main_offset, | ||
| 111 | VideoCommon::Shader::CompilerSettings compiler_settings, | ||
| 112 | const VideoCommon::Shader::Registry& registry, | ||
| 113 | VAddr cpu_addr) { | ||
| 114 | WorkerParams params{device.UseAssemblyShaders() ? AsyncShaders::Backend::GLASM | ||
| 115 | : AsyncShaders::Backend::OpenGL, | ||
| 116 | device, | ||
| 117 | shader_type, | ||
| 118 | uid, | ||
| 119 | std::move(code), | ||
| 120 | std::move(code_b), | ||
| 121 | main_offset, | ||
| 122 | compiler_settings, | ||
| 123 | registry, | ||
| 124 | cpu_addr}; | ||
| 125 | std::unique_lock lock(queue_mutex); | ||
| 126 | pending_queue.push_back(std::move(params)); | ||
| 127 | cv.notify_one(); | ||
| 128 | } | ||
| 129 | |||
| 130 | void AsyncShaders::ShaderCompilerThread(Core::Frontend::GraphicsContext* context) { | ||
| 131 | using namespace std::chrono_literals; | ||
| 132 | while (!is_thread_exiting.load(std::memory_order_relaxed)) { | ||
| 133 | std::unique_lock lock{queue_mutex}; | ||
| 134 | cv.wait(lock, [this] { return HasWorkQueued() || is_thread_exiting; }); | ||
| 135 | if (is_thread_exiting) { | ||
| 136 | return; | ||
| 137 | } | ||
| 138 | |||
| 139 | // Partial lock to allow all threads to read at the same time | ||
| 140 | if (!HasWorkQueued()) { | ||
| 141 | continue; | ||
| 142 | } | ||
| 143 | // Another thread beat us, just unlock and wait for the next load | ||
| 144 | if (pending_queue.empty()) { | ||
| 145 | continue; | ||
| 146 | } | ||
| 147 | // Pull work from queue | ||
| 148 | WorkerParams work = std::move(pending_queue.front()); | ||
| 149 | pending_queue.pop_front(); | ||
| 150 | |||
| 151 | lock.unlock(); | ||
| 152 | |||
| 153 | if (work.backend == AsyncShaders::Backend::OpenGL || | ||
| 154 | work.backend == AsyncShaders::Backend::GLASM) { | ||
| 155 | const ShaderIR ir(work.code, work.main_offset, work.compiler_settings, work.registry); | ||
| 156 | const auto scope = context->Acquire(); | ||
| 157 | auto program = | ||
| 158 | OpenGL::BuildShader(work.device, work.shader_type, work.uid, ir, work.registry); | ||
| 159 | Result result{}; | ||
| 160 | result.backend = work.backend; | ||
| 161 | result.cpu_address = work.cpu_address; | ||
| 162 | result.uid = work.uid; | ||
| 163 | result.code = std::move(work.code); | ||
| 164 | result.code_b = std::move(work.code_b); | ||
| 165 | result.shader_type = work.shader_type; | ||
| 166 | |||
| 167 | if (work.backend == AsyncShaders::Backend::OpenGL) { | ||
| 168 | result.program.opengl = std::move(program->source_program); | ||
| 169 | } else if (work.backend == AsyncShaders::Backend::GLASM) { | ||
| 170 | result.program.glasm = std::move(program->assembly_program); | ||
| 171 | } | ||
| 172 | |||
| 173 | { | ||
| 174 | std::unique_lock complete_lock(completed_mutex); | ||
| 175 | finished_work.push_back(std::move(result)); | ||
| 176 | } | ||
| 177 | } | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | } // namespace VideoCommon::Shader | ||
diff --git a/src/video_core/shader/async_shaders.h b/src/video_core/shader/async_shaders.h new file mode 100644 index 000000000..2f5ee94ad --- /dev/null +++ b/src/video_core/shader/async_shaders.h | |||
| @@ -0,0 +1,109 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <condition_variable> | ||
| 8 | #include <deque> | ||
| 9 | #include <memory> | ||
| 10 | #include <shared_mutex> | ||
| 11 | #include <thread> | ||
| 12 | #include "common/bit_field.h" | ||
| 13 | #include "common/common_types.h" | ||
| 14 | #include "video_core/renderer_opengl/gl_device.h" | ||
| 15 | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||
| 16 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" | ||
| 17 | |||
| 18 | namespace Core::Frontend { | ||
| 19 | class EmuWindow; | ||
| 20 | class GraphicsContext; | ||
| 21 | } // namespace Core::Frontend | ||
| 22 | |||
| 23 | namespace Tegra { | ||
| 24 | class GPU; | ||
| 25 | } | ||
| 26 | |||
| 27 | namespace VideoCommon::Shader { | ||
| 28 | |||
| 29 | class AsyncShaders { | ||
| 30 | public: | ||
| 31 | enum class Backend { | ||
| 32 | OpenGL, | ||
| 33 | GLASM, | ||
| 34 | }; | ||
| 35 | |||
| 36 | struct ResultPrograms { | ||
| 37 | OpenGL::OGLProgram opengl; | ||
| 38 | OpenGL::OGLAssemblyProgram glasm; | ||
| 39 | }; | ||
| 40 | |||
| 41 | struct Result { | ||
| 42 | u64 uid; | ||
| 43 | VAddr cpu_address; | ||
| 44 | Backend backend; | ||
| 45 | ResultPrograms program; | ||
| 46 | std::vector<u64> code; | ||
| 47 | std::vector<u64> code_b; | ||
| 48 | Tegra::Engines::ShaderType shader_type; | ||
| 49 | }; | ||
| 50 | |||
| 51 | explicit AsyncShaders(Core::Frontend::EmuWindow& emu_window); | ||
| 52 | ~AsyncShaders(); | ||
| 53 | |||
| 54 | /// Start up shader worker threads | ||
| 55 | void AllocateWorkers(std::size_t num_workers); | ||
| 56 | |||
| 57 | /// Clear the shader queue and kill all worker threads | ||
| 58 | void FreeWorkers(); | ||
| 59 | |||
| 60 | // Force end all threads | ||
| 61 | void KillWorkers(); | ||
| 62 | |||
| 63 | /// Check to see if any shaders have actually been compiled | ||
| 64 | bool HasCompletedWork(); | ||
| 65 | |||
| 66 | /// Deduce if a shader can be build on another thread of MUST be built in sync. We cannot build | ||
| 67 | /// every shader async as some shaders are only built and executed once. We try to "guess" which | ||
| 68 | /// shader would be used only once | ||
| 69 | bool IsShaderAsync(const Tegra::GPU& gpu) const; | ||
| 70 | |||
| 71 | /// Pulls completed compiled shaders | ||
| 72 | std::vector<Result> GetCompletedWork(); | ||
| 73 | |||
| 74 | void QueueOpenGLShader(const OpenGL::Device& device, Tegra::Engines::ShaderType shader_type, | ||
| 75 | u64 uid, std::vector<u64> code, std::vector<u64> code_b, u32 main_offset, | ||
| 76 | VideoCommon::Shader::CompilerSettings compiler_settings, | ||
| 77 | const VideoCommon::Shader::Registry& registry, VAddr cpu_addr); | ||
| 78 | |||
| 79 | private: | ||
| 80 | void ShaderCompilerThread(Core::Frontend::GraphicsContext* context); | ||
| 81 | |||
| 82 | /// Check our worker queue to see if we have any work queued already | ||
| 83 | bool HasWorkQueued(); | ||
| 84 | |||
| 85 | struct WorkerParams { | ||
| 86 | AsyncShaders::Backend backend; | ||
| 87 | OpenGL::Device device; | ||
| 88 | Tegra::Engines::ShaderType shader_type; | ||
| 89 | u64 uid; | ||
| 90 | std::vector<u64> code; | ||
| 91 | std::vector<u64> code_b; | ||
| 92 | u32 main_offset; | ||
| 93 | VideoCommon::Shader::CompilerSettings compiler_settings; | ||
| 94 | VideoCommon::Shader::Registry registry; | ||
| 95 | VAddr cpu_address; | ||
| 96 | }; | ||
| 97 | |||
| 98 | std::condition_variable cv; | ||
| 99 | std::mutex queue_mutex; | ||
| 100 | std::shared_mutex completed_mutex; | ||
| 101 | std::atomic<bool> is_thread_exiting{}; | ||
| 102 | std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> context_list; | ||
| 103 | std::vector<std::thread> worker_threads; | ||
| 104 | std::deque<WorkerParams> pending_queue; | ||
| 105 | std::vector<AsyncShaders::Result> finished_work; | ||
| 106 | Core::Frontend::EmuWindow& emu_window; | ||
| 107 | }; | ||
| 108 | |||
| 109 | } // namespace VideoCommon::Shader | ||
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp index 07778dc3e..e75ca4fdb 100644 --- a/src/video_core/shader/decode/image.cpp +++ b/src/video_core/shader/decode/image.cpp | |||
| @@ -31,11 +31,11 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor, | |||
| 31 | std::size_t component) { | 31 | std::size_t component) { |
| 32 | const TextureFormat format{descriptor.format}; | 32 | const TextureFormat format{descriptor.format}; |
| 33 | switch (format) { | 33 | switch (format) { |
| 34 | case TextureFormat::R16_G16_B16_A16: | 34 | case TextureFormat::R16G16B16A16: |
| 35 | case TextureFormat::R32_G32_B32_A32: | 35 | case TextureFormat::R32G32B32A32: |
| 36 | case TextureFormat::R32_G32_B32: | 36 | case TextureFormat::R32G32B32: |
| 37 | case TextureFormat::R32_G32: | 37 | case TextureFormat::R32G32: |
| 38 | case TextureFormat::R16_G16: | 38 | case TextureFormat::R16G16: |
| 39 | case TextureFormat::R32: | 39 | case TextureFormat::R32: |
| 40 | case TextureFormat::R16: | 40 | case TextureFormat::R16: |
| 41 | case TextureFormat::R8: | 41 | case TextureFormat::R8: |
| @@ -97,7 +97,7 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor, | |||
| 97 | break; | 97 | break; |
| 98 | case TextureFormat::B5G6R5: | 98 | case TextureFormat::B5G6R5: |
| 99 | case TextureFormat::B6G5R5: | 99 | case TextureFormat::B6G5R5: |
| 100 | case TextureFormat::BF10GF11RF11: | 100 | case TextureFormat::B10G11R11: |
| 101 | if (component == 0) { | 101 | if (component == 0) { |
| 102 | return descriptor.b_type; | 102 | return descriptor.b_type; |
| 103 | } | 103 | } |
| @@ -108,9 +108,9 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor, | |||
| 108 | return descriptor.r_type; | 108 | return descriptor.r_type; |
| 109 | } | 109 | } |
| 110 | break; | 110 | break; |
| 111 | case TextureFormat::G8R24: | 111 | case TextureFormat::R24G8: |
| 112 | case TextureFormat::G24R8: | 112 | case TextureFormat::R8G24: |
| 113 | case TextureFormat::G8R8: | 113 | case TextureFormat::R8G8: |
| 114 | case TextureFormat::G4R4: | 114 | case TextureFormat::G4R4: |
| 115 | if (component == 0) { | 115 | if (component == 0) { |
| 116 | return descriptor.g_type; | 116 | return descriptor.g_type; |
| @@ -137,15 +137,15 @@ bool IsComponentEnabled(std::size_t component_mask, std::size_t component) { | |||
| 137 | 137 | ||
| 138 | u32 GetComponentSize(TextureFormat format, std::size_t component) { | 138 | u32 GetComponentSize(TextureFormat format, std::size_t component) { |
| 139 | switch (format) { | 139 | switch (format) { |
| 140 | case TextureFormat::R32_G32_B32_A32: | 140 | case TextureFormat::R32G32B32A32: |
| 141 | return 32; | 141 | return 32; |
| 142 | case TextureFormat::R16_G16_B16_A16: | 142 | case TextureFormat::R16G16B16A16: |
| 143 | return 16; | 143 | return 16; |
| 144 | case TextureFormat::R32_G32_B32: | 144 | case TextureFormat::R32G32B32: |
| 145 | return component <= 2 ? 32 : 0; | 145 | return component <= 2 ? 32 : 0; |
| 146 | case TextureFormat::R32_G32: | 146 | case TextureFormat::R32G32: |
| 147 | return component <= 1 ? 32 : 0; | 147 | return component <= 1 ? 32 : 0; |
| 148 | case TextureFormat::R16_G16: | 148 | case TextureFormat::R16G16: |
| 149 | return component <= 1 ? 16 : 0; | 149 | return component <= 1 ? 16 : 0; |
| 150 | case TextureFormat::R32: | 150 | case TextureFormat::R32: |
| 151 | return component == 0 ? 32 : 0; | 151 | return component == 0 ? 32 : 0; |
| @@ -192,7 +192,7 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) { | |||
| 192 | return 6; | 192 | return 6; |
| 193 | } | 193 | } |
| 194 | return 0; | 194 | return 0; |
| 195 | case TextureFormat::BF10GF11RF11: | 195 | case TextureFormat::B10G11R11: |
| 196 | if (component == 1 || component == 2) { | 196 | if (component == 1 || component == 2) { |
| 197 | return 11; | 197 | return 11; |
| 198 | } | 198 | } |
| @@ -200,7 +200,7 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) { | |||
| 200 | return 10; | 200 | return 10; |
| 201 | } | 201 | } |
| 202 | return 0; | 202 | return 0; |
| 203 | case TextureFormat::G8R24: | 203 | case TextureFormat::R24G8: |
| 204 | if (component == 0) { | 204 | if (component == 0) { |
| 205 | return 8; | 205 | return 8; |
| 206 | } | 206 | } |
| @@ -208,7 +208,7 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) { | |||
| 208 | return 24; | 208 | return 24; |
| 209 | } | 209 | } |
| 210 | return 0; | 210 | return 0; |
| 211 | case TextureFormat::G24R8: | 211 | case TextureFormat::R8G24: |
| 212 | if (component == 0) { | 212 | if (component == 0) { |
| 213 | return 8; | 213 | return 8; |
| 214 | } | 214 | } |
| @@ -216,7 +216,7 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) { | |||
| 216 | return 24; | 216 | return 24; |
| 217 | } | 217 | } |
| 218 | return 0; | 218 | return 0; |
| 219 | case TextureFormat::G8R8: | 219 | case TextureFormat::R8G8: |
| 220 | return (component == 0 || component == 1) ? 8 : 0; | 220 | return (component == 0 || component == 1) ? 8 : 0; |
| 221 | case TextureFormat::G4R4: | 221 | case TextureFormat::G4R4: |
| 222 | return (component == 0 || component == 1) ? 4 : 0; | 222 | return (component == 0 || component == 1) ? 4 : 0; |
| @@ -231,25 +231,25 @@ std::size_t GetImageComponentMask(TextureFormat format) { | |||
| 231 | constexpr u8 B = 0b0100; | 231 | constexpr u8 B = 0b0100; |
| 232 | constexpr u8 A = 0b1000; | 232 | constexpr u8 A = 0b1000; |
| 233 | switch (format) { | 233 | switch (format) { |
| 234 | case TextureFormat::R32_G32_B32_A32: | 234 | case TextureFormat::R32G32B32A32: |
| 235 | case TextureFormat::R16_G16_B16_A16: | 235 | case TextureFormat::R16G16B16A16: |
| 236 | case TextureFormat::A8R8G8B8: | 236 | case TextureFormat::A8R8G8B8: |
| 237 | case TextureFormat::A2B10G10R10: | 237 | case TextureFormat::A2B10G10R10: |
| 238 | case TextureFormat::A4B4G4R4: | 238 | case TextureFormat::A4B4G4R4: |
| 239 | case TextureFormat::A5B5G5R1: | 239 | case TextureFormat::A5B5G5R1: |
| 240 | case TextureFormat::A1B5G5R5: | 240 | case TextureFormat::A1B5G5R5: |
| 241 | return std::size_t{R | G | B | A}; | 241 | return std::size_t{R | G | B | A}; |
| 242 | case TextureFormat::R32_G32_B32: | 242 | case TextureFormat::R32G32B32: |
| 243 | case TextureFormat::R32_B24G8: | 243 | case TextureFormat::R32_B24G8: |
| 244 | case TextureFormat::B5G6R5: | 244 | case TextureFormat::B5G6R5: |
| 245 | case TextureFormat::B6G5R5: | 245 | case TextureFormat::B6G5R5: |
| 246 | case TextureFormat::BF10GF11RF11: | 246 | case TextureFormat::B10G11R11: |
| 247 | return std::size_t{R | G | B}; | 247 | return std::size_t{R | G | B}; |
| 248 | case TextureFormat::R32_G32: | 248 | case TextureFormat::R32G32: |
| 249 | case TextureFormat::R16_G16: | 249 | case TextureFormat::R16G16: |
| 250 | case TextureFormat::G8R24: | 250 | case TextureFormat::R24G8: |
| 251 | case TextureFormat::G24R8: | 251 | case TextureFormat::R8G24: |
| 252 | case TextureFormat::G8R8: | 252 | case TextureFormat::R8G8: |
| 253 | case TextureFormat::G4R4: | 253 | case TextureFormat::G4R4: |
| 254 | return std::size_t{R | G}; | 254 | return std::size_t{R | G}; |
| 255 | case TextureFormat::R32: | 255 | case TextureFormat::R32: |
diff --git a/src/video_core/shader_notify.cpp b/src/video_core/shader_notify.cpp new file mode 100644 index 000000000..c3c71657d --- /dev/null +++ b/src/video_core/shader_notify.cpp | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "video_core/shader_notify.h" | ||
| 6 | |||
| 7 | using namespace std::chrono_literals; | ||
| 8 | |||
| 9 | namespace VideoCore { | ||
| 10 | namespace { | ||
| 11 | constexpr auto UPDATE_TICK = 32ms; | ||
| 12 | } | ||
| 13 | |||
| 14 | ShaderNotify::ShaderNotify() = default; | ||
| 15 | ShaderNotify::~ShaderNotify() = default; | ||
| 16 | |||
| 17 | std::size_t ShaderNotify::GetShadersBuilding() { | ||
| 18 | const auto now = std::chrono::high_resolution_clock::now(); | ||
| 19 | const auto diff = now - last_update; | ||
| 20 | if (diff > UPDATE_TICK) { | ||
| 21 | std::shared_lock lock(mutex); | ||
| 22 | last_updated_count = accurate_count; | ||
| 23 | } | ||
| 24 | return last_updated_count; | ||
| 25 | } | ||
| 26 | |||
| 27 | std::size_t ShaderNotify::GetShadersBuildingAccurate() { | ||
| 28 | std::shared_lock lock{mutex}; | ||
| 29 | return accurate_count; | ||
| 30 | } | ||
| 31 | |||
| 32 | void ShaderNotify::MarkShaderComplete() { | ||
| 33 | std::unique_lock lock{mutex}; | ||
| 34 | accurate_count--; | ||
| 35 | } | ||
| 36 | |||
| 37 | void ShaderNotify::MarkSharderBuilding() { | ||
| 38 | std::unique_lock lock{mutex}; | ||
| 39 | accurate_count++; | ||
| 40 | } | ||
| 41 | |||
| 42 | } // namespace VideoCore | ||
diff --git a/src/video_core/shader_notify.h b/src/video_core/shader_notify.h new file mode 100644 index 000000000..a9c92d179 --- /dev/null +++ b/src/video_core/shader_notify.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <chrono> | ||
| 8 | #include <shared_mutex> | ||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | namespace VideoCore { | ||
| 12 | class ShaderNotify { | ||
| 13 | public: | ||
| 14 | ShaderNotify(); | ||
| 15 | ~ShaderNotify(); | ||
| 16 | |||
| 17 | std::size_t GetShadersBuilding(); | ||
| 18 | std::size_t GetShadersBuildingAccurate(); | ||
| 19 | |||
| 20 | void MarkShaderComplete(); | ||
| 21 | void MarkSharderBuilding(); | ||
| 22 | |||
| 23 | private: | ||
| 24 | std::size_t last_updated_count{}; | ||
| 25 | std::size_t accurate_count{}; | ||
| 26 | std::shared_mutex mutex; | ||
| 27 | std::chrono::high_resolution_clock::time_point last_update{}; | ||
| 28 | }; | ||
| 29 | } // namespace VideoCore | ||
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index bbe93903c..1688267bb 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp | |||
| @@ -74,117 +74,131 @@ bool SurfaceTargetIsArray(SurfaceTarget target) { | |||
| 74 | 74 | ||
| 75 | PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { | 75 | PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { |
| 76 | switch (format) { | 76 | switch (format) { |
| 77 | case Tegra::DepthFormat::S8_Z24_UNORM: | 77 | case Tegra::DepthFormat::S8_UINT_Z24_UNORM: |
| 78 | return PixelFormat::S8Z24; | 78 | return PixelFormat::S8_UINT_D24_UNORM; |
| 79 | case Tegra::DepthFormat::Z24_S8_UNORM: | 79 | case Tegra::DepthFormat::D24S8_UNORM: |
| 80 | return PixelFormat::Z24S8; | 80 | return PixelFormat::D24_UNORM_S8_UINT; |
| 81 | case Tegra::DepthFormat::Z32_FLOAT: | 81 | case Tegra::DepthFormat::D32_FLOAT: |
| 82 | return PixelFormat::Z32F; | 82 | return PixelFormat::D32_FLOAT; |
| 83 | case Tegra::DepthFormat::Z16_UNORM: | 83 | case Tegra::DepthFormat::D16_UNORM: |
| 84 | return PixelFormat::Z16; | 84 | return PixelFormat::D16_UNORM; |
| 85 | case Tegra::DepthFormat::Z32_S8_X24_FLOAT: | 85 | case Tegra::DepthFormat::D32_FLOAT_S8X24_UINT: |
| 86 | return PixelFormat::Z32FS8; | 86 | return PixelFormat::D32_FLOAT_S8_UINT; |
| 87 | default: | 87 | default: |
| 88 | LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); | 88 | UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<u32>(format)); |
| 89 | UNREACHABLE(); | 89 | return PixelFormat::S8_UINT_D24_UNORM; |
| 90 | return PixelFormat::S8Z24; | ||
| 91 | } | 90 | } |
| 92 | } | 91 | } |
| 93 | 92 | ||
| 94 | PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { | 93 | PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { |
| 95 | switch (format) { | 94 | switch (format) { |
| 96 | case Tegra::RenderTargetFormat::RGBA8_SRGB: | 95 | case Tegra::RenderTargetFormat::R32B32G32A32_FLOAT: |
| 97 | return PixelFormat::RGBA8_SRGB; | 96 | return PixelFormat::R32G32B32A32_FLOAT; |
| 98 | case Tegra::RenderTargetFormat::RGBA8_UNORM: | 97 | case Tegra::RenderTargetFormat::R32G32B32A32_SINT: |
| 99 | return PixelFormat::ABGR8U; | 98 | return PixelFormat::R32G32B32A32_SINT; |
| 100 | case Tegra::RenderTargetFormat::RGBA8_SNORM: | 99 | case Tegra::RenderTargetFormat::R32G32B32A32_UINT: |
| 101 | return PixelFormat::ABGR8S; | 100 | return PixelFormat::R32G32B32A32_UINT; |
| 102 | case Tegra::RenderTargetFormat::RGBA8_UINT: | 101 | case Tegra::RenderTargetFormat::R16G16B16A16_UNORM: |
| 103 | return PixelFormat::ABGR8UI; | 102 | return PixelFormat::R16G16B16A16_UNORM; |
| 104 | case Tegra::RenderTargetFormat::BGRA8_SRGB: | 103 | case Tegra::RenderTargetFormat::R16G16B16A16_SNORM: |
| 105 | return PixelFormat::BGRA8_SRGB; | 104 | return PixelFormat::R16G16B16A16_SNORM; |
| 106 | case Tegra::RenderTargetFormat::BGRA8_UNORM: | 105 | case Tegra::RenderTargetFormat::R16G16B16A16_SINT: |
| 107 | return PixelFormat::BGRA8; | 106 | return PixelFormat::R16G16B16A16_SINT; |
| 108 | case Tegra::RenderTargetFormat::RGB10_A2_UNORM: | 107 | case Tegra::RenderTargetFormat::R16G16B16A16_UINT: |
| 109 | return PixelFormat::A2B10G10R10U; | 108 | return PixelFormat::R16G16B16A16_UINT; |
| 110 | case Tegra::RenderTargetFormat::RGBA16_FLOAT: | 109 | case Tegra::RenderTargetFormat::R16G16B16A16_FLOAT: |
| 111 | return PixelFormat::RGBA16F; | 110 | return PixelFormat::R16G16B16A16_FLOAT; |
| 112 | case Tegra::RenderTargetFormat::RGBA16_UNORM: | 111 | case Tegra::RenderTargetFormat::R32G32_FLOAT: |
| 113 | return PixelFormat::RGBA16U; | 112 | return PixelFormat::R32G32_FLOAT; |
| 114 | case Tegra::RenderTargetFormat::RGBA16_SNORM: | 113 | case Tegra::RenderTargetFormat::R32G32_SINT: |
| 115 | return PixelFormat::RGBA16S; | 114 | return PixelFormat::R32G32_SINT; |
| 116 | case Tegra::RenderTargetFormat::RGBA16_UINT: | 115 | case Tegra::RenderTargetFormat::R32G32_UINT: |
| 117 | return PixelFormat::RGBA16UI; | 116 | return PixelFormat::R32G32_UINT; |
| 118 | case Tegra::RenderTargetFormat::RGBA32_FLOAT: | 117 | case Tegra::RenderTargetFormat::R16G16B16X16_FLOAT: |
| 119 | return PixelFormat::RGBA32F; | 118 | return PixelFormat::R16G16B16X16_FLOAT; |
| 120 | case Tegra::RenderTargetFormat::RG32_FLOAT: | 119 | case Tegra::RenderTargetFormat::B8G8R8A8_UNORM: |
| 121 | return PixelFormat::RG32F; | 120 | return PixelFormat::B8G8R8A8_UNORM; |
| 122 | case Tegra::RenderTargetFormat::R11G11B10_FLOAT: | 121 | case Tegra::RenderTargetFormat::B8G8R8A8_SRGB: |
| 123 | return PixelFormat::R11FG11FB10F; | 122 | return PixelFormat::B8G8R8A8_SRGB; |
| 124 | case Tegra::RenderTargetFormat::B5G6R5_UNORM: | 123 | case Tegra::RenderTargetFormat::A2B10G10R10_UNORM: |
| 125 | return PixelFormat::B5G6R5U; | 124 | return PixelFormat::A2B10G10R10_UNORM; |
| 126 | case Tegra::RenderTargetFormat::BGR5A1_UNORM: | 125 | case Tegra::RenderTargetFormat::A2B10G10R10_UINT: |
| 127 | return PixelFormat::A1B5G5R5U; | 126 | return PixelFormat::A2B10G10R10_UINT; |
| 128 | case Tegra::RenderTargetFormat::RGBA32_UINT: | 127 | case Tegra::RenderTargetFormat::A8B8G8R8_UNORM: |
| 129 | return PixelFormat::RGBA32UI; | 128 | return PixelFormat::A8B8G8R8_UNORM; |
| 130 | case Tegra::RenderTargetFormat::R8_UNORM: | 129 | case Tegra::RenderTargetFormat::A8B8G8R8_SRGB: |
| 131 | return PixelFormat::R8U; | 130 | return PixelFormat::A8B8G8R8_SRGB; |
| 132 | case Tegra::RenderTargetFormat::R8_UINT: | 131 | case Tegra::RenderTargetFormat::A8B8G8R8_SNORM: |
| 133 | return PixelFormat::R8UI; | 132 | return PixelFormat::A8B8G8R8_SNORM; |
| 134 | case Tegra::RenderTargetFormat::RG16_FLOAT: | 133 | case Tegra::RenderTargetFormat::A8B8G8R8_SINT: |
| 135 | return PixelFormat::RG16F; | 134 | return PixelFormat::A8B8G8R8_SINT; |
| 136 | case Tegra::RenderTargetFormat::RG16_UINT: | 135 | case Tegra::RenderTargetFormat::A8B8G8R8_UINT: |
| 137 | return PixelFormat::RG16UI; | 136 | return PixelFormat::A8B8G8R8_UINT; |
| 138 | case Tegra::RenderTargetFormat::RG16_SINT: | 137 | case Tegra::RenderTargetFormat::R16G16_UNORM: |
| 139 | return PixelFormat::RG16I; | 138 | return PixelFormat::R16G16_UNORM; |
| 140 | case Tegra::RenderTargetFormat::RG16_UNORM: | 139 | case Tegra::RenderTargetFormat::R16G16_SNORM: |
| 141 | return PixelFormat::RG16; | 140 | return PixelFormat::R16G16_SNORM; |
| 142 | case Tegra::RenderTargetFormat::RG16_SNORM: | 141 | case Tegra::RenderTargetFormat::R16G16_SINT: |
| 143 | return PixelFormat::RG16S; | 142 | return PixelFormat::R16G16_SINT; |
| 144 | case Tegra::RenderTargetFormat::RG8_UNORM: | 143 | case Tegra::RenderTargetFormat::R16G16_UINT: |
| 145 | return PixelFormat::RG8U; | 144 | return PixelFormat::R16G16_UINT; |
| 146 | case Tegra::RenderTargetFormat::RG8_SNORM: | 145 | case Tegra::RenderTargetFormat::R16G16_FLOAT: |
| 147 | return PixelFormat::RG8S; | 146 | return PixelFormat::R16G16_FLOAT; |
| 148 | case Tegra::RenderTargetFormat::RG8_UINT: | 147 | case Tegra::RenderTargetFormat::B10G11R11_FLOAT: |
| 149 | return PixelFormat::RG8UI; | 148 | return PixelFormat::B10G11R11_FLOAT; |
| 150 | case Tegra::RenderTargetFormat::R16_FLOAT: | 149 | case Tegra::RenderTargetFormat::R32_SINT: |
| 151 | return PixelFormat::R16F; | 150 | return PixelFormat::R32_SINT; |
| 151 | case Tegra::RenderTargetFormat::R32_UINT: | ||
| 152 | return PixelFormat::R32_UINT; | ||
| 153 | case Tegra::RenderTargetFormat::R32_FLOAT: | ||
| 154 | return PixelFormat::R32_FLOAT; | ||
| 155 | case Tegra::RenderTargetFormat::R5G6B5_UNORM: | ||
| 156 | return PixelFormat::R5G6B5_UNORM; | ||
| 157 | case Tegra::RenderTargetFormat::A1R5G5B5_UNORM: | ||
| 158 | return PixelFormat::A1R5G5B5_UNORM; | ||
| 159 | case Tegra::RenderTargetFormat::R8G8_UNORM: | ||
| 160 | return PixelFormat::R8G8_UNORM; | ||
| 161 | case Tegra::RenderTargetFormat::R8G8_SNORM: | ||
| 162 | return PixelFormat::R8G8_SNORM; | ||
| 163 | case Tegra::RenderTargetFormat::R8G8_SINT: | ||
| 164 | return PixelFormat::R8G8_SINT; | ||
| 165 | case Tegra::RenderTargetFormat::R8G8_UINT: | ||
| 166 | return PixelFormat::R8G8_UINT; | ||
| 152 | case Tegra::RenderTargetFormat::R16_UNORM: | 167 | case Tegra::RenderTargetFormat::R16_UNORM: |
| 153 | return PixelFormat::R16U; | 168 | return PixelFormat::R16_UNORM; |
| 154 | case Tegra::RenderTargetFormat::R16_SNORM: | 169 | case Tegra::RenderTargetFormat::R16_SNORM: |
| 155 | return PixelFormat::R16S; | 170 | return PixelFormat::R16_SNORM; |
| 156 | case Tegra::RenderTargetFormat::R16_UINT: | ||
| 157 | return PixelFormat::R16UI; | ||
| 158 | case Tegra::RenderTargetFormat::R16_SINT: | 171 | case Tegra::RenderTargetFormat::R16_SINT: |
| 159 | return PixelFormat::R16I; | 172 | return PixelFormat::R16_SINT; |
| 160 | case Tegra::RenderTargetFormat::R32_FLOAT: | 173 | case Tegra::RenderTargetFormat::R16_UINT: |
| 161 | return PixelFormat::R32F; | 174 | return PixelFormat::R16_UINT; |
| 162 | case Tegra::RenderTargetFormat::R32_SINT: | 175 | case Tegra::RenderTargetFormat::R16_FLOAT: |
| 163 | return PixelFormat::R32I; | 176 | return PixelFormat::R16_FLOAT; |
| 164 | case Tegra::RenderTargetFormat::R32_UINT: | 177 | case Tegra::RenderTargetFormat::R8_UNORM: |
| 165 | return PixelFormat::R32UI; | 178 | return PixelFormat::R8_UNORM; |
| 166 | case Tegra::RenderTargetFormat::RG32_UINT: | 179 | case Tegra::RenderTargetFormat::R8_SNORM: |
| 167 | return PixelFormat::RG32UI; | 180 | return PixelFormat::R8_SNORM; |
| 168 | case Tegra::RenderTargetFormat::RGBX16_FLOAT: | 181 | case Tegra::RenderTargetFormat::R8_SINT: |
| 169 | return PixelFormat::RGBX16F; | 182 | return PixelFormat::R8_SINT; |
| 183 | case Tegra::RenderTargetFormat::R8_UINT: | ||
| 184 | return PixelFormat::R8_UINT; | ||
| 170 | default: | 185 | default: |
| 171 | LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); | 186 | UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<int>(format)); |
| 172 | UNREACHABLE(); | 187 | return PixelFormat::A8B8G8R8_UNORM; |
| 173 | return PixelFormat::RGBA8_SRGB; | ||
| 174 | } | 188 | } |
| 175 | } | 189 | } |
| 176 | 190 | ||
| 177 | PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) { | 191 | PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) { |
| 178 | switch (format) { | 192 | switch (format) { |
| 179 | case Tegra::FramebufferConfig::PixelFormat::ABGR8: | 193 | case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM: |
| 180 | return PixelFormat::ABGR8U; | 194 | return PixelFormat::A8B8G8R8_UNORM; |
| 181 | case Tegra::FramebufferConfig::PixelFormat::RGB565: | 195 | case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM: |
| 182 | return PixelFormat::B5G6R5U; | 196 | return PixelFormat::R5G6B5_UNORM; |
| 183 | case Tegra::FramebufferConfig::PixelFormat::BGRA8: | 197 | case Tegra::FramebufferConfig::PixelFormat::B8G8R8A8_UNORM: |
| 184 | return PixelFormat::BGRA8; | 198 | return PixelFormat::B8G8R8A8_UNORM; |
| 185 | default: | 199 | default: |
| 186 | UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<u32>(format)); | 200 | UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<u32>(format)); |
| 187 | return PixelFormat::ABGR8U; | 201 | return PixelFormat::A8B8G8R8_UNORM; |
| 188 | } | 202 | } |
| 189 | } | 203 | } |
| 190 | 204 | ||
| @@ -212,27 +226,27 @@ SurfaceType GetFormatType(PixelFormat pixel_format) { | |||
| 212 | 226 | ||
| 213 | bool IsPixelFormatASTC(PixelFormat format) { | 227 | bool IsPixelFormatASTC(PixelFormat format) { |
| 214 | switch (format) { | 228 | switch (format) { |
| 215 | case PixelFormat::ASTC_2D_4X4: | 229 | case PixelFormat::ASTC_2D_4X4_UNORM: |
| 216 | case PixelFormat::ASTC_2D_5X4: | 230 | case PixelFormat::ASTC_2D_5X4_UNORM: |
| 217 | case PixelFormat::ASTC_2D_5X5: | 231 | case PixelFormat::ASTC_2D_5X5_UNORM: |
| 218 | case PixelFormat::ASTC_2D_8X8: | 232 | case PixelFormat::ASTC_2D_8X8_UNORM: |
| 219 | case PixelFormat::ASTC_2D_8X5: | 233 | case PixelFormat::ASTC_2D_8X5_UNORM: |
| 220 | case PixelFormat::ASTC_2D_4X4_SRGB: | 234 | case PixelFormat::ASTC_2D_4X4_SRGB: |
| 221 | case PixelFormat::ASTC_2D_5X4_SRGB: | 235 | case PixelFormat::ASTC_2D_5X4_SRGB: |
| 222 | case PixelFormat::ASTC_2D_5X5_SRGB: | 236 | case PixelFormat::ASTC_2D_5X5_SRGB: |
| 223 | case PixelFormat::ASTC_2D_8X8_SRGB: | 237 | case PixelFormat::ASTC_2D_8X8_SRGB: |
| 224 | case PixelFormat::ASTC_2D_8X5_SRGB: | 238 | case PixelFormat::ASTC_2D_8X5_SRGB: |
| 225 | case PixelFormat::ASTC_2D_10X8: | 239 | case PixelFormat::ASTC_2D_10X8_UNORM: |
| 226 | case PixelFormat::ASTC_2D_10X8_SRGB: | 240 | case PixelFormat::ASTC_2D_10X8_SRGB: |
| 227 | case PixelFormat::ASTC_2D_6X6: | 241 | case PixelFormat::ASTC_2D_6X6_UNORM: |
| 228 | case PixelFormat::ASTC_2D_6X6_SRGB: | 242 | case PixelFormat::ASTC_2D_6X6_SRGB: |
| 229 | case PixelFormat::ASTC_2D_10X10: | 243 | case PixelFormat::ASTC_2D_10X10_UNORM: |
| 230 | case PixelFormat::ASTC_2D_10X10_SRGB: | 244 | case PixelFormat::ASTC_2D_10X10_SRGB: |
| 231 | case PixelFormat::ASTC_2D_12X12: | 245 | case PixelFormat::ASTC_2D_12X12_UNORM: |
| 232 | case PixelFormat::ASTC_2D_12X12_SRGB: | 246 | case PixelFormat::ASTC_2D_12X12_SRGB: |
| 233 | case PixelFormat::ASTC_2D_8X6: | 247 | case PixelFormat::ASTC_2D_8X6_UNORM: |
| 234 | case PixelFormat::ASTC_2D_8X6_SRGB: | 248 | case PixelFormat::ASTC_2D_8X6_SRGB: |
| 235 | case PixelFormat::ASTC_2D_6X5: | 249 | case PixelFormat::ASTC_2D_6X5_UNORM: |
| 236 | case PixelFormat::ASTC_2D_6X5_SRGB: | 250 | case PixelFormat::ASTC_2D_6X5_SRGB: |
| 237 | return true; | 251 | return true; |
| 238 | default: | 252 | default: |
| @@ -242,12 +256,12 @@ bool IsPixelFormatASTC(PixelFormat format) { | |||
| 242 | 256 | ||
| 243 | bool IsPixelFormatSRGB(PixelFormat format) { | 257 | bool IsPixelFormatSRGB(PixelFormat format) { |
| 244 | switch (format) { | 258 | switch (format) { |
| 245 | case PixelFormat::RGBA8_SRGB: | 259 | case PixelFormat::A8B8G8R8_SRGB: |
| 246 | case PixelFormat::BGRA8_SRGB: | 260 | case PixelFormat::B8G8R8A8_SRGB: |
| 247 | case PixelFormat::DXT1_SRGB: | 261 | case PixelFormat::BC1_RGBA_SRGB: |
| 248 | case PixelFormat::DXT23_SRGB: | 262 | case PixelFormat::BC2_SRGB: |
| 249 | case PixelFormat::DXT45_SRGB: | 263 | case PixelFormat::BC3_SRGB: |
| 250 | case PixelFormat::BC7U_SRGB: | 264 | case PixelFormat::BC7_SRGB: |
| 251 | case PixelFormat::ASTC_2D_4X4_SRGB: | 265 | case PixelFormat::ASTC_2D_4X4_SRGB: |
| 252 | case PixelFormat::ASTC_2D_8X8_SRGB: | 266 | case PixelFormat::ASTC_2D_8X8_SRGB: |
| 253 | case PixelFormat::ASTC_2D_8X5_SRGB: | 267 | case PixelFormat::ASTC_2D_8X5_SRGB: |
| @@ -269,25 +283,4 @@ std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) { | |||
| 269 | return {GetDefaultBlockWidth(format), GetDefaultBlockHeight(format)}; | 283 | return {GetDefaultBlockWidth(format), GetDefaultBlockHeight(format)}; |
| 270 | } | 284 | } |
| 271 | 285 | ||
| 272 | bool IsFormatBCn(PixelFormat format) { | ||
| 273 | switch (format) { | ||
| 274 | case PixelFormat::DXT1: | ||
| 275 | case PixelFormat::DXT23: | ||
| 276 | case PixelFormat::DXT45: | ||
| 277 | case PixelFormat::DXN1: | ||
| 278 | case PixelFormat::DXN2SNORM: | ||
| 279 | case PixelFormat::DXN2UNORM: | ||
| 280 | case PixelFormat::BC7U: | ||
| 281 | case PixelFormat::BC6H_UF16: | ||
| 282 | case PixelFormat::BC6H_SF16: | ||
| 283 | case PixelFormat::DXT1_SRGB: | ||
| 284 | case PixelFormat::DXT23_SRGB: | ||
| 285 | case PixelFormat::DXT45_SRGB: | ||
| 286 | case PixelFormat::BC7U_SRGB: | ||
| 287 | return true; | ||
| 288 | default: | ||
| 289 | return false; | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | } // namespace VideoCore::Surface | 286 | } // namespace VideoCore::Surface |
diff --git a/src/video_core/surface.h b/src/video_core/surface.h index 6da6a1b97..cfd12fa61 100644 --- a/src/video_core/surface.h +++ b/src/video_core/surface.h | |||
| @@ -15,94 +15,105 @@ | |||
| 15 | namespace VideoCore::Surface { | 15 | namespace VideoCore::Surface { |
| 16 | 16 | ||
| 17 | enum class PixelFormat { | 17 | enum class PixelFormat { |
| 18 | ABGR8U = 0, | 18 | A8B8G8R8_UNORM, |
| 19 | ABGR8S = 1, | 19 | A8B8G8R8_SNORM, |
| 20 | ABGR8UI = 2, | 20 | A8B8G8R8_SINT, |
| 21 | B5G6R5U = 3, | 21 | A8B8G8R8_UINT, |
| 22 | A2B10G10R10U = 4, | 22 | R5G6B5_UNORM, |
| 23 | A1B5G5R5U = 5, | 23 | B5G6R5_UNORM, |
| 24 | R8U = 6, | 24 | A1R5G5B5_UNORM, |
| 25 | R8UI = 7, | 25 | A2B10G10R10_UNORM, |
| 26 | RGBA16F = 8, | 26 | A2B10G10R10_UINT, |
| 27 | RGBA16U = 9, | 27 | A1B5G5R5_UNORM, |
| 28 | RGBA16S = 10, | 28 | R8_UNORM, |
| 29 | RGBA16UI = 11, | 29 | R8_SNORM, |
| 30 | R11FG11FB10F = 12, | 30 | R8_SINT, |
| 31 | RGBA32UI = 13, | 31 | R8_UINT, |
| 32 | DXT1 = 14, | 32 | R16G16B16A16_FLOAT, |
| 33 | DXT23 = 15, | 33 | R16G16B16A16_UNORM, |
| 34 | DXT45 = 16, | 34 | R16G16B16A16_SNORM, |
| 35 | DXN1 = 17, // This is also known as BC4 | 35 | R16G16B16A16_SINT, |
| 36 | DXN2UNORM = 18, | 36 | R16G16B16A16_UINT, |
| 37 | DXN2SNORM = 19, | 37 | B10G11R11_FLOAT, |
| 38 | BC7U = 20, | 38 | R32G32B32A32_UINT, |
| 39 | BC6H_UF16 = 21, | 39 | BC1_RGBA_UNORM, |
| 40 | BC6H_SF16 = 22, | 40 | BC2_UNORM, |
| 41 | ASTC_2D_4X4 = 23, | 41 | BC3_UNORM, |
| 42 | BGRA8 = 24, | 42 | BC4_UNORM, |
| 43 | RGBA32F = 25, | 43 | BC4_SNORM, |
| 44 | RG32F = 26, | 44 | BC5_UNORM, |
| 45 | R32F = 27, | 45 | BC5_SNORM, |
| 46 | R16F = 28, | 46 | BC7_UNORM, |
| 47 | R16U = 29, | 47 | BC6H_UFLOAT, |
| 48 | R16S = 30, | 48 | BC6H_SFLOAT, |
| 49 | R16UI = 31, | 49 | ASTC_2D_4X4_UNORM, |
| 50 | R16I = 32, | 50 | B8G8R8A8_UNORM, |
| 51 | RG16 = 33, | 51 | R32G32B32A32_FLOAT, |
| 52 | RG16F = 34, | 52 | R32G32B32A32_SINT, |
| 53 | RG16UI = 35, | 53 | R32G32_FLOAT, |
| 54 | RG16I = 36, | 54 | R32G32_SINT, |
| 55 | RG16S = 37, | 55 | R32_FLOAT, |
| 56 | RGB32F = 38, | 56 | R16_FLOAT, |
| 57 | RGBA8_SRGB = 39, | 57 | R16_UNORM, |
| 58 | RG8U = 40, | 58 | R16_SNORM, |
| 59 | RG8S = 41, | 59 | R16_UINT, |
| 60 | RG8UI = 42, | 60 | R16_SINT, |
| 61 | RG32UI = 43, | 61 | R16G16_UNORM, |
| 62 | RGBX16F = 44, | 62 | R16G16_FLOAT, |
| 63 | R32UI = 45, | 63 | R16G16_UINT, |
| 64 | R32I = 46, | 64 | R16G16_SINT, |
| 65 | ASTC_2D_8X8 = 47, | 65 | R16G16_SNORM, |
| 66 | ASTC_2D_8X5 = 48, | 66 | R32G32B32_FLOAT, |
| 67 | ASTC_2D_5X4 = 49, | 67 | A8B8G8R8_SRGB, |
| 68 | BGRA8_SRGB = 50, | 68 | R8G8_UNORM, |
| 69 | DXT1_SRGB = 51, | 69 | R8G8_SNORM, |
| 70 | DXT23_SRGB = 52, | 70 | R8G8_SINT, |
| 71 | DXT45_SRGB = 53, | 71 | R8G8_UINT, |
| 72 | BC7U_SRGB = 54, | 72 | R32G32_UINT, |
| 73 | R4G4B4A4U = 55, | 73 | R16G16B16X16_FLOAT, |
| 74 | ASTC_2D_4X4_SRGB = 56, | 74 | R32_UINT, |
| 75 | ASTC_2D_8X8_SRGB = 57, | 75 | R32_SINT, |
| 76 | ASTC_2D_8X5_SRGB = 58, | 76 | ASTC_2D_8X8_UNORM, |
| 77 | ASTC_2D_5X4_SRGB = 59, | 77 | ASTC_2D_8X5_UNORM, |
| 78 | ASTC_2D_5X5 = 60, | 78 | ASTC_2D_5X4_UNORM, |
| 79 | ASTC_2D_5X5_SRGB = 61, | 79 | B8G8R8A8_SRGB, |
| 80 | ASTC_2D_10X8 = 62, | 80 | BC1_RGBA_SRGB, |
| 81 | ASTC_2D_10X8_SRGB = 63, | 81 | BC2_SRGB, |
| 82 | ASTC_2D_6X6 = 64, | 82 | BC3_SRGB, |
| 83 | ASTC_2D_6X6_SRGB = 65, | 83 | BC7_SRGB, |
| 84 | ASTC_2D_10X10 = 66, | 84 | A4B4G4R4_UNORM, |
| 85 | ASTC_2D_10X10_SRGB = 67, | 85 | ASTC_2D_4X4_SRGB, |
| 86 | ASTC_2D_12X12 = 68, | 86 | ASTC_2D_8X8_SRGB, |
| 87 | ASTC_2D_12X12_SRGB = 69, | 87 | ASTC_2D_8X5_SRGB, |
| 88 | ASTC_2D_8X6 = 70, | 88 | ASTC_2D_5X4_SRGB, |
| 89 | ASTC_2D_8X6_SRGB = 71, | 89 | ASTC_2D_5X5_UNORM, |
| 90 | ASTC_2D_6X5 = 72, | 90 | ASTC_2D_5X5_SRGB, |
| 91 | ASTC_2D_6X5_SRGB = 73, | 91 | ASTC_2D_10X8_UNORM, |
| 92 | E5B9G9R9F = 74, | 92 | ASTC_2D_10X8_SRGB, |
| 93 | ASTC_2D_6X6_UNORM, | ||
| 94 | ASTC_2D_6X6_SRGB, | ||
| 95 | ASTC_2D_10X10_UNORM, | ||
| 96 | ASTC_2D_10X10_SRGB, | ||
| 97 | ASTC_2D_12X12_UNORM, | ||
| 98 | ASTC_2D_12X12_SRGB, | ||
| 99 | ASTC_2D_8X6_UNORM, | ||
| 100 | ASTC_2D_8X6_SRGB, | ||
| 101 | ASTC_2D_6X5_UNORM, | ||
| 102 | ASTC_2D_6X5_SRGB, | ||
| 103 | E5B9G9R9_FLOAT, | ||
| 93 | 104 | ||
| 94 | MaxColorFormat, | 105 | MaxColorFormat, |
| 95 | 106 | ||
| 96 | // Depth formats | 107 | // Depth formats |
| 97 | Z32F = 75, | 108 | D32_FLOAT = MaxColorFormat, |
| 98 | Z16 = 76, | 109 | D16_UNORM, |
| 99 | 110 | ||
| 100 | MaxDepthFormat, | 111 | MaxDepthFormat, |
| 101 | 112 | ||
| 102 | // DepthStencil formats | 113 | // DepthStencil formats |
| 103 | Z24S8 = 77, | 114 | D24_UNORM_S8_UINT = MaxDepthFormat, |
| 104 | S8Z24 = 78, | 115 | S8_UINT_D24_UNORM, |
| 105 | Z32FS8 = 79, | 116 | D32_FLOAT_S8_UINT, |
| 106 | 117 | ||
| 107 | MaxDepthStencilFormat, | 118 | MaxDepthStencilFormat, |
| 108 | 119 | ||
| @@ -130,86 +141,97 @@ enum class SurfaceTarget { | |||
| 130 | }; | 141 | }; |
| 131 | 142 | ||
| 132 | constexpr std::array<u32, MaxPixelFormat> compression_factor_shift_table = {{ | 143 | constexpr std::array<u32, MaxPixelFormat> compression_factor_shift_table = {{ |
| 133 | 0, // ABGR8U | 144 | 0, // A8B8G8R8_UNORM |
| 134 | 0, // ABGR8S | 145 | 0, // A8B8G8R8_SNORM |
| 135 | 0, // ABGR8UI | 146 | 0, // A8B8G8R8_SINT |
| 136 | 0, // B5G6R5U | 147 | 0, // A8B8G8R8_UINT |
| 137 | 0, // A2B10G10R10U | 148 | 0, // R5G6B5_UNORM |
| 138 | 0, // A1B5G5R5U | 149 | 0, // B5G6R5_UNORM |
| 139 | 0, // R8U | 150 | 0, // A1R5G5B5_UNORM |
| 140 | 0, // R8UI | 151 | 0, // A2B10G10R10_UNORM |
| 141 | 0, // RGBA16F | 152 | 0, // A2B10G10R10_UINT |
| 142 | 0, // RGBA16U | 153 | 0, // A1B5G5R5_UNORM |
| 143 | 0, // RGBA16S | 154 | 0, // R8_UNORM |
| 144 | 0, // RGBA16UI | 155 | 0, // R8_SNORM |
| 145 | 0, // R11FG11FB10F | 156 | 0, // R8_SINT |
| 146 | 0, // RGBA32UI | 157 | 0, // R8_UINT |
| 147 | 2, // DXT1 | 158 | 0, // R16G16B16A16_FLOAT |
| 148 | 2, // DXT23 | 159 | 0, // R16G16B16A16_UNORM |
| 149 | 2, // DXT45 | 160 | 0, // R16G16B16A16_SNORM |
| 150 | 2, // DXN1 | 161 | 0, // R16G16B16A16_SINT |
| 151 | 2, // DXN2UNORM | 162 | 0, // R16G16B16A16_UINT |
| 152 | 2, // DXN2SNORM | 163 | 0, // B10G11R11_FLOAT |
| 153 | 2, // BC7U | 164 | 0, // R32G32B32A32_UINT |
| 154 | 2, // BC6H_UF16 | 165 | 2, // BC1_RGBA_UNORM |
| 155 | 2, // BC6H_SF16 | 166 | 2, // BC2_UNORM |
| 156 | 2, // ASTC_2D_4X4 | 167 | 2, // BC3_UNORM |
| 157 | 0, // BGRA8 | 168 | 2, // BC4_UNORM |
| 158 | 0, // RGBA32F | 169 | 2, // BC4_SNORM |
| 159 | 0, // RG32F | 170 | 2, // BC5_UNORM |
| 160 | 0, // R32F | 171 | 2, // BC5_SNORM |
| 161 | 0, // R16F | 172 | 2, // BC7_UNORM |
| 162 | 0, // R16U | 173 | 2, // BC6H_UFLOAT |
| 163 | 0, // R16S | 174 | 2, // BC6H_SFLOAT |
| 164 | 0, // R16UI | 175 | 2, // ASTC_2D_4X4_UNORM |
| 165 | 0, // R16I | 176 | 0, // B8G8R8A8_UNORM |
| 166 | 0, // RG16 | 177 | 0, // R32G32B32A32_FLOAT |
| 167 | 0, // RG16F | 178 | 0, // R32G32B32A32_SINT |
| 168 | 0, // RG16UI | 179 | 0, // R32G32_FLOAT |
| 169 | 0, // RG16I | 180 | 0, // R32G32_SINT |
| 170 | 0, // RG16S | 181 | 0, // R32_FLOAT |
| 171 | 0, // RGB32F | 182 | 0, // R16_FLOAT |
| 172 | 0, // RGBA8_SRGB | 183 | 0, // R16_UNORM |
| 173 | 0, // RG8U | 184 | 0, // R16_SNORM |
| 174 | 0, // RG8S | 185 | 0, // R16_UINT |
| 175 | 0, // RG8UI | 186 | 0, // R16_SINT |
| 176 | 0, // RG32UI | 187 | 0, // R16G16_UNORM |
| 177 | 0, // RGBX16F | 188 | 0, // R16G16_FLOAT |
| 178 | 0, // R32UI | 189 | 0, // R16G16_UINT |
| 179 | 0, // R32I | 190 | 0, // R16G16_SINT |
| 180 | 2, // ASTC_2D_8X8 | 191 | 0, // R16G16_SNORM |
| 181 | 2, // ASTC_2D_8X5 | 192 | 0, // R32G32B32_FLOAT |
| 182 | 2, // ASTC_2D_5X4 | 193 | 0, // A8B8G8R8_SRGB |
| 183 | 0, // BGRA8_SRGB | 194 | 0, // R8G8_UNORM |
| 184 | 2, // DXT1_SRGB | 195 | 0, // R8G8_SNORM |
| 185 | 2, // DXT23_SRGB | 196 | 0, // R8G8_SINT |
| 186 | 2, // DXT45_SRGB | 197 | 0, // R8G8_UINT |
| 187 | 2, // BC7U_SRGB | 198 | 0, // R32G32_UINT |
| 188 | 0, // R4G4B4A4U | 199 | 0, // R16G16B16X16_FLOAT |
| 200 | 0, // R32_UINT | ||
| 201 | 0, // R32_SINT | ||
| 202 | 2, // ASTC_2D_8X8_UNORM | ||
| 203 | 2, // ASTC_2D_8X5_UNORM | ||
| 204 | 2, // ASTC_2D_5X4_UNORM | ||
| 205 | 0, // B8G8R8A8_SRGB | ||
| 206 | 2, // BC1_RGBA_SRGB | ||
| 207 | 2, // BC2_SRGB | ||
| 208 | 2, // BC3_SRGB | ||
| 209 | 2, // BC7_SRGB | ||
| 210 | 0, // A4B4G4R4_UNORM | ||
| 189 | 2, // ASTC_2D_4X4_SRGB | 211 | 2, // ASTC_2D_4X4_SRGB |
| 190 | 2, // ASTC_2D_8X8_SRGB | 212 | 2, // ASTC_2D_8X8_SRGB |
| 191 | 2, // ASTC_2D_8X5_SRGB | 213 | 2, // ASTC_2D_8X5_SRGB |
| 192 | 2, // ASTC_2D_5X4_SRGB | 214 | 2, // ASTC_2D_5X4_SRGB |
| 193 | 2, // ASTC_2D_5X5 | 215 | 2, // ASTC_2D_5X5_UNORM |
| 194 | 2, // ASTC_2D_5X5_SRGB | 216 | 2, // ASTC_2D_5X5_SRGB |
| 195 | 2, // ASTC_2D_10X8 | 217 | 2, // ASTC_2D_10X8_UNORM |
| 196 | 2, // ASTC_2D_10X8_SRGB | 218 | 2, // ASTC_2D_10X8_SRGB |
| 197 | 2, // ASTC_2D_6X6 | 219 | 2, // ASTC_2D_6X6_UNORM |
| 198 | 2, // ASTC_2D_6X6_SRGB | 220 | 2, // ASTC_2D_6X6_SRGB |
| 199 | 2, // ASTC_2D_10X10 | 221 | 2, // ASTC_2D_10X10_UNORM |
| 200 | 2, // ASTC_2D_10X10_SRGB | 222 | 2, // ASTC_2D_10X10_SRGB |
| 201 | 2, // ASTC_2D_12X12 | 223 | 2, // ASTC_2D_12X12_UNORM |
| 202 | 2, // ASTC_2D_12X12_SRGB | 224 | 2, // ASTC_2D_12X12_SRGB |
| 203 | 2, // ASTC_2D_8X6 | 225 | 2, // ASTC_2D_8X6_UNORM |
| 204 | 2, // ASTC_2D_8X6_SRGB | 226 | 2, // ASTC_2D_8X6_SRGB |
| 205 | 2, // ASTC_2D_6X5 | 227 | 2, // ASTC_2D_6X5_UNORM |
| 206 | 2, // ASTC_2D_6X5_SRGB | 228 | 2, // ASTC_2D_6X5_SRGB |
| 207 | 0, // E5B9G9R9F | 229 | 0, // E5B9G9R9_FLOAT |
| 208 | 0, // Z32F | 230 | 0, // D32_FLOAT |
| 209 | 0, // Z16 | 231 | 0, // D16_UNORM |
| 210 | 0, // Z24S8 | 232 | 0, // D24_UNORM_S8_UINT |
| 211 | 0, // S8Z24 | 233 | 0, // S8_UINT_D24_UNORM |
| 212 | 0, // Z32FS8 | 234 | 0, // D32_FLOAT_S8_UINT |
| 213 | }}; | 235 | }}; |
| 214 | 236 | ||
| 215 | /** | 237 | /** |
| @@ -229,86 +251,97 @@ inline constexpr u32 GetCompressionFactor(PixelFormat format) { | |||
| 229 | } | 251 | } |
| 230 | 252 | ||
| 231 | constexpr std::array<u32, MaxPixelFormat> block_width_table = {{ | 253 | constexpr std::array<u32, MaxPixelFormat> block_width_table = {{ |
| 232 | 1, // ABGR8U | 254 | 1, // A8B8G8R8_UNORM |
| 233 | 1, // ABGR8S | 255 | 1, // A8B8G8R8_SNORM |
| 234 | 1, // ABGR8UI | 256 | 1, // A8B8G8R8_SINT |
| 235 | 1, // B5G6R5U | 257 | 1, // A8B8G8R8_UINT |
| 236 | 1, // A2B10G10R10U | 258 | 1, // R5G6B5_UNORM |
| 237 | 1, // A1B5G5R5U | 259 | 1, // B5G6R5_UNORM |
| 238 | 1, // R8U | 260 | 1, // A1R5G5B5_UNORM |
| 239 | 1, // R8UI | 261 | 1, // A2B10G10R10_UNORM |
| 240 | 1, // RGBA16F | 262 | 1, // A2B10G10R10_UINT |
| 241 | 1, // RGBA16U | 263 | 1, // A1B5G5R5_UNORM |
| 242 | 1, // RGBA16S | 264 | 1, // R8_UNORM |
| 243 | 1, // RGBA16UI | 265 | 1, // R8_SNORM |
| 244 | 1, // R11FG11FB10F | 266 | 1, // R8_SINT |
| 245 | 1, // RGBA32UI | 267 | 1, // R8_UINT |
| 246 | 4, // DXT1 | 268 | 1, // R16G16B16A16_FLOAT |
| 247 | 4, // DXT23 | 269 | 1, // R16G16B16A16_UNORM |
| 248 | 4, // DXT45 | 270 | 1, // R16G16B16A16_SNORM |
| 249 | 4, // DXN1 | 271 | 1, // R16G16B16A16_SINT |
| 250 | 4, // DXN2UNORM | 272 | 1, // R16G16B16A16_UINT |
| 251 | 4, // DXN2SNORM | 273 | 1, // B10G11R11_FLOAT |
| 252 | 4, // BC7U | 274 | 1, // R32G32B32A32_UINT |
| 253 | 4, // BC6H_UF16 | 275 | 4, // BC1_RGBA_UNORM |
| 254 | 4, // BC6H_SF16 | 276 | 4, // BC2_UNORM |
| 255 | 4, // ASTC_2D_4X4 | 277 | 4, // BC3_UNORM |
| 256 | 1, // BGRA8 | 278 | 4, // BC4_UNORM |
| 257 | 1, // RGBA32F | 279 | 4, // BC4_SNORM |
| 258 | 1, // RG32F | 280 | 4, // BC5_UNORM |
| 259 | 1, // R32F | 281 | 4, // BC5_SNORM |
| 260 | 1, // R16F | 282 | 4, // BC7_UNORM |
| 261 | 1, // R16U | 283 | 4, // BC6H_UFLOAT |
| 262 | 1, // R16S | 284 | 4, // BC6H_SFLOAT |
| 263 | 1, // R16UI | 285 | 4, // ASTC_2D_4X4_UNORM |
| 264 | 1, // R16I | 286 | 1, // B8G8R8A8_UNORM |
| 265 | 1, // RG16 | 287 | 1, // R32G32B32A32_FLOAT |
| 266 | 1, // RG16F | 288 | 1, // R32G32B32A32_SINT |
| 267 | 1, // RG16UI | 289 | 1, // R32G32_FLOAT |
| 268 | 1, // RG16I | 290 | 1, // R32G32_SINT |
| 269 | 1, // RG16S | 291 | 1, // R32_FLOAT |
| 270 | 1, // RGB32F | 292 | 1, // R16_FLOAT |
| 271 | 1, // RGBA8_SRGB | 293 | 1, // R16_UNORM |
| 272 | 1, // RG8U | 294 | 1, // R16_SNORM |
| 273 | 1, // RG8S | 295 | 1, // R16_UINT |
| 274 | 1, // RG8UI | 296 | 1, // R16_SINT |
| 275 | 1, // RG32UI | 297 | 1, // R16G16_UNORM |
| 276 | 1, // RGBX16F | 298 | 1, // R16G16_FLOAT |
| 277 | 1, // R32UI | 299 | 1, // R16G16_UINT |
| 278 | 1, // R32I | 300 | 1, // R16G16_SINT |
| 279 | 8, // ASTC_2D_8X8 | 301 | 1, // R16G16_SNORM |
| 280 | 8, // ASTC_2D_8X5 | 302 | 1, // R32G32B32_FLOAT |
| 281 | 5, // ASTC_2D_5X4 | 303 | 1, // A8B8G8R8_SRGB |
| 282 | 1, // BGRA8_SRGB | 304 | 1, // R8G8_UNORM |
| 283 | 4, // DXT1_SRGB | 305 | 1, // R8G8_SNORM |
| 284 | 4, // DXT23_SRGB | 306 | 1, // R8G8_SINT |
| 285 | 4, // DXT45_SRGB | 307 | 1, // R8G8_UINT |
| 286 | 4, // BC7U_SRGB | 308 | 1, // R32G32_UINT |
| 287 | 1, // R4G4B4A4U | 309 | 1, // R16G16B16X16_FLOAT |
| 310 | 1, // R32_UINT | ||
| 311 | 1, // R32_SINT | ||
| 312 | 8, // ASTC_2D_8X8_UNORM | ||
| 313 | 8, // ASTC_2D_8X5_UNORM | ||
| 314 | 5, // ASTC_2D_5X4_UNORM | ||
| 315 | 1, // B8G8R8A8_SRGB | ||
| 316 | 4, // BC1_RGBA_SRGB | ||
| 317 | 4, // BC2_SRGB | ||
| 318 | 4, // BC3_SRGB | ||
| 319 | 4, // BC7_SRGB | ||
| 320 | 1, // A4B4G4R4_UNORM | ||
| 288 | 4, // ASTC_2D_4X4_SRGB | 321 | 4, // ASTC_2D_4X4_SRGB |
| 289 | 8, // ASTC_2D_8X8_SRGB | 322 | 8, // ASTC_2D_8X8_SRGB |
| 290 | 8, // ASTC_2D_8X5_SRGB | 323 | 8, // ASTC_2D_8X5_SRGB |
| 291 | 5, // ASTC_2D_5X4_SRGB | 324 | 5, // ASTC_2D_5X4_SRGB |
| 292 | 5, // ASTC_2D_5X5 | 325 | 5, // ASTC_2D_5X5_UNORM |
| 293 | 5, // ASTC_2D_5X5_SRGB | 326 | 5, // ASTC_2D_5X5_SRGB |
| 294 | 10, // ASTC_2D_10X8 | 327 | 10, // ASTC_2D_10X8_UNORM |
| 295 | 10, // ASTC_2D_10X8_SRGB | 328 | 10, // ASTC_2D_10X8_SRGB |
| 296 | 6, // ASTC_2D_6X6 | 329 | 6, // ASTC_2D_6X6_UNORM |
| 297 | 6, // ASTC_2D_6X6_SRGB | 330 | 6, // ASTC_2D_6X6_SRGB |
| 298 | 10, // ASTC_2D_10X10 | 331 | 10, // ASTC_2D_10X10_UNORM |
| 299 | 10, // ASTC_2D_10X10_SRGB | 332 | 10, // ASTC_2D_10X10_SRGB |
| 300 | 12, // ASTC_2D_12X12 | 333 | 12, // ASTC_2D_12X12_UNORM |
| 301 | 12, // ASTC_2D_12X12_SRGB | 334 | 12, // ASTC_2D_12X12_SRGB |
| 302 | 8, // ASTC_2D_8X6 | 335 | 8, // ASTC_2D_8X6_UNORM |
| 303 | 8, // ASTC_2D_8X6_SRGB | 336 | 8, // ASTC_2D_8X6_SRGB |
| 304 | 6, // ASTC_2D_6X5 | 337 | 6, // ASTC_2D_6X5_UNORM |
| 305 | 6, // ASTC_2D_6X5_SRGB | 338 | 6, // ASTC_2D_6X5_SRGB |
| 306 | 1, // E5B9G9R9F | 339 | 1, // E5B9G9R9_FLOAT |
| 307 | 1, // Z32F | 340 | 1, // D32_FLOAT |
| 308 | 1, // Z16 | 341 | 1, // D16_UNORM |
| 309 | 1, // Z24S8 | 342 | 1, // D24_UNORM_S8_UINT |
| 310 | 1, // S8Z24 | 343 | 1, // S8_UINT_D24_UNORM |
| 311 | 1, // Z32FS8 | 344 | 1, // D32_FLOAT_S8_UINT |
| 312 | }}; | 345 | }}; |
| 313 | 346 | ||
| 314 | static constexpr u32 GetDefaultBlockWidth(PixelFormat format) { | 347 | static constexpr u32 GetDefaultBlockWidth(PixelFormat format) { |
| @@ -320,86 +353,97 @@ static constexpr u32 GetDefaultBlockWidth(PixelFormat format) { | |||
| 320 | } | 353 | } |
| 321 | 354 | ||
| 322 | constexpr std::array<u32, MaxPixelFormat> block_height_table = {{ | 355 | constexpr std::array<u32, MaxPixelFormat> block_height_table = {{ |
| 323 | 1, // ABGR8U | 356 | 1, // A8B8G8R8_UNORM |
| 324 | 1, // ABGR8S | 357 | 1, // A8B8G8R8_SNORM |
| 325 | 1, // ABGR8UI | 358 | 1, // A8B8G8R8_SINT |
| 326 | 1, // B5G6R5U | 359 | 1, // A8B8G8R8_UINT |
| 327 | 1, // A2B10G10R10U | 360 | 1, // R5G6B5_UNORM |
| 328 | 1, // A1B5G5R5U | 361 | 1, // B5G6R5_UNORM |
| 329 | 1, // R8U | 362 | 1, // A1R5G5B5_UNORM |
| 330 | 1, // R8UI | 363 | 1, // A2B10G10R10_UNORM |
| 331 | 1, // RGBA16F | 364 | 1, // A2B10G10R10_UINT |
| 332 | 1, // RGBA16U | 365 | 1, // A1B5G5R5_UNORM |
| 333 | 1, // RGBA16S | 366 | 1, // R8_UNORM |
| 334 | 1, // RGBA16UI | 367 | 1, // R8_SNORM |
| 335 | 1, // R11FG11FB10F | 368 | 1, // R8_SINT |
| 336 | 1, // RGBA32UI | 369 | 1, // R8_UINT |
| 337 | 4, // DXT1 | 370 | 1, // R16G16B16A16_FLOAT |
| 338 | 4, // DXT23 | 371 | 1, // R16G16B16A16_UNORM |
| 339 | 4, // DXT45 | 372 | 1, // R16G16B16A16_SNORM |
| 340 | 4, // DXN1 | 373 | 1, // R16G16B16A16_SINT |
| 341 | 4, // DXN2UNORM | 374 | 1, // R16G16B16A16_UINT |
| 342 | 4, // DXN2SNORM | 375 | 1, // B10G11R11_FLOAT |
| 343 | 4, // BC7U | 376 | 1, // R32G32B32A32_UINT |
| 344 | 4, // BC6H_UF16 | 377 | 4, // BC1_RGBA_UNORM |
| 345 | 4, // BC6H_SF16 | 378 | 4, // BC2_UNORM |
| 346 | 4, // ASTC_2D_4X4 | 379 | 4, // BC3_UNORM |
| 347 | 1, // BGRA8 | 380 | 4, // BC4_UNORM |
| 348 | 1, // RGBA32F | 381 | 4, // BC4_SNORM |
| 349 | 1, // RG32F | 382 | 4, // BC5_UNORM |
| 350 | 1, // R32F | 383 | 4, // BC5_SNORM |
| 351 | 1, // R16F | 384 | 4, // BC7_UNORM |
| 352 | 1, // R16U | 385 | 4, // BC6H_UFLOAT |
| 353 | 1, // R16S | 386 | 4, // BC6H_SFLOAT |
| 354 | 1, // R16UI | 387 | 4, // ASTC_2D_4X4_UNORM |
| 355 | 1, // R16I | 388 | 1, // B8G8R8A8_UNORM |
| 356 | 1, // RG16 | 389 | 1, // R32G32B32A32_FLOAT |
| 357 | 1, // RG16F | 390 | 1, // R32G32B32A32_SINT |
| 358 | 1, // RG16UI | 391 | 1, // R32G32_FLOAT |
| 359 | 1, // RG16I | 392 | 1, // R32G32_SINT |
| 360 | 1, // RG16S | 393 | 1, // R32_FLOAT |
| 361 | 1, // RGB32F | 394 | 1, // R16_FLOAT |
| 362 | 1, // RGBA8_SRGB | 395 | 1, // R16_UNORM |
| 363 | 1, // RG8U | 396 | 1, // R16_SNORM |
| 364 | 1, // RG8S | 397 | 1, // R16_UINT |
| 365 | 1, // RG8UI | 398 | 1, // R16_SINT |
| 366 | 1, // RG32UI | 399 | 1, // R16G16_UNORM |
| 367 | 1, // RGBX16F | 400 | 1, // R16G16_FLOAT |
| 368 | 1, // R32UI | 401 | 1, // R16G16_UINT |
| 369 | 1, // R32I | 402 | 1, // R16G16_SINT |
| 370 | 8, // ASTC_2D_8X8 | 403 | 1, // R16G16_SNORM |
| 371 | 5, // ASTC_2D_8X5 | 404 | 1, // R32G32B32_FLOAT |
| 372 | 4, // ASTC_2D_5X4 | 405 | 1, // A8B8G8R8_SRGB |
| 373 | 1, // BGRA8_SRGB | 406 | 1, // R8G8_UNORM |
| 374 | 4, // DXT1_SRGB | 407 | 1, // R8G8_SNORM |
| 375 | 4, // DXT23_SRGB | 408 | 1, // R8G8_SINT |
| 376 | 4, // DXT45_SRGB | 409 | 1, // R8G8_UINT |
| 377 | 4, // BC7U_SRGB | 410 | 1, // R32G32_UINT |
| 378 | 1, // R4G4B4A4U | 411 | 1, // R16G16B16X16_FLOAT |
| 412 | 1, // R32_UINT | ||
| 413 | 1, // R32_SINT | ||
| 414 | 8, // ASTC_2D_8X8_UNORM | ||
| 415 | 5, // ASTC_2D_8X5_UNORM | ||
| 416 | 4, // ASTC_2D_5X4_UNORM | ||
| 417 | 1, // B8G8R8A8_SRGB | ||
| 418 | 4, // BC1_RGBA_SRGB | ||
| 419 | 4, // BC2_SRGB | ||
| 420 | 4, // BC3_SRGB | ||
| 421 | 4, // BC7_SRGB | ||
| 422 | 1, // A4B4G4R4_UNORM | ||
| 379 | 4, // ASTC_2D_4X4_SRGB | 423 | 4, // ASTC_2D_4X4_SRGB |
| 380 | 8, // ASTC_2D_8X8_SRGB | 424 | 8, // ASTC_2D_8X8_SRGB |
| 381 | 5, // ASTC_2D_8X5_SRGB | 425 | 5, // ASTC_2D_8X5_SRGB |
| 382 | 4, // ASTC_2D_5X4_SRGB | 426 | 4, // ASTC_2D_5X4_SRGB |
| 383 | 5, // ASTC_2D_5X5 | 427 | 5, // ASTC_2D_5X5_UNORM |
| 384 | 5, // ASTC_2D_5X5_SRGB | 428 | 5, // ASTC_2D_5X5_SRGB |
| 385 | 8, // ASTC_2D_10X8 | 429 | 8, // ASTC_2D_10X8_UNORM |
| 386 | 8, // ASTC_2D_10X8_SRGB | 430 | 8, // ASTC_2D_10X8_SRGB |
| 387 | 6, // ASTC_2D_6X6 | 431 | 6, // ASTC_2D_6X6_UNORM |
| 388 | 6, // ASTC_2D_6X6_SRGB | 432 | 6, // ASTC_2D_6X6_SRGB |
| 389 | 10, // ASTC_2D_10X10 | 433 | 10, // ASTC_2D_10X10_UNORM |
| 390 | 10, // ASTC_2D_10X10_SRGB | 434 | 10, // ASTC_2D_10X10_SRGB |
| 391 | 12, // ASTC_2D_12X12 | 435 | 12, // ASTC_2D_12X12_UNORM |
| 392 | 12, // ASTC_2D_12X12_SRGB | 436 | 12, // ASTC_2D_12X12_SRGB |
| 393 | 6, // ASTC_2D_8X6 | 437 | 6, // ASTC_2D_8X6_UNORM |
| 394 | 6, // ASTC_2D_8X6_SRGB | 438 | 6, // ASTC_2D_8X6_SRGB |
| 395 | 5, // ASTC_2D_6X5 | 439 | 5, // ASTC_2D_6X5_UNORM |
| 396 | 5, // ASTC_2D_6X5_SRGB | 440 | 5, // ASTC_2D_6X5_SRGB |
| 397 | 1, // E5B9G9R9F | 441 | 1, // E5B9G9R9_FLOAT |
| 398 | 1, // Z32F | 442 | 1, // D32_FLOAT |
| 399 | 1, // Z16 | 443 | 1, // D16_UNORM |
| 400 | 1, // Z24S8 | 444 | 1, // D24_UNORM_S8_UINT |
| 401 | 1, // S8Z24 | 445 | 1, // S8_UINT_D24_UNORM |
| 402 | 1, // Z32FS8 | 446 | 1, // D32_FLOAT_S8_UINT |
| 403 | }}; | 447 | }}; |
| 404 | 448 | ||
| 405 | static constexpr u32 GetDefaultBlockHeight(PixelFormat format) { | 449 | static constexpr u32 GetDefaultBlockHeight(PixelFormat format) { |
| @@ -411,86 +455,97 @@ static constexpr u32 GetDefaultBlockHeight(PixelFormat format) { | |||
| 411 | } | 455 | } |
| 412 | 456 | ||
| 413 | constexpr std::array<u32, MaxPixelFormat> bpp_table = {{ | 457 | constexpr std::array<u32, MaxPixelFormat> bpp_table = {{ |
| 414 | 32, // ABGR8U | 458 | 32, // A8B8G8R8_UNORM |
| 415 | 32, // ABGR8S | 459 | 32, // A8B8G8R8_SNORM |
| 416 | 32, // ABGR8UI | 460 | 32, // A8B8G8R8_SINT |
| 417 | 16, // B5G6R5U | 461 | 32, // A8B8G8R8_UINT |
| 418 | 32, // A2B10G10R10U | 462 | 16, // R5G6B5_UNORM |
| 419 | 16, // A1B5G5R5U | 463 | 16, // B5G6R5_UNORM |
| 420 | 8, // R8U | 464 | 16, // A1R5G5B5_UNORM |
| 421 | 8, // R8UI | 465 | 32, // A2B10G10R10_UNORM |
| 422 | 64, // RGBA16F | 466 | 32, // A2B10G10R10_UINT |
| 423 | 64, // RGBA16U | 467 | 16, // A1B5G5R5_UNORM |
| 424 | 64, // RGBA16S | 468 | 8, // R8_UNORM |
| 425 | 64, // RGBA16UI | 469 | 8, // R8_SNORM |
| 426 | 32, // R11FG11FB10F | 470 | 8, // R8_SINT |
| 427 | 128, // RGBA32UI | 471 | 8, // R8_UINT |
| 428 | 64, // DXT1 | 472 | 64, // R16G16B16A16_FLOAT |
| 429 | 128, // DXT23 | 473 | 64, // R16G16B16A16_UNORM |
| 430 | 128, // DXT45 | 474 | 64, // R16G16B16A16_SNORM |
| 431 | 64, // DXN1 | 475 | 64, // R16G16B16A16_SINT |
| 432 | 128, // DXN2UNORM | 476 | 64, // R16G16B16A16_UINT |
| 433 | 128, // DXN2SNORM | 477 | 32, // B10G11R11_FLOAT |
| 434 | 128, // BC7U | 478 | 128, // R32G32B32A32_UINT |
| 435 | 128, // BC6H_UF16 | 479 | 64, // BC1_RGBA_UNORM |
| 436 | 128, // BC6H_SF16 | 480 | 128, // BC2_UNORM |
| 437 | 128, // ASTC_2D_4X4 | 481 | 128, // BC3_UNORM |
| 438 | 32, // BGRA8 | 482 | 64, // BC4_UNORM |
| 439 | 128, // RGBA32F | 483 | 64, // BC4_SNORM |
| 440 | 64, // RG32F | 484 | 128, // BC5_UNORM |
| 441 | 32, // R32F | 485 | 128, // BC5_SNORM |
| 442 | 16, // R16F | 486 | 128, // BC7_UNORM |
| 443 | 16, // R16U | 487 | 128, // BC6H_UFLOAT |
| 444 | 16, // R16S | 488 | 128, // BC6H_SFLOAT |
| 445 | 16, // R16UI | 489 | 128, // ASTC_2D_4X4_UNORM |
| 446 | 16, // R16I | 490 | 32, // B8G8R8A8_UNORM |
| 447 | 32, // RG16 | 491 | 128, // R32G32B32A32_FLOAT |
| 448 | 32, // RG16F | 492 | 128, // R32G32B32A32_SINT |
| 449 | 32, // RG16UI | 493 | 64, // R32G32_FLOAT |
| 450 | 32, // RG16I | 494 | 64, // R32G32_SINT |
| 451 | 32, // RG16S | 495 | 32, // R32_FLOAT |
| 452 | 96, // RGB32F | 496 | 16, // R16_FLOAT |
| 453 | 32, // RGBA8_SRGB | 497 | 16, // R16_UNORM |
| 454 | 16, // RG8U | 498 | 16, // R16_SNORM |
| 455 | 16, // RG8S | 499 | 16, // R16_UINT |
| 456 | 16, // RG8UI | 500 | 16, // R16_SINT |
| 457 | 64, // RG32UI | 501 | 32, // R16G16_UNORM |
| 458 | 64, // RGBX16F | 502 | 32, // R16G16_FLOAT |
| 459 | 32, // R32UI | 503 | 32, // R16G16_UINT |
| 460 | 32, // R32I | 504 | 32, // R16G16_SINT |
| 461 | 128, // ASTC_2D_8X8 | 505 | 32, // R16G16_SNORM |
| 462 | 128, // ASTC_2D_8X5 | 506 | 96, // R32G32B32_FLOAT |
| 463 | 128, // ASTC_2D_5X4 | 507 | 32, // A8B8G8R8_SRGB |
| 464 | 32, // BGRA8_SRGB | 508 | 16, // R8G8_UNORM |
| 465 | 64, // DXT1_SRGB | 509 | 16, // R8G8_SNORM |
| 466 | 128, // DXT23_SRGB | 510 | 16, // R8G8_SINT |
| 467 | 128, // DXT45_SRGB | 511 | 16, // R8G8_UINT |
| 468 | 128, // BC7U | 512 | 64, // R32G32_UINT |
| 469 | 16, // R4G4B4A4U | 513 | 64, // R16G16B16X16_FLOAT |
| 514 | 32, // R32_UINT | ||
| 515 | 32, // R32_SINT | ||
| 516 | 128, // ASTC_2D_8X8_UNORM | ||
| 517 | 128, // ASTC_2D_8X5_UNORM | ||
| 518 | 128, // ASTC_2D_5X4_UNORM | ||
| 519 | 32, // B8G8R8A8_SRGB | ||
| 520 | 64, // BC1_RGBA_SRGB | ||
| 521 | 128, // BC2_SRGB | ||
| 522 | 128, // BC3_SRGB | ||
| 523 | 128, // BC7_UNORM | ||
| 524 | 16, // A4B4G4R4_UNORM | ||
| 470 | 128, // ASTC_2D_4X4_SRGB | 525 | 128, // ASTC_2D_4X4_SRGB |
| 471 | 128, // ASTC_2D_8X8_SRGB | 526 | 128, // ASTC_2D_8X8_SRGB |
| 472 | 128, // ASTC_2D_8X5_SRGB | 527 | 128, // ASTC_2D_8X5_SRGB |
| 473 | 128, // ASTC_2D_5X4_SRGB | 528 | 128, // ASTC_2D_5X4_SRGB |
| 474 | 128, // ASTC_2D_5X5 | 529 | 128, // ASTC_2D_5X5_UNORM |
| 475 | 128, // ASTC_2D_5X5_SRGB | 530 | 128, // ASTC_2D_5X5_SRGB |
| 476 | 128, // ASTC_2D_10X8 | 531 | 128, // ASTC_2D_10X8_UNORM |
| 477 | 128, // ASTC_2D_10X8_SRGB | 532 | 128, // ASTC_2D_10X8_SRGB |
| 478 | 128, // ASTC_2D_6X6 | 533 | 128, // ASTC_2D_6X6_UNORM |
| 479 | 128, // ASTC_2D_6X6_SRGB | 534 | 128, // ASTC_2D_6X6_SRGB |
| 480 | 128, // ASTC_2D_10X10 | 535 | 128, // ASTC_2D_10X10_UNORM |
| 481 | 128, // ASTC_2D_10X10_SRGB | 536 | 128, // ASTC_2D_10X10_SRGB |
| 482 | 128, // ASTC_2D_12X12 | 537 | 128, // ASTC_2D_12X12_UNORM |
| 483 | 128, // ASTC_2D_12X12_SRGB | 538 | 128, // ASTC_2D_12X12_SRGB |
| 484 | 128, // ASTC_2D_8X6 | 539 | 128, // ASTC_2D_8X6_UNORM |
| 485 | 128, // ASTC_2D_8X6_SRGB | 540 | 128, // ASTC_2D_8X6_SRGB |
| 486 | 128, // ASTC_2D_6X5 | 541 | 128, // ASTC_2D_6X5_UNORM |
| 487 | 128, // ASTC_2D_6X5_SRGB | 542 | 128, // ASTC_2D_6X5_SRGB |
| 488 | 32, // E5B9G9R9F | 543 | 32, // E5B9G9R9_FLOAT |
| 489 | 32, // Z32F | 544 | 32, // D32_FLOAT |
| 490 | 16, // Z16 | 545 | 16, // D16_UNORM |
| 491 | 32, // Z24S8 | 546 | 32, // D24_UNORM_S8_UINT |
| 492 | 32, // S8Z24 | 547 | 32, // S8_UINT_D24_UNORM |
| 493 | 64, // Z32FS8 | 548 | 64, // D32_FLOAT_S8_UINT |
| 494 | }}; | 549 | }}; |
| 495 | 550 | ||
| 496 | static constexpr u32 GetFormatBpp(PixelFormat format) { | 551 | static constexpr u32 GetFormatBpp(PixelFormat format) { |
| @@ -529,7 +584,4 @@ bool IsPixelFormatSRGB(PixelFormat format); | |||
| 529 | 584 | ||
| 530 | std::pair<u32, u32> GetASTCBlockSize(PixelFormat format); | 585 | std::pair<u32, u32> GetASTCBlockSize(PixelFormat format); |
| 531 | 586 | ||
| 532 | /// Returns true if the specified PixelFormat is a BCn format, e.g. DXT or DXN | ||
| 533 | bool IsFormatBCn(PixelFormat format); | ||
| 534 | |||
| 535 | } // namespace VideoCore::Surface | 587 | } // namespace VideoCore::Surface |
diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp index f476f03b0..a1cc4756d 100644 --- a/src/video_core/texture_cache/format_lookup_table.cpp +++ b/src/video_core/texture_cache/format_lookup_table.cpp | |||
| @@ -41,119 +41,126 @@ struct Table { | |||
| 41 | ComponentType alpha_component; | 41 | ComponentType alpha_component; |
| 42 | bool is_srgb; | 42 | bool is_srgb; |
| 43 | }; | 43 | }; |
| 44 | constexpr std::array<Table, 78> DefinitionTable = {{ | 44 | constexpr std::array<Table, 86> DefinitionTable = {{ |
| 45 | {TextureFormat::A8R8G8B8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ABGR8U}, | 45 | {TextureFormat::A8R8G8B8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A8B8G8R8_UNORM}, |
| 46 | {TextureFormat::A8R8G8B8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::ABGR8S}, | 46 | {TextureFormat::A8R8G8B8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::A8B8G8R8_SNORM}, |
| 47 | {TextureFormat::A8R8G8B8, C, UINT, UINT, UINT, UINT, PixelFormat::ABGR8UI}, | 47 | {TextureFormat::A8R8G8B8, C, UINT, UINT, UINT, UINT, PixelFormat::A8B8G8R8_UINT}, |
| 48 | {TextureFormat::A8R8G8B8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::RGBA8_SRGB}, | 48 | {TextureFormat::A8R8G8B8, C, SINT, SINT, SINT, SINT, PixelFormat::A8B8G8R8_SINT}, |
| 49 | {TextureFormat::A8R8G8B8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::A8B8G8R8_SRGB}, | ||
| 49 | 50 | ||
| 50 | {TextureFormat::B5G6R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::B5G6R5U}, | 51 | {TextureFormat::B5G6R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::B5G6R5_UNORM}, |
| 51 | 52 | ||
| 52 | {TextureFormat::A2B10G10R10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A2B10G10R10U}, | 53 | {TextureFormat::A2B10G10R10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A2B10G10R10_UNORM}, |
| 54 | {TextureFormat::A2B10G10R10, C, UINT, UINT, UINT, UINT, PixelFormat::A2B10G10R10_UINT}, | ||
| 53 | 55 | ||
| 54 | {TextureFormat::A1B5G5R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A1B5G5R5U}, | 56 | {TextureFormat::A1B5G5R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A1B5G5R5_UNORM}, |
| 55 | 57 | ||
| 56 | {TextureFormat::A4B4G4R4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R4G4B4A4U}, | 58 | {TextureFormat::A4B4G4R4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A4B4G4R4_UNORM}, |
| 57 | 59 | ||
| 58 | {TextureFormat::R8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R8U}, | 60 | {TextureFormat::R8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R8_UNORM}, |
| 59 | {TextureFormat::R8, C, UINT, UINT, UINT, UINT, PixelFormat::R8UI}, | 61 | {TextureFormat::R8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R8_SNORM}, |
| 62 | {TextureFormat::R8, C, UINT, UINT, UINT, UINT, PixelFormat::R8_UINT}, | ||
| 63 | {TextureFormat::R8, C, SINT, SINT, SINT, SINT, PixelFormat::R8_SINT}, | ||
| 60 | 64 | ||
| 61 | {TextureFormat::G8R8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::RG8U}, | 65 | {TextureFormat::R8G8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R8G8_UNORM}, |
| 62 | {TextureFormat::G8R8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::RG8S}, | 66 | {TextureFormat::R8G8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R8G8_SNORM}, |
| 63 | {TextureFormat::G8R8, C, UINT, UINT, UINT, UINT, PixelFormat::RG8UI}, | 67 | {TextureFormat::R8G8, C, UINT, UINT, UINT, UINT, PixelFormat::R8G8_UINT}, |
| 68 | {TextureFormat::R8G8, C, SINT, SINT, SINT, SINT, PixelFormat::R8G8_SINT}, | ||
| 64 | 69 | ||
| 65 | {TextureFormat::R16_G16_B16_A16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::RGBA16S}, | 70 | {TextureFormat::R16G16B16A16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16G16B16A16_SNORM}, |
| 66 | {TextureFormat::R16_G16_B16_A16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::RGBA16U}, | 71 | {TextureFormat::R16G16B16A16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16G16B16A16_UNORM}, |
| 67 | {TextureFormat::R16_G16_B16_A16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RGBA16F}, | 72 | {TextureFormat::R16G16B16A16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16G16B16A16_FLOAT}, |
| 68 | {TextureFormat::R16_G16_B16_A16, C, UINT, UINT, UINT, UINT, PixelFormat::RGBA16UI}, | 73 | {TextureFormat::R16G16B16A16, C, UINT, UINT, UINT, UINT, PixelFormat::R16G16B16A16_UINT}, |
| 74 | {TextureFormat::R16G16B16A16, C, SINT, SINT, SINT, SINT, PixelFormat::R16G16B16A16_SINT}, | ||
| 69 | 75 | ||
| 70 | {TextureFormat::R16_G16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RG16F}, | 76 | {TextureFormat::R16G16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16G16_FLOAT}, |
| 71 | {TextureFormat::R16_G16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::RG16}, | 77 | {TextureFormat::R16G16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16G16_UNORM}, |
| 72 | {TextureFormat::R16_G16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::RG16S}, | 78 | {TextureFormat::R16G16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16G16_SNORM}, |
| 73 | {TextureFormat::R16_G16, C, UINT, UINT, UINT, UINT, PixelFormat::RG16UI}, | 79 | {TextureFormat::R16G16, C, UINT, UINT, UINT, UINT, PixelFormat::R16G16_UINT}, |
| 74 | {TextureFormat::R16_G16, C, SINT, SINT, SINT, SINT, PixelFormat::RG16I}, | 80 | {TextureFormat::R16G16, C, SINT, SINT, SINT, SINT, PixelFormat::R16G16_SINT}, |
| 75 | 81 | ||
| 76 | {TextureFormat::R16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16F}, | 82 | {TextureFormat::R16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16_FLOAT}, |
| 77 | {TextureFormat::R16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16U}, | 83 | {TextureFormat::R16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16_UNORM}, |
| 78 | {TextureFormat::R16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16S}, | 84 | {TextureFormat::R16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16_SNORM}, |
| 79 | {TextureFormat::R16, C, UINT, UINT, UINT, UINT, PixelFormat::R16UI}, | 85 | {TextureFormat::R16, C, UINT, UINT, UINT, UINT, PixelFormat::R16_UINT}, |
| 80 | {TextureFormat::R16, C, SINT, SINT, SINT, SINT, PixelFormat::R16I}, | 86 | {TextureFormat::R16, C, SINT, SINT, SINT, SINT, PixelFormat::R16_SINT}, |
| 81 | 87 | ||
| 82 | {TextureFormat::BF10GF11RF11, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R11FG11FB10F}, | 88 | {TextureFormat::B10G11R11, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::B10G11R11_FLOAT}, |
| 83 | 89 | ||
| 84 | {TextureFormat::R32_G32_B32_A32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RGBA32F}, | 90 | {TextureFormat::R32G32B32A32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32G32B32A32_FLOAT}, |
| 85 | {TextureFormat::R32_G32_B32_A32, C, UINT, UINT, UINT, UINT, PixelFormat::RGBA32UI}, | 91 | {TextureFormat::R32G32B32A32, C, UINT, UINT, UINT, UINT, PixelFormat::R32G32B32A32_UINT}, |
| 92 | {TextureFormat::R32G32B32A32, C, SINT, SINT, SINT, SINT, PixelFormat::R32G32B32A32_SINT}, | ||
| 86 | 93 | ||
| 87 | {TextureFormat::R32_G32_B32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RGB32F}, | 94 | {TextureFormat::R32G32B32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32G32B32_FLOAT}, |
| 88 | 95 | ||
| 89 | {TextureFormat::R32_G32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RG32F}, | 96 | {TextureFormat::R32G32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32G32_FLOAT}, |
| 90 | {TextureFormat::R32_G32, C, UINT, UINT, UINT, UINT, PixelFormat::RG32UI}, | 97 | {TextureFormat::R32G32, C, UINT, UINT, UINT, UINT, PixelFormat::R32G32_UINT}, |
| 98 | {TextureFormat::R32G32, C, SINT, SINT, SINT, SINT, PixelFormat::R32G32_SINT}, | ||
| 91 | 99 | ||
| 92 | {TextureFormat::R32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32F}, | 100 | {TextureFormat::R32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32_FLOAT}, |
| 93 | {TextureFormat::R32, C, UINT, UINT, UINT, UINT, PixelFormat::R32UI}, | 101 | {TextureFormat::R32, C, UINT, UINT, UINT, UINT, PixelFormat::R32_UINT}, |
| 94 | {TextureFormat::R32, C, SINT, SINT, SINT, SINT, PixelFormat::R32I}, | 102 | {TextureFormat::R32, C, SINT, SINT, SINT, SINT, PixelFormat::R32_SINT}, |
| 95 | 103 | ||
| 96 | {TextureFormat::E5B9G9R9_SHAREDEXP, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::E5B9G9R9F}, | 104 | {TextureFormat::E5B9G9R9, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::E5B9G9R9_FLOAT}, |
| 97 | 105 | ||
| 98 | {TextureFormat::ZF32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::Z32F}, | 106 | {TextureFormat::D32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::D32_FLOAT}, |
| 99 | {TextureFormat::Z16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::Z16}, | 107 | {TextureFormat::D16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::D16_UNORM}, |
| 100 | {TextureFormat::S8Z24, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8Z24}, | 108 | {TextureFormat::S8D24, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8_UINT_D24_UNORM}, |
| 101 | {TextureFormat::G24R8, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8Z24}, | 109 | {TextureFormat::R8G24, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8_UINT_D24_UNORM}, |
| 102 | {TextureFormat::ZF32_X24S8, C, FLOAT, UINT, UNORM, UNORM, PixelFormat::Z32FS8}, | 110 | {TextureFormat::D32S8, C, FLOAT, UINT, UNORM, UNORM, PixelFormat::D32_FLOAT_S8_UINT}, |
| 103 | 111 | ||
| 104 | {TextureFormat::DXT1, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT1}, | 112 | {TextureFormat::BC1_RGBA, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC1_RGBA_UNORM}, |
| 105 | {TextureFormat::DXT1, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT1_SRGB}, | 113 | {TextureFormat::BC1_RGBA, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC1_RGBA_SRGB}, |
| 106 | 114 | ||
| 107 | {TextureFormat::DXT23, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT23}, | 115 | {TextureFormat::BC2, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC2_UNORM}, |
| 108 | {TextureFormat::DXT23, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT23_SRGB}, | 116 | {TextureFormat::BC2, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC2_SRGB}, |
| 109 | 117 | ||
| 110 | {TextureFormat::DXT45, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT45}, | 118 | {TextureFormat::BC3, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC3_UNORM}, |
| 111 | {TextureFormat::DXT45, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT45_SRGB}, | 119 | {TextureFormat::BC3, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC3_SRGB}, |
| 112 | 120 | ||
| 113 | // TODO: Use a different pixel format for SNORM | 121 | {TextureFormat::BC4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC4_UNORM}, |
| 114 | {TextureFormat::DXN1, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXN1}, | 122 | {TextureFormat::BC4, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::BC4_SNORM}, |
| 115 | {TextureFormat::DXN1, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::DXN1}, | ||
| 116 | 123 | ||
| 117 | {TextureFormat::DXN2, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXN2UNORM}, | 124 | {TextureFormat::BC5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC5_UNORM}, |
| 118 | {TextureFormat::DXN2, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::DXN2SNORM}, | 125 | {TextureFormat::BC5, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::BC5_SNORM}, |
| 119 | 126 | ||
| 120 | {TextureFormat::BC7U, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7U}, | 127 | {TextureFormat::BC7, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7_UNORM}, |
| 121 | {TextureFormat::BC7U, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7U_SRGB}, | 128 | {TextureFormat::BC7, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7_SRGB}, |
| 122 | 129 | ||
| 123 | {TextureFormat::BC6H_SF16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_SF16}, | 130 | {TextureFormat::BC6H_SFLOAT, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_SFLOAT}, |
| 124 | {TextureFormat::BC6H_UF16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_UF16}, | 131 | {TextureFormat::BC6H_UFLOAT, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_UFLOAT}, |
| 125 | 132 | ||
| 126 | {TextureFormat::ASTC_2D_4X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4}, | 133 | {TextureFormat::ASTC_2D_4X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4_UNORM}, |
| 127 | {TextureFormat::ASTC_2D_4X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4_SRGB}, | 134 | {TextureFormat::ASTC_2D_4X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4_SRGB}, |
| 128 | 135 | ||
| 129 | {TextureFormat::ASTC_2D_5X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4}, | 136 | {TextureFormat::ASTC_2D_5X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4_UNORM}, |
| 130 | {TextureFormat::ASTC_2D_5X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4_SRGB}, | 137 | {TextureFormat::ASTC_2D_5X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4_SRGB}, |
| 131 | 138 | ||
| 132 | {TextureFormat::ASTC_2D_5X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5}, | 139 | {TextureFormat::ASTC_2D_5X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5_UNORM}, |
| 133 | {TextureFormat::ASTC_2D_5X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5_SRGB}, | 140 | {TextureFormat::ASTC_2D_5X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5_SRGB}, |
| 134 | 141 | ||
| 135 | {TextureFormat::ASTC_2D_8X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8}, | 142 | {TextureFormat::ASTC_2D_8X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8_UNORM}, |
| 136 | {TextureFormat::ASTC_2D_8X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8_SRGB}, | 143 | {TextureFormat::ASTC_2D_8X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8_SRGB}, |
| 137 | 144 | ||
| 138 | {TextureFormat::ASTC_2D_8X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5}, | 145 | {TextureFormat::ASTC_2D_8X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5_UNORM}, |
| 139 | {TextureFormat::ASTC_2D_8X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5_SRGB}, | 146 | {TextureFormat::ASTC_2D_8X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5_SRGB}, |
| 140 | 147 | ||
| 141 | {TextureFormat::ASTC_2D_10X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8}, | 148 | {TextureFormat::ASTC_2D_10X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8_UNORM}, |
| 142 | {TextureFormat::ASTC_2D_10X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8_SRGB}, | 149 | {TextureFormat::ASTC_2D_10X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8_SRGB}, |
| 143 | 150 | ||
| 144 | {TextureFormat::ASTC_2D_6X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6}, | 151 | {TextureFormat::ASTC_2D_6X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6_UNORM}, |
| 145 | {TextureFormat::ASTC_2D_6X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6_SRGB}, | 152 | {TextureFormat::ASTC_2D_6X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6_SRGB}, |
| 146 | 153 | ||
| 147 | {TextureFormat::ASTC_2D_10X10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10}, | 154 | {TextureFormat::ASTC_2D_10X10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10_UNORM}, |
| 148 | {TextureFormat::ASTC_2D_10X10, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10_SRGB}, | 155 | {TextureFormat::ASTC_2D_10X10, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10_SRGB}, |
| 149 | 156 | ||
| 150 | {TextureFormat::ASTC_2D_12X12, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12}, | 157 | {TextureFormat::ASTC_2D_12X12, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12_UNORM}, |
| 151 | {TextureFormat::ASTC_2D_12X12, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12_SRGB}, | 158 | {TextureFormat::ASTC_2D_12X12, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12_SRGB}, |
| 152 | 159 | ||
| 153 | {TextureFormat::ASTC_2D_8X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6}, | 160 | {TextureFormat::ASTC_2D_8X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6_UNORM}, |
| 154 | {TextureFormat::ASTC_2D_8X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6_SRGB}, | 161 | {TextureFormat::ASTC_2D_8X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6_SRGB}, |
| 155 | 162 | ||
| 156 | {TextureFormat::ASTC_2D_6X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5}, | 163 | {TextureFormat::ASTC_2D_6X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5_UNORM}, |
| 157 | {TextureFormat::ASTC_2D_6X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5_SRGB}, | 164 | {TextureFormat::ASTC_2D_6X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5_SRGB}, |
| 158 | }}; | 165 | }}; |
| 159 | 166 | ||
| @@ -184,7 +191,7 @@ PixelFormat FormatLookupTable::GetPixelFormat(TextureFormat format, bool is_srgb | |||
| 184 | static_cast<int>(format), is_srgb, static_cast<int>(red_component), | 191 | static_cast<int>(format), is_srgb, static_cast<int>(red_component), |
| 185 | static_cast<int>(green_component), static_cast<int>(blue_component), | 192 | static_cast<int>(green_component), static_cast<int>(blue_component), |
| 186 | static_cast<int>(alpha_component)); | 193 | static_cast<int>(alpha_component)); |
| 187 | return PixelFormat::ABGR8U; | 194 | return PixelFormat::A8B8G8R8_UNORM; |
| 188 | } | 195 | } |
| 189 | 196 | ||
| 190 | void FormatLookupTable::Set(TextureFormat format, bool is_srgb, ComponentType red_component, | 197 | void FormatLookupTable::Set(TextureFormat format, bool is_srgb, ComponentType red_component, |
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp index 0caf3b4f0..dfcf36e0b 100644 --- a/src/video_core/texture_cache/surface_base.cpp +++ b/src/video_core/texture_cache/surface_base.cpp | |||
| @@ -228,7 +228,7 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager, | |||
| 228 | } | 228 | } |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | if (!is_converted && params.pixel_format != PixelFormat::S8Z24) { | 231 | if (!is_converted && params.pixel_format != PixelFormat::S8_UINT_D24_UNORM) { |
| 232 | return; | 232 | return; |
| 233 | } | 233 | } |
| 234 | 234 | ||
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp index 921562c1f..9e5fe2374 100644 --- a/src/video_core/texture_cache/surface_params.cpp +++ b/src/video_core/texture_cache/surface_params.cpp | |||
| @@ -83,12 +83,12 @@ SurfaceParams SurfaceParams::CreateForTexture(const FormatLookupTable& lookup_ta | |||
| 83 | params.type = GetFormatType(params.pixel_format); | 83 | params.type = GetFormatType(params.pixel_format); |
| 84 | if (entry.is_shadow && params.type == SurfaceType::ColorTexture) { | 84 | if (entry.is_shadow && params.type == SurfaceType::ColorTexture) { |
| 85 | switch (params.pixel_format) { | 85 | switch (params.pixel_format) { |
| 86 | case PixelFormat::R16U: | 86 | case PixelFormat::R16_UNORM: |
| 87 | case PixelFormat::R16F: | 87 | case PixelFormat::R16_FLOAT: |
| 88 | params.pixel_format = PixelFormat::Z16; | 88 | params.pixel_format = PixelFormat::D16_UNORM; |
| 89 | break; | 89 | break; |
| 90 | case PixelFormat::R32F: | 90 | case PixelFormat::R32_FLOAT: |
| 91 | params.pixel_format = PixelFormat::Z32F; | 91 | params.pixel_format = PixelFormat::D32_FLOAT; |
| 92 | break; | 92 | break; |
| 93 | default: | 93 | default: |
| 94 | UNIMPLEMENTED_MSG("Unimplemented shadow convert format: {}", | 94 | UNIMPLEMENTED_MSG("Unimplemented shadow convert format: {}", |
| @@ -195,8 +195,8 @@ SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::siz | |||
| 195 | SurfaceParams params; | 195 | SurfaceParams params; |
| 196 | params.is_tiled = | 196 | params.is_tiled = |
| 197 | config.memory_layout.type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear; | 197 | config.memory_layout.type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear; |
| 198 | params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB || | 198 | params.srgb_conversion = config.format == Tegra::RenderTargetFormat::B8G8R8A8_SRGB || |
| 199 | config.format == Tegra::RenderTargetFormat::RGBA8_SRGB; | 199 | config.format == Tegra::RenderTargetFormat::A8B8G8R8_SRGB; |
| 200 | params.block_width = config.memory_layout.block_width; | 200 | params.block_width = config.memory_layout.block_width; |
| 201 | params.block_height = config.memory_layout.block_height; | 201 | params.block_height = config.memory_layout.block_height; |
| 202 | params.block_depth = config.memory_layout.block_depth; | 202 | params.block_depth = config.memory_layout.block_depth; |
| @@ -235,8 +235,8 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface( | |||
| 235 | const Tegra::Engines::Fermi2D::Regs::Surface& config) { | 235 | const Tegra::Engines::Fermi2D::Regs::Surface& config) { |
| 236 | SurfaceParams params{}; | 236 | SurfaceParams params{}; |
| 237 | params.is_tiled = !config.linear; | 237 | params.is_tiled = !config.linear; |
| 238 | params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB || | 238 | params.srgb_conversion = config.format == Tegra::RenderTargetFormat::B8G8R8A8_SRGB || |
| 239 | config.format == Tegra::RenderTargetFormat::RGBA8_SRGB; | 239 | config.format == Tegra::RenderTargetFormat::A8B8G8R8_SRGB; |
| 240 | params.block_width = params.is_tiled ? std::min(config.BlockWidth(), 5U) : 0, | 240 | params.block_width = params.is_tiled ? std::min(config.BlockWidth(), 5U) : 0, |
| 241 | params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 5U) : 0, | 241 | params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 5U) : 0, |
| 242 | params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 5U) : 0, | 242 | params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 5U) : 0, |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index cdcddb225..96c4e4cc2 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -373,9 +373,9 @@ protected: | |||
| 373 | siblings_table[static_cast<std::size_t>(b)] = a; | 373 | siblings_table[static_cast<std::size_t>(b)] = a; |
| 374 | }; | 374 | }; |
| 375 | std::fill(siblings_table.begin(), siblings_table.end(), PixelFormat::Invalid); | 375 | std::fill(siblings_table.begin(), siblings_table.end(), PixelFormat::Invalid); |
| 376 | make_siblings(PixelFormat::Z16, PixelFormat::R16U); | 376 | make_siblings(PixelFormat::D16_UNORM, PixelFormat::R16_UNORM); |
| 377 | make_siblings(PixelFormat::Z32F, PixelFormat::R32F); | 377 | make_siblings(PixelFormat::D32_FLOAT, PixelFormat::R32_FLOAT); |
| 378 | make_siblings(PixelFormat::Z32FS8, PixelFormat::RG32F); | 378 | make_siblings(PixelFormat::D32_FLOAT_S8_UINT, PixelFormat::R32G32_FLOAT); |
| 379 | 379 | ||
| 380 | sampled_textures.reserve(64); | 380 | sampled_textures.reserve(64); |
| 381 | } | 381 | } |
| @@ -1031,7 +1031,7 @@ private: | |||
| 1031 | params.pitch = 4; | 1031 | params.pitch = 4; |
| 1032 | params.num_levels = 1; | 1032 | params.num_levels = 1; |
| 1033 | params.emulated_levels = 1; | 1033 | params.emulated_levels = 1; |
| 1034 | params.pixel_format = VideoCore::Surface::PixelFormat::R8U; | 1034 | params.pixel_format = VideoCore::Surface::PixelFormat::R8_UNORM; |
| 1035 | params.type = VideoCore::Surface::SurfaceType::ColorTexture; | 1035 | params.type = VideoCore::Surface::SurfaceType::ColorTexture; |
| 1036 | auto surface = CreateSurface(0ULL, params); | 1036 | auto surface = CreateSurface(0ULL, params); |
| 1037 | invalid_memory.resize(surface->GetHostSizeInBytes(), 0U); | 1037 | invalid_memory.resize(surface->GetHostSizeInBytes(), 0U); |
diff --git a/src/video_core/textures/convert.cpp b/src/video_core/textures/convert.cpp index f3efa7eb0..962921483 100644 --- a/src/video_core/textures/convert.cpp +++ b/src/video_core/textures/convert.cpp | |||
| @@ -35,7 +35,7 @@ void SwapS8Z24ToZ24S8(u8* data, u32 width, u32 height) { | |||
| 35 | S8Z24 s8z24_pixel{}; | 35 | S8Z24 s8z24_pixel{}; |
| 36 | Z24S8 z24s8_pixel{}; | 36 | Z24S8 z24s8_pixel{}; |
| 37 | constexpr auto bpp{ | 37 | constexpr auto bpp{ |
| 38 | VideoCore::Surface::GetBytesPerPixel(VideoCore::Surface::PixelFormat::S8Z24)}; | 38 | VideoCore::Surface::GetBytesPerPixel(VideoCore::Surface::PixelFormat::S8_UINT_D24_UNORM)}; |
| 39 | for (std::size_t y = 0; y < height; ++y) { | 39 | for (std::size_t y = 0; y < height; ++y) { |
| 40 | for (std::size_t x = 0; x < width; ++x) { | 40 | for (std::size_t x = 0; x < width; ++x) { |
| 41 | const std::size_t offset{bpp * (y * width + x)}; | 41 | const std::size_t offset{bpp * (y * width + x)}; |
| @@ -73,7 +73,7 @@ void ConvertFromGuestToHost(u8* in_data, u8* out_data, PixelFormat pixel_format, | |||
| 73 | in_data, width, height, depth, block_width, block_height); | 73 | in_data, width, height, depth, block_width, block_height); |
| 74 | std::copy(rgba8_data.begin(), rgba8_data.end(), out_data); | 74 | std::copy(rgba8_data.begin(), rgba8_data.end(), out_data); |
| 75 | 75 | ||
| 76 | } else if (convert_s8z24 && pixel_format == PixelFormat::S8Z24) { | 76 | } else if (convert_s8z24 && pixel_format == PixelFormat::S8_UINT_D24_UNORM) { |
| 77 | Tegra::Texture::ConvertS8Z24ToZ24S8(in_data, width, height); | 77 | Tegra::Texture::ConvertS8Z24ToZ24S8(in_data, width, height); |
| 78 | } | 78 | } |
| 79 | } | 79 | } |
| @@ -85,7 +85,7 @@ void ConvertFromHostToGuest(u8* data, PixelFormat pixel_format, u32 width, u32 h | |||
| 85 | static_cast<u32>(pixel_format)); | 85 | static_cast<u32>(pixel_format)); |
| 86 | UNREACHABLE(); | 86 | UNREACHABLE(); |
| 87 | 87 | ||
| 88 | } else if (convert_s8z24 && pixel_format == PixelFormat::S8Z24) { | 88 | } else if (convert_s8z24 && pixel_format == PixelFormat::S8_UINT_D24_UNORM) { |
| 89 | Tegra::Texture::ConvertZ24S8ToS8Z24(data, width, height); | 89 | Tegra::Texture::ConvertZ24S8ToS8Z24(data, width, height); |
| 90 | } | 90 | } |
| 91 | } | 91 | } |
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 98beabef1..474ae620a 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp | |||
| @@ -184,53 +184,6 @@ void CopySwizzledData(u32 width, u32 height, u32 depth, u32 bytes_per_pixel, | |||
| 184 | } | 184 | } |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | u32 BytesPerPixel(TextureFormat format) { | ||
| 188 | switch (format) { | ||
| 189 | case TextureFormat::DXT1: | ||
| 190 | case TextureFormat::DXN1: | ||
| 191 | // In this case a 'pixel' actually refers to a 4x4 tile. | ||
| 192 | return 8; | ||
| 193 | case TextureFormat::DXT23: | ||
| 194 | case TextureFormat::DXT45: | ||
| 195 | case TextureFormat::DXN2: | ||
| 196 | case TextureFormat::BC7U: | ||
| 197 | case TextureFormat::BC6H_UF16: | ||
| 198 | case TextureFormat::BC6H_SF16: | ||
| 199 | // In this case a 'pixel' actually refers to a 4x4 tile. | ||
| 200 | return 16; | ||
| 201 | case TextureFormat::R32_G32_B32: | ||
| 202 | return 12; | ||
| 203 | case TextureFormat::ASTC_2D_4X4: | ||
| 204 | case TextureFormat::ASTC_2D_5X4: | ||
| 205 | case TextureFormat::ASTC_2D_8X8: | ||
| 206 | case TextureFormat::ASTC_2D_8X5: | ||
| 207 | case TextureFormat::ASTC_2D_10X8: | ||
| 208 | case TextureFormat::ASTC_2D_5X5: | ||
| 209 | case TextureFormat::A8R8G8B8: | ||
| 210 | case TextureFormat::A2B10G10R10: | ||
| 211 | case TextureFormat::BF10GF11RF11: | ||
| 212 | case TextureFormat::R32: | ||
| 213 | case TextureFormat::R16_G16: | ||
| 214 | return 4; | ||
| 215 | case TextureFormat::A1B5G5R5: | ||
| 216 | case TextureFormat::B5G6R5: | ||
| 217 | case TextureFormat::G8R8: | ||
| 218 | case TextureFormat::R16: | ||
| 219 | return 2; | ||
| 220 | case TextureFormat::R8: | ||
| 221 | return 1; | ||
| 222 | case TextureFormat::R16_G16_B16_A16: | ||
| 223 | return 8; | ||
| 224 | case TextureFormat::R32_G32_B32_A32: | ||
| 225 | return 16; | ||
| 226 | case TextureFormat::R32_G32: | ||
| 227 | return 8; | ||
| 228 | default: | ||
| 229 | UNIMPLEMENTED_MSG("Format not implemented"); | ||
| 230 | return 1; | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | void UnswizzleTexture(u8* const unswizzled_data, u8* address, u32 tile_size_x, u32 tile_size_y, | 187 | void UnswizzleTexture(u8* const unswizzled_data, u8* address, u32 tile_size_x, u32 tile_size_y, |
| 235 | u32 bytes_per_pixel, u32 width, u32 height, u32 depth, u32 block_height, | 188 | u32 bytes_per_pixel, u32 width, u32 height, u32 depth, u32 block_height, |
| 236 | u32 block_depth, u32 width_spacing) { | 189 | u32 block_depth, u32 width_spacing) { |
| @@ -348,48 +301,6 @@ void SwizzleKepler(const u32 width, const u32 height, const u32 dst_x, const u32 | |||
| 348 | } | 301 | } |
| 349 | } | 302 | } |
| 350 | 303 | ||
| 351 | std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width, | ||
| 352 | u32 height) { | ||
| 353 | std::vector<u8> rgba_data; | ||
| 354 | |||
| 355 | // TODO(Subv): Implement. | ||
| 356 | switch (format) { | ||
| 357 | case TextureFormat::DXT1: | ||
| 358 | case TextureFormat::DXT23: | ||
| 359 | case TextureFormat::DXT45: | ||
| 360 | case TextureFormat::DXN1: | ||
| 361 | case TextureFormat::DXN2: | ||
| 362 | case TextureFormat::BC7U: | ||
| 363 | case TextureFormat::BC6H_UF16: | ||
| 364 | case TextureFormat::BC6H_SF16: | ||
| 365 | case TextureFormat::ASTC_2D_4X4: | ||
| 366 | case TextureFormat::ASTC_2D_8X8: | ||
| 367 | case TextureFormat::ASTC_2D_5X5: | ||
| 368 | case TextureFormat::ASTC_2D_10X8: | ||
| 369 | case TextureFormat::A8R8G8B8: | ||
| 370 | case TextureFormat::A2B10G10R10: | ||
| 371 | case TextureFormat::A1B5G5R5: | ||
| 372 | case TextureFormat::B5G6R5: | ||
| 373 | case TextureFormat::R8: | ||
| 374 | case TextureFormat::G8R8: | ||
| 375 | case TextureFormat::BF10GF11RF11: | ||
| 376 | case TextureFormat::R32_G32_B32_A32: | ||
| 377 | case TextureFormat::R32_G32: | ||
| 378 | case TextureFormat::R32: | ||
| 379 | case TextureFormat::R16: | ||
| 380 | case TextureFormat::R16_G16: | ||
| 381 | case TextureFormat::R32_G32_B32: | ||
| 382 | // TODO(Subv): For the time being just forward the same data without any decoding. | ||
| 383 | rgba_data = texture_data; | ||
| 384 | break; | ||
| 385 | default: | ||
| 386 | UNIMPLEMENTED_MSG("Format not implemented"); | ||
| 387 | break; | ||
| 388 | } | ||
| 389 | |||
| 390 | return rgba_data; | ||
| 391 | } | ||
| 392 | |||
| 393 | std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, | 304 | std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, |
| 394 | u32 block_height, u32 block_depth) { | 305 | u32 block_height, u32 block_depth) { |
| 395 | if (tiled) { | 306 | if (tiled) { |
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h index 232b696b3..d6fe35d37 100644 --- a/src/video_core/textures/decoders.h +++ b/src/video_core/textures/decoders.h | |||
| @@ -38,10 +38,6 @@ void CopySwizzledData(u32 width, u32 height, u32 depth, u32 bytes_per_pixel, | |||
| 38 | u32 out_bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, | 38 | u32 out_bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, |
| 39 | bool unswizzle, u32 block_height, u32 block_depth, u32 width_spacing); | 39 | bool unswizzle, u32 block_height, u32 block_depth, u32 width_spacing); |
| 40 | 40 | ||
| 41 | /// Decodes an unswizzled texture into a A8R8G8B8 texture. | ||
| 42 | std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width, | ||
| 43 | u32 height); | ||
| 44 | |||
| 45 | /// This function calculates the correct size of a texture depending if it's tiled or not. | 41 | /// This function calculates the correct size of a texture depending if it's tiled or not. |
| 46 | std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, | 42 | std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, |
| 47 | u32 block_height, u32 block_depth); | 43 | u32 block_height, u32 block_depth); |
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h index eba05aced..0574fef12 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h | |||
| @@ -12,10 +12,10 @@ | |||
| 12 | namespace Tegra::Texture { | 12 | namespace Tegra::Texture { |
| 13 | 13 | ||
| 14 | enum class TextureFormat : u32 { | 14 | enum class TextureFormat : u32 { |
| 15 | R32_G32_B32_A32 = 0x01, | 15 | R32G32B32A32 = 0x01, |
| 16 | R32_G32_B32 = 0x02, | 16 | R32G32B32 = 0x02, |
| 17 | R16_G16_B16_A16 = 0x03, | 17 | R16G16B16A16 = 0x03, |
| 18 | R32_G32 = 0x04, | 18 | R32G32 = 0x04, |
| 19 | R32_B24G8 = 0x05, | 19 | R32_B24G8 = 0x05, |
| 20 | ETC2_RGB = 0x06, | 20 | ETC2_RGB = 0x06, |
| 21 | X8B8G8R8 = 0x07, | 21 | X8B8G8R8 = 0x07, |
| @@ -23,19 +23,19 @@ enum class TextureFormat : u32 { | |||
| 23 | A2B10G10R10 = 0x09, | 23 | A2B10G10R10 = 0x09, |
| 24 | ETC2_RGB_PTA = 0x0a, | 24 | ETC2_RGB_PTA = 0x0a, |
| 25 | ETC2_RGBA = 0x0b, | 25 | ETC2_RGBA = 0x0b, |
| 26 | R16_G16 = 0x0c, | 26 | R16G16 = 0x0c, |
| 27 | G8R24 = 0x0d, | 27 | R24G8 = 0x0d, |
| 28 | G24R8 = 0x0e, | 28 | R8G24 = 0x0e, |
| 29 | R32 = 0x0f, | 29 | R32 = 0x0f, |
| 30 | BC6H_SF16 = 0x10, | 30 | BC6H_SFLOAT = 0x10, |
| 31 | BC6H_UF16 = 0x11, | 31 | BC6H_UFLOAT = 0x11, |
| 32 | A4B4G4R4 = 0x12, | 32 | A4B4G4R4 = 0x12, |
| 33 | A5B5G5R1 = 0x13, | 33 | A5B5G5R1 = 0x13, |
| 34 | A1B5G5R5 = 0x14, | 34 | A1B5G5R5 = 0x14, |
| 35 | B5G6R5 = 0x15, | 35 | B5G6R5 = 0x15, |
| 36 | B6G5R5 = 0x16, | 36 | B6G5R5 = 0x16, |
| 37 | BC7U = 0x17, | 37 | BC7 = 0x17, |
| 38 | G8R8 = 0x18, | 38 | R8G8 = 0x18, |
| 39 | EAC = 0x19, | 39 | EAC = 0x19, |
| 40 | EACX2 = 0x1a, | 40 | EACX2 = 0x1a, |
| 41 | R16 = 0x1b, | 41 | R16 = 0x1b, |
| @@ -43,23 +43,23 @@ enum class TextureFormat : u32 { | |||
| 43 | R8 = 0x1d, | 43 | R8 = 0x1d, |
| 44 | G4R4 = 0x1e, | 44 | G4R4 = 0x1e, |
| 45 | R1 = 0x1f, | 45 | R1 = 0x1f, |
| 46 | E5B9G9R9_SHAREDEXP = 0x20, | 46 | E5B9G9R9 = 0x20, |
| 47 | BF10GF11RF11 = 0x21, | 47 | B10G11R11 = 0x21, |
| 48 | G8B8G8R8 = 0x22, | 48 | G8B8G8R8 = 0x22, |
| 49 | B8G8R8G8 = 0x23, | 49 | B8G8R8G8 = 0x23, |
| 50 | DXT1 = 0x24, | 50 | BC1_RGBA = 0x24, |
| 51 | DXT23 = 0x25, | 51 | BC2 = 0x25, |
| 52 | DXT45 = 0x26, | 52 | BC3 = 0x26, |
| 53 | DXN1 = 0x27, | 53 | BC4 = 0x27, |
| 54 | DXN2 = 0x28, | 54 | BC5 = 0x28, |
| 55 | S8Z24 = 0x29, | 55 | S8D24 = 0x29, |
| 56 | X8Z24 = 0x2a, | 56 | X8Z24 = 0x2a, |
| 57 | Z24S8 = 0x2b, | 57 | D24S8 = 0x2b, |
| 58 | X4V4Z24__COV4R4V = 0x2c, | 58 | X4V4Z24__COV4R4V = 0x2c, |
| 59 | X4V4Z24__COV8R8V = 0x2d, | 59 | X4V4Z24__COV8R8V = 0x2d, |
| 60 | V8Z24__COV4R12V = 0x2e, | 60 | V8Z24__COV4R12V = 0x2e, |
| 61 | ZF32 = 0x2f, | 61 | D32 = 0x2f, |
| 62 | ZF32_X24S8 = 0x30, | 62 | D32S8 = 0x30, |
| 63 | X8Z24_X20V4S8__COV4R4V = 0x31, | 63 | X8Z24_X20V4S8__COV4R4V = 0x31, |
| 64 | X8Z24_X20V4S8__COV8R8V = 0x32, | 64 | X8Z24_X20V4S8__COV8R8V = 0x32, |
| 65 | ZF32_X20V4X8__COV4R4V = 0x33, | 65 | ZF32_X20V4X8__COV4R4V = 0x33, |
| @@ -69,7 +69,7 @@ enum class TextureFormat : u32 { | |||
| 69 | X8Z24_X16V8S8__COV4R12V = 0x37, | 69 | X8Z24_X16V8S8__COV4R12V = 0x37, |
| 70 | ZF32_X16V8X8__COV4R12V = 0x38, | 70 | ZF32_X16V8X8__COV4R12V = 0x38, |
| 71 | ZF32_X16V8S8__COV4R12V = 0x39, | 71 | ZF32_X16V8S8__COV4R12V = 0x39, |
| 72 | Z16 = 0x3a, | 72 | D16 = 0x3a, |
| 73 | V8Z24__COV8R24V = 0x3b, | 73 | V8Z24__COV8R24V = 0x3b, |
| 74 | X8Z24_X16V8S8__COV8R24V = 0x3c, | 74 | X8Z24_X16V8S8__COV8R24V = 0x3c, |
| 75 | ZF32_X16V8X8__COV8R24V = 0x3d, | 75 | ZF32_X16V8X8__COV8R24V = 0x3d, |
| @@ -375,7 +375,4 @@ struct FullTextureInfo { | |||
| 375 | TSCEntry tsc; | 375 | TSCEntry tsc; |
| 376 | }; | 376 | }; |
| 377 | 377 | ||
| 378 | /// Returns the number of bytes per pixel of the input texture format. | ||
| 379 | u32 BytesPerPixel(TextureFormat format); | ||
| 380 | |||
| 381 | } // namespace Tegra::Texture | 378 | } // namespace Tegra::Texture |
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index a862b2610..656096c9f 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -133,11 +133,44 @@ file(GLOB COMPAT_LIST | |||
| 133 | file(GLOB_RECURSE ICONS ${PROJECT_SOURCE_DIR}/dist/icons/*) | 133 | file(GLOB_RECURSE ICONS ${PROJECT_SOURCE_DIR}/dist/icons/*) |
| 134 | file(GLOB_RECURSE THEMES ${PROJECT_SOURCE_DIR}/dist/qt_themes/*) | 134 | file(GLOB_RECURSE THEMES ${PROJECT_SOURCE_DIR}/dist/qt_themes/*) |
| 135 | 135 | ||
| 136 | if (ENABLE_QT_TRANSLATION) | ||
| 137 | set(YUZU_QT_LANGUAGES "${PROJECT_SOURCE_DIR}/dist/languages" CACHE PATH "Path to the translation bundle for the Qt frontend") | ||
| 138 | option(GENERATE_QT_TRANSLATION "Generate en.ts as the translation source file" OFF) | ||
| 139 | |||
| 140 | # Update source TS file if enabled | ||
| 141 | if (GENERATE_QT_TRANSLATION) | ||
| 142 | get_target_property(SRCS yuzu SOURCES) | ||
| 143 | qt5_create_translation(QM_FILES ${SRCS} ${UIS} ${YUZU_QT_LANGUAGES}/en.ts) | ||
| 144 | add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts) | ||
| 145 | endif() | ||
| 146 | |||
| 147 | # Find all TS files except en.ts | ||
| 148 | file(GLOB_RECURSE LANGUAGES_TS ${YUZU_QT_LANGUAGES}/*.ts) | ||
| 149 | list(REMOVE_ITEM LANGUAGES_TS ${YUZU_QT_LANGUAGES}/en.ts) | ||
| 150 | |||
| 151 | # Compile TS files to QM files | ||
| 152 | qt5_add_translation(LANGUAGES_QM ${LANGUAGES_TS}) | ||
| 153 | |||
| 154 | # Build a QRC file from the QM file list | ||
| 155 | set(LANGUAGES_QRC ${CMAKE_CURRENT_BINARY_DIR}/languages.qrc) | ||
| 156 | file(WRITE ${LANGUAGES_QRC} "<RCC><qresource prefix=\"languages\">\n") | ||
| 157 | foreach (QM ${LANGUAGES_QM}) | ||
| 158 | get_filename_component(QM_FILE ${QM} NAME) | ||
| 159 | file(APPEND ${LANGUAGES_QRC} "<file>${QM_FILE}</file>\n") | ||
| 160 | endforeach (QM) | ||
| 161 | file(APPEND ${LANGUAGES_QRC} "</qresource></RCC>") | ||
| 162 | |||
| 163 | # Add the QRC file to package in all QM files | ||
| 164 | qt5_add_resources(LANGUAGES ${LANGUAGES_QRC}) | ||
| 165 | else() | ||
| 166 | set(LANGUAGES) | ||
| 167 | endif() | ||
| 136 | 168 | ||
| 137 | target_sources(yuzu | 169 | target_sources(yuzu |
| 138 | PRIVATE | 170 | PRIVATE |
| 139 | ${COMPAT_LIST} | 171 | ${COMPAT_LIST} |
| 140 | ${ICONS} | 172 | ${ICONS} |
| 173 | ${LANGUAGES} | ||
| 141 | ${THEMES} | 174 | ${THEMES} |
| 142 | ) | 175 | ) |
| 143 | 176 | ||
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index d25b99a32..59a193edd 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -611,6 +611,7 @@ void Config::ReadPathValues() { | |||
| 611 | } | 611 | } |
| 612 | } | 612 | } |
| 613 | UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList(); | 613 | UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList(); |
| 614 | UISettings::values.language = ReadSetting(QStringLiteral("language"), QString{}).toString(); | ||
| 614 | 615 | ||
| 615 | qt_config->endGroup(); | 616 | qt_config->endGroup(); |
| 616 | } | 617 | } |
| @@ -661,6 +662,8 @@ void Config::ReadRendererValues() { | |||
| 661 | ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true); | 662 | ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true); |
| 662 | ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"), | 663 | ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"), |
| 663 | false); | 664 | false); |
| 665 | ReadSettingGlobal(Settings::values.use_asynchronous_shaders, | ||
| 666 | QStringLiteral("use_asynchronous_shaders"), false); | ||
| 664 | ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"), | 667 | ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"), |
| 665 | true); | 668 | true); |
| 666 | ReadSettingGlobal(Settings::values.force_30fps_mode, QStringLiteral("force_30fps_mode"), false); | 669 | ReadSettingGlobal(Settings::values.force_30fps_mode, QStringLiteral("force_30fps_mode"), false); |
| @@ -1093,6 +1096,7 @@ void Config::SavePathValues() { | |||
| 1093 | } | 1096 | } |
| 1094 | qt_config->endArray(); | 1097 | qt_config->endArray(); |
| 1095 | WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files); | 1098 | WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files); |
| 1099 | WriteSetting(QStringLiteral("language"), UISettings::values.language, QString{}); | ||
| 1096 | 1100 | ||
| 1097 | qt_config->endGroup(); | 1101 | qt_config->endGroup(); |
| 1098 | } | 1102 | } |
| @@ -1145,6 +1149,8 @@ void Config::SaveRendererValues() { | |||
| 1145 | WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true); | 1149 | WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true); |
| 1146 | WriteSettingGlobal(QStringLiteral("use_assembly_shaders"), | 1150 | WriteSettingGlobal(QStringLiteral("use_assembly_shaders"), |
| 1147 | Settings::values.use_assembly_shaders, false); | 1151 | Settings::values.use_assembly_shaders, false); |
| 1152 | WriteSettingGlobal(QStringLiteral("use_asynchronous_shaders"), | ||
| 1153 | Settings::values.use_asynchronous_shaders, false); | ||
| 1148 | WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time, | 1154 | WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time, |
| 1149 | true); | 1155 | true); |
| 1150 | WriteSettingGlobal(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode, | 1156 | WriteSettingGlobal(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode, |
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index a5afb354f..4e30dc51e 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -23,6 +23,7 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) | |||
| 23 | SetConfiguration(); | 23 | SetConfiguration(); |
| 24 | PopulateSelectionList(); | 24 | PopulateSelectionList(); |
| 25 | 25 | ||
| 26 | connect(ui->uiTab, &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged); | ||
| 26 | connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, | 27 | connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, |
| 27 | &ConfigureDialog::UpdateVisibleTabs); | 28 | &ConfigureDialog::UpdateVisibleTabs); |
| 28 | 29 | ||
| @@ -98,6 +99,14 @@ void ConfigureDialog::PopulateSelectionList() { | |||
| 98 | } | 99 | } |
| 99 | } | 100 | } |
| 100 | 101 | ||
| 102 | void ConfigureDialog::OnLanguageChanged(const QString& locale) { | ||
| 103 | emit LanguageChanged(locale); | ||
| 104 | // first apply the configuration, and then restore the display | ||
| 105 | ApplyConfiguration(); | ||
| 106 | RetranslateUI(); | ||
| 107 | SetConfiguration(); | ||
| 108 | } | ||
| 109 | |||
| 101 | void ConfigureDialog::UpdateVisibleTabs() { | 110 | void ConfigureDialog::UpdateVisibleTabs() { |
| 102 | const auto items = ui->selectorList->selectedItems(); | 111 | const auto items = ui->selectorList->selectedItems(); |
| 103 | if (items.isEmpty()) { | 112 | if (items.isEmpty()) { |
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 2d3bfc2da..4289bc225 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h | |||
| @@ -22,6 +22,12 @@ public: | |||
| 22 | 22 | ||
| 23 | void ApplyConfiguration(); | 23 | void ApplyConfiguration(); |
| 24 | 24 | ||
| 25 | private slots: | ||
| 26 | void OnLanguageChanged(const QString& locale); | ||
| 27 | |||
| 28 | signals: | ||
| 29 | void LanguageChanged(const QString& locale); | ||
| 30 | |||
| 25 | private: | 31 | private: |
| 26 | void changeEvent(QEvent* event) override; | 32 | void changeEvent(QEvent* event) override; |
| 27 | 33 | ||
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index 7c0fa7ec5..ce30188cd 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp | |||
| @@ -24,6 +24,7 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { | |||
| 24 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); | 24 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); |
| 25 | ui->use_vsync->setEnabled(runtime_lock); | 25 | ui->use_vsync->setEnabled(runtime_lock); |
| 26 | ui->use_assembly_shaders->setEnabled(runtime_lock); | 26 | ui->use_assembly_shaders->setEnabled(runtime_lock); |
| 27 | ui->use_asynchronous_shaders->setEnabled(runtime_lock); | ||
| 27 | ui->force_30fps_mode->setEnabled(runtime_lock); | 28 | ui->force_30fps_mode->setEnabled(runtime_lock); |
| 28 | ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); | 29 | ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); |
| 29 | 30 | ||
| @@ -32,6 +33,8 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { | |||
| 32 | static_cast<int>(Settings::values.gpu_accuracy.GetValue())); | 33 | static_cast<int>(Settings::values.gpu_accuracy.GetValue())); |
| 33 | ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); | 34 | ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); |
| 34 | ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue()); | 35 | ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue()); |
| 36 | ui->use_asynchronous_shaders->setChecked( | ||
| 37 | Settings::values.use_asynchronous_shaders.GetValue()); | ||
| 35 | ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); | 38 | ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); |
| 36 | ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue()); | 39 | ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue()); |
| 37 | ui->anisotropic_filtering_combobox->setCurrentIndex( | 40 | ui->anisotropic_filtering_combobox->setCurrentIndex( |
| @@ -41,6 +44,10 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { | |||
| 41 | ConfigurationShared::SetPerGameSetting(ui->use_vsync, &Settings::values.use_vsync); | 44 | ConfigurationShared::SetPerGameSetting(ui->use_vsync, &Settings::values.use_vsync); |
| 42 | ConfigurationShared::SetPerGameSetting(ui->use_assembly_shaders, | 45 | ConfigurationShared::SetPerGameSetting(ui->use_assembly_shaders, |
| 43 | &Settings::values.use_assembly_shaders); | 46 | &Settings::values.use_assembly_shaders); |
| 47 | ConfigurationShared::SetPerGameSetting(ui->use_asynchronous_shaders, | ||
| 48 | &Settings::values.use_asynchronous_shaders); | ||
| 49 | ConfigurationShared::SetPerGameSetting(ui->use_asynchronous_shaders, | ||
| 50 | &Settings::values.use_asynchronous_shaders); | ||
| 44 | ConfigurationShared::SetPerGameSetting(ui->use_fast_gpu_time, | 51 | ConfigurationShared::SetPerGameSetting(ui->use_fast_gpu_time, |
| 45 | &Settings::values.use_fast_gpu_time); | 52 | &Settings::values.use_fast_gpu_time); |
| 46 | ConfigurationShared::SetPerGameSetting(ui->force_30fps_mode, | 53 | ConfigurationShared::SetPerGameSetting(ui->force_30fps_mode, |
| @@ -67,6 +74,14 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { | |||
| 67 | if (Settings::values.use_assembly_shaders.UsingGlobal()) { | 74 | if (Settings::values.use_assembly_shaders.UsingGlobal()) { |
| 68 | Settings::values.use_assembly_shaders.SetValue(ui->use_assembly_shaders->isChecked()); | 75 | Settings::values.use_assembly_shaders.SetValue(ui->use_assembly_shaders->isChecked()); |
| 69 | } | 76 | } |
| 77 | if (Settings::values.use_asynchronous_shaders.UsingGlobal()) { | ||
| 78 | Settings::values.use_asynchronous_shaders.SetValue( | ||
| 79 | ui->use_asynchronous_shaders->isChecked()); | ||
| 80 | } | ||
| 81 | if (Settings::values.use_asynchronous_shaders.UsingGlobal()) { | ||
| 82 | Settings::values.use_asynchronous_shaders.SetValue( | ||
| 83 | ui->use_asynchronous_shaders->isChecked()); | ||
| 84 | } | ||
| 70 | if (Settings::values.use_fast_gpu_time.UsingGlobal()) { | 85 | if (Settings::values.use_fast_gpu_time.UsingGlobal()) { |
| 71 | Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked()); | 86 | Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked()); |
| 72 | } | 87 | } |
| @@ -83,6 +98,10 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { | |||
| 83 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync); | 98 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync); |
| 84 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, | 99 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, |
| 85 | ui->use_assembly_shaders); | 100 | ui->use_assembly_shaders); |
| 101 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, | ||
| 102 | ui->use_asynchronous_shaders); | ||
| 103 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, | ||
| 104 | ui->use_asynchronous_shaders); | ||
| 86 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, | 105 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, |
| 87 | ui->use_fast_gpu_time); | 106 | ui->use_fast_gpu_time); |
| 88 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.force_30fps_mode, | 107 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.force_30fps_mode, |
| @@ -117,6 +136,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { | |||
| 117 | ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal()); | 136 | ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal()); |
| 118 | ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal()); | 137 | ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal()); |
| 119 | ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal()); | 138 | ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal()); |
| 139 | ui->use_asynchronous_shaders->setEnabled( | ||
| 140 | Settings::values.use_asynchronous_shaders.UsingGlobal()); | ||
| 120 | ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); | 141 | ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); |
| 121 | ui->force_30fps_mode->setEnabled(Settings::values.force_30fps_mode.UsingGlobal()); | 142 | ui->force_30fps_mode->setEnabled(Settings::values.force_30fps_mode.UsingGlobal()); |
| 122 | ui->anisotropic_filtering_combobox->setEnabled( | 143 | ui->anisotropic_filtering_combobox->setEnabled( |
| @@ -128,6 +149,7 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { | |||
| 128 | ConfigurationShared::InsertGlobalItem(ui->gpu_accuracy); | 149 | ConfigurationShared::InsertGlobalItem(ui->gpu_accuracy); |
| 129 | ui->use_vsync->setTristate(true); | 150 | ui->use_vsync->setTristate(true); |
| 130 | ui->use_assembly_shaders->setTristate(true); | 151 | ui->use_assembly_shaders->setTristate(true); |
| 152 | ui->use_asynchronous_shaders->setTristate(true); | ||
| 131 | ui->use_fast_gpu_time->setTristate(true); | 153 | ui->use_fast_gpu_time->setTristate(true); |
| 132 | ui->force_30fps_mode->setTristate(true); | 154 | ui->force_30fps_mode->setTristate(true); |
| 133 | ConfigurationShared::InsertGlobalItem(ui->anisotropic_filtering_combobox); | 155 | ConfigurationShared::InsertGlobalItem(ui->anisotropic_filtering_combobox); |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index 0021607ac..71e7dfe5e 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui | |||
| @@ -73,6 +73,16 @@ | |||
| 73 | </widget> | 73 | </widget> |
| 74 | </item> | 74 | </item> |
| 75 | <item> | 75 | <item> |
| 76 | <widget class="QCheckBox" name="use_asynchronous_shaders"> | ||
| 77 | <property name="toolTip"> | ||
| 78 | <string>Enables asynchronous shader compilation, which may reduce shader stutter. This feature is experimental.</string> | ||
| 79 | </property> | ||
| 80 | <property name="text"> | ||
| 81 | <string>Use asynchronous shader building (experimental, OpenGL or Assembly shaders only)</string> | ||
| 82 | </property> | ||
| 83 | </widget> | ||
| 84 | </item> | ||
| 85 | <item> | ||
| 76 | <widget class="QCheckBox" name="force_30fps_mode"> | 86 | <widget class="QCheckBox" name="force_30fps_mode"> |
| 77 | <property name="text"> | 87 | <property name="text"> |
| 78 | <string>Force 30 FPS mode</string> | 88 | <string>Force 30 FPS mode</string> |
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index 94424ee44..24b6c5b72 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <array> | 5 | #include <array> |
| 6 | #include <utility> | 6 | #include <utility> |
| 7 | 7 | ||
| 8 | #include <QDirIterator> | ||
| 8 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 9 | #include "core/settings.h" | 10 | #include "core/settings.h" |
| 10 | #include "ui_configure_ui.h" | 11 | #include "ui_configure_ui.h" |
| @@ -29,6 +30,8 @@ constexpr std::array row_text_names{ | |||
| 29 | ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureUi) { | 30 | ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureUi) { |
| 30 | ui->setupUi(this); | 31 | ui->setupUi(this); |
| 31 | 32 | ||
| 33 | InitializeLanguageComboBox(); | ||
| 34 | |||
| 32 | for (const auto& theme : UISettings::themes) { | 35 | for (const auto& theme : UISettings::themes) { |
| 33 | ui->theme_combobox->addItem(QString::fromUtf8(theme.first), | 36 | ui->theme_combobox->addItem(QString::fromUtf8(theme.first), |
| 34 | QString::fromUtf8(theme.second)); | 37 | QString::fromUtf8(theme.second)); |
| @@ -72,6 +75,8 @@ void ConfigureUi::RequestGameListUpdate() { | |||
| 72 | 75 | ||
| 73 | void ConfigureUi::SetConfiguration() { | 76 | void ConfigureUi::SetConfiguration() { |
| 74 | ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); | 77 | ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); |
| 78 | ui->language_combobox->setCurrentIndex( | ||
| 79 | ui->language_combobox->findData(UISettings::values.language)); | ||
| 75 | ui->show_add_ons->setChecked(UISettings::values.show_add_ons); | 80 | ui->show_add_ons->setChecked(UISettings::values.show_add_ons); |
| 76 | ui->icon_size_combobox->setCurrentIndex( | 81 | ui->icon_size_combobox->setCurrentIndex( |
| 77 | ui->icon_size_combobox->findData(UISettings::values.icon_size)); | 82 | ui->icon_size_combobox->findData(UISettings::values.icon_size)); |
| @@ -100,6 +105,25 @@ void ConfigureUi::RetranslateUI() { | |||
| 100 | } | 105 | } |
| 101 | } | 106 | } |
| 102 | 107 | ||
| 108 | void ConfigureUi::InitializeLanguageComboBox() { | ||
| 109 | ui->language_combobox->addItem(tr("<System>"), QString{}); | ||
| 110 | ui->language_combobox->addItem(tr("English"), QStringLiteral("en")); | ||
| 111 | QDirIterator it(QStringLiteral(":/languages"), QDirIterator::NoIteratorFlags); | ||
| 112 | while (it.hasNext()) { | ||
| 113 | QString locale = it.next(); | ||
| 114 | locale.truncate(locale.lastIndexOf(QLatin1Char{'.'})); | ||
| 115 | locale.remove(0, locale.lastIndexOf(QLatin1Char{'/'}) + 1); | ||
| 116 | const QString lang = QLocale::languageToString(QLocale(locale).language()); | ||
| 117 | ui->language_combobox->addItem(lang, locale); | ||
| 118 | } | ||
| 119 | |||
| 120 | // Unlike other configuration changes, interface language changes need to be reflected on the | ||
| 121 | // interface immediately. This is done by passing a signal to the main window, and then | ||
| 122 | // retranslating when passing back. | ||
| 123 | connect(ui->language_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, | ||
| 124 | &ConfigureUi::OnLanguageChanged); | ||
| 125 | } | ||
| 126 | |||
| 103 | void ConfigureUi::InitializeIconSizeComboBox() { | 127 | void ConfigureUi::InitializeIconSizeComboBox() { |
| 104 | for (const auto& size : default_icon_sizes) { | 128 | for (const auto& size : default_icon_sizes) { |
| 105 | ui->icon_size_combobox->addItem(QString::fromUtf8(size.second), size.first); | 129 | ui->icon_size_combobox->addItem(QString::fromUtf8(size.second), size.first); |
| @@ -147,3 +171,10 @@ void ConfigureUi::UpdateSecondRowComboBox(bool init) { | |||
| 147 | ui->row_2_text_combobox->removeItem( | 171 | ui->row_2_text_combobox->removeItem( |
| 148 | ui->row_2_text_combobox->findData(ui->row_1_text_combobox->currentData())); | 172 | ui->row_2_text_combobox->findData(ui->row_1_text_combobox->currentData())); |
| 149 | } | 173 | } |
| 174 | |||
| 175 | void ConfigureUi::OnLanguageChanged(int index) { | ||
| 176 | if (index == -1) | ||
| 177 | return; | ||
| 178 | |||
| 179 | emit LanguageChanged(ui->language_combobox->itemData(index).toString()); | ||
| 180 | } | ||
diff --git a/src/yuzu/configuration/configure_ui.h b/src/yuzu/configuration/configure_ui.h index d471afe99..c30bcf6ff 100644 --- a/src/yuzu/configuration/configure_ui.h +++ b/src/yuzu/configuration/configure_ui.h | |||
| @@ -20,6 +20,12 @@ public: | |||
| 20 | 20 | ||
| 21 | void ApplyConfiguration(); | 21 | void ApplyConfiguration(); |
| 22 | 22 | ||
| 23 | private slots: | ||
| 24 | void OnLanguageChanged(int index); | ||
| 25 | |||
| 26 | signals: | ||
| 27 | void LanguageChanged(const QString& locale); | ||
| 28 | |||
| 23 | private: | 29 | private: |
| 24 | void RequestGameListUpdate(); | 30 | void RequestGameListUpdate(); |
| 25 | 31 | ||
| @@ -28,6 +34,7 @@ private: | |||
| 28 | void changeEvent(QEvent*) override; | 34 | void changeEvent(QEvent*) override; |
| 29 | void RetranslateUI(); | 35 | void RetranslateUI(); |
| 30 | 36 | ||
| 37 | void InitializeLanguageComboBox(); | ||
| 31 | void InitializeIconSizeComboBox(); | 38 | void InitializeIconSizeComboBox(); |
| 32 | void InitializeRowComboBoxes(); | 39 | void InitializeRowComboBoxes(); |
| 33 | 40 | ||
diff --git a/src/yuzu/configuration/configure_ui.ui b/src/yuzu/configuration/configure_ui.ui index bd5c5d3c2..0b81747d7 100644 --- a/src/yuzu/configuration/configure_ui.ui +++ b/src/yuzu/configuration/configure_ui.ui | |||
| @@ -13,112 +13,132 @@ | |||
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| 14 | <string>Form</string> | 14 | <string>Form</string> |
| 15 | </property> | 15 | </property> |
| 16 | <layout class="QHBoxLayout" name="HorizontalLayout"> | 16 | <layout class="QVBoxLayout" name="verticalLayout"> |
| 17 | <item> | 17 | <item> |
| 18 | <layout class="QVBoxLayout" name="VerticalLayout"> | 18 | <widget class="QGroupBox" name="general_groupBox"> |
| 19 | <item> | 19 | <property name="title"> |
| 20 | <widget class="QGroupBox" name="GeneralGroupBox"> | 20 | <string>General</string> |
| 21 | <property name="title"> | 21 | </property> |
| 22 | <string>General</string> | 22 | <layout class="QHBoxLayout" name="horizontalLayout"> |
| 23 | </property> | 23 | <item> |
| 24 | <layout class="QHBoxLayout" name="horizontalLayout"> | 24 | <layout class="QVBoxLayout" name="verticalLayout_2"> |
| 25 | <item> | 25 | <item> |
| 26 | <layout class="QVBoxLayout" name="verticalLayout"> | 26 | <widget class="QLabel" name="label_change_language_info"> |
| 27 | <property name="text"> | ||
| 28 | <string>Note: Changing language will apply your configuration.</string> | ||
| 29 | </property> | ||
| 30 | <property name="wordWrap"> | ||
| 31 | <bool>true</bool> | ||
| 32 | </property> | ||
| 33 | </widget> | ||
| 34 | </item> | ||
| 35 | <item> | ||
| 36 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| 37 | <item> | ||
| 38 | <widget class="QLabel" name="language_label"> | ||
| 39 | <property name="text"> | ||
| 40 | <string>Interface language:</string> | ||
| 41 | </property> | ||
| 42 | </widget> | ||
| 43 | </item> | ||
| 44 | <item> | ||
| 45 | <widget class="QComboBox" name="language_combobox"/> | ||
| 46 | </item> | ||
| 47 | </layout> | ||
| 48 | </item> | ||
| 49 | <item> | ||
| 50 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||
| 51 | <item> | ||
| 52 | <widget class="QLabel" name="theme_label"> | ||
| 53 | <property name="text"> | ||
| 54 | <string>Theme:</string> | ||
| 55 | </property> | ||
| 56 | </widget> | ||
| 57 | </item> | ||
| 27 | <item> | 58 | <item> |
| 28 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | 59 | <widget class="QComboBox" name="theme_combobox"/> |
| 29 | <item> | ||
| 30 | <widget class="QLabel" name="theme_label"> | ||
| 31 | <property name="text"> | ||
| 32 | <string>Theme:</string> | ||
| 33 | </property> | ||
| 34 | </widget> | ||
| 35 | </item> | ||
| 36 | <item> | ||
| 37 | <widget class="QComboBox" name="theme_combobox"/> | ||
| 38 | </item> | ||
| 39 | </layout> | ||
| 40 | </item> | 60 | </item> |
| 41 | </layout> | 61 | </layout> |
| 42 | </item> | 62 | </item> |
| 43 | </layout> | 63 | </layout> |
| 44 | </widget> | 64 | </item> |
| 45 | </item> | 65 | </layout> |
| 46 | <item> | 66 | </widget> |
| 47 | <widget class="QGroupBox" name="GameListGroupBox"> | 67 | </item> |
| 48 | <property name="title"> | 68 | <item> |
| 49 | <string>Game List</string> | 69 | <widget class="QGroupBox" name="GameListGroupBox"> |
| 50 | </property> | 70 | <property name="title"> |
| 51 | <layout class="QHBoxLayout" name="GameListHorizontalLayout"> | 71 | <string>Game List</string> |
| 72 | </property> | ||
| 73 | <layout class="QHBoxLayout" name="GameListHorizontalLayout"> | ||
| 74 | <item> | ||
| 75 | <layout class="QVBoxLayout" name="GeneralVerticalLayout"> | ||
| 52 | <item> | 76 | <item> |
| 53 | <layout class="QVBoxLayout" name="GeneralVerticalLayout"> | 77 | <widget class="QCheckBox" name="show_add_ons"> |
| 78 | <property name="text"> | ||
| 79 | <string>Show Add-Ons Column</string> | ||
| 80 | </property> | ||
| 81 | </widget> | ||
| 82 | </item> | ||
| 83 | <item> | ||
| 84 | <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2"> | ||
| 54 | <item> | 85 | <item> |
| 55 | <widget class="QCheckBox" name="show_add_ons"> | 86 | <widget class="QLabel" name="icon_size_label"> |
| 56 | <property name="text"> | 87 | <property name="text"> |
| 57 | <string>Show Add-Ons Column</string> | 88 | <string>Icon Size:</string> |
| 58 | </property> | 89 | </property> |
| 59 | </widget> | 90 | </widget> |
| 60 | </item> | 91 | </item> |
| 61 | <item> | 92 | <item> |
| 62 | <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2"> | 93 | <widget class="QComboBox" name="icon_size_combobox"/> |
| 63 | <item> | ||
| 64 | <widget class="QLabel" name="icon_size_label"> | ||
| 65 | <property name="text"> | ||
| 66 | <string>Icon Size:</string> | ||
| 67 | </property> | ||
| 68 | </widget> | ||
| 69 | </item> | ||
| 70 | <item> | ||
| 71 | <widget class="QComboBox" name="icon_size_combobox"/> | ||
| 72 | </item> | ||
| 73 | </layout> | ||
| 74 | </item> | 94 | </item> |
| 95 | </layout> | ||
| 96 | </item> | ||
| 97 | <item> | ||
| 98 | <layout class="QHBoxLayout" name="row_1_qhbox_layout"> | ||
| 75 | <item> | 99 | <item> |
| 76 | <layout class="QHBoxLayout" name="row_1_qhbox_layout"> | 100 | <widget class="QLabel" name="row_1_label"> |
| 77 | <item> | 101 | <property name="text"> |
| 78 | <widget class="QLabel" name="row_1_label"> | 102 | <string>Row 1 Text:</string> |
| 79 | <property name="text"> | 103 | </property> |
| 80 | <string>Row 1 Text:</string> | 104 | </widget> |
| 81 | </property> | ||
| 82 | </widget> | ||
| 83 | </item> | ||
| 84 | <item> | ||
| 85 | <widget class="QComboBox" name="row_1_text_combobox"/> | ||
| 86 | </item> | ||
| 87 | </layout> | ||
| 88 | </item> | 105 | </item> |
| 89 | <item> | 106 | <item> |
| 90 | <layout class="QHBoxLayout" name="row_2_qhbox_layout"> | 107 | <widget class="QComboBox" name="row_1_text_combobox"/> |
| 91 | <item> | 108 | </item> |
| 92 | <widget class="QLabel" name="row_2_label"> | 109 | </layout> |
| 93 | <property name="text"> | 110 | </item> |
| 94 | <string>Row 2 Text:</string> | 111 | <item> |
| 95 | </property> | 112 | <layout class="QHBoxLayout" name="row_2_qhbox_layout"> |
| 96 | </widget> | 113 | <item> |
| 97 | </item> | 114 | <widget class="QLabel" name="row_2_label"> |
| 98 | <item> | 115 | <property name="text"> |
| 99 | <widget class="QComboBox" name="row_2_text_combobox"/> | 116 | <string>Row 2 Text:</string> |
| 100 | </item> | 117 | </property> |
| 101 | </layout> | 118 | </widget> |
| 119 | </item> | ||
| 120 | <item> | ||
| 121 | <widget class="QComboBox" name="row_2_text_combobox"/> | ||
| 102 | </item> | 122 | </item> |
| 103 | </layout> | 123 | </layout> |
| 104 | </item> | 124 | </item> |
| 105 | </layout> | 125 | </layout> |
| 106 | </widget> | 126 | </item> |
| 107 | </item> | 127 | </layout> |
| 108 | <item> | 128 | </widget> |
| 109 | <spacer name="verticalSpacer"> | 129 | </item> |
| 110 | <property name="orientation"> | 130 | <item> |
| 111 | <enum>Qt::Vertical</enum> | 131 | <spacer name="verticalSpacer"> |
| 112 | </property> | 132 | <property name="orientation"> |
| 113 | <property name="sizeHint" stdset="0"> | 133 | <enum>Qt::Vertical</enum> |
| 114 | <size> | 134 | </property> |
| 115 | <width>20</width> | 135 | <property name="sizeHint" stdset="0"> |
| 116 | <height>40</height> | 136 | <size> |
| 117 | </size> | 137 | <width>20</width> |
| 118 | </property> | 138 | <height>40</height> |
| 119 | </spacer> | 139 | </size> |
| 120 | </item> | 140 | </property> |
| 121 | </layout> | 141 | </spacer> |
| 122 | </item> | 142 | </item> |
| 123 | </layout> | 143 | </layout> |
| 124 | </widget> | 144 | </widget> |
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 9bb0a0109..f391a41a9 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp | |||
| @@ -2,9 +2,11 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <array> | ||
| 5 | #include <fmt/format.h> | 6 | #include <fmt/format.h> |
| 6 | 7 | ||
| 7 | #include "yuzu/debugger/wait_tree.h" | 8 | #include "yuzu/debugger/wait_tree.h" |
| 9 | #include "yuzu/uisettings.h" | ||
| 8 | #include "yuzu/util/util.h" | 10 | #include "yuzu/util/util.h" |
| 9 | 11 | ||
| 10 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| @@ -19,11 +21,37 @@ | |||
| 19 | #include "core/hle/kernel/thread.h" | 21 | #include "core/hle/kernel/thread.h" |
| 20 | #include "core/memory.h" | 22 | #include "core/memory.h" |
| 21 | 23 | ||
| 24 | namespace { | ||
| 25 | |||
| 26 | constexpr std::array<std::array<Qt::GlobalColor, 2>, 10> WaitTreeColors{{ | ||
| 27 | {Qt::GlobalColor::darkGreen, Qt::GlobalColor::green}, | ||
| 28 | {Qt::GlobalColor::darkGreen, Qt::GlobalColor::green}, | ||
| 29 | {Qt::GlobalColor::darkBlue, Qt::GlobalColor::cyan}, | ||
| 30 | {Qt::GlobalColor::lightGray, Qt::GlobalColor::lightGray}, | ||
| 31 | {Qt::GlobalColor::lightGray, Qt::GlobalColor::lightGray}, | ||
| 32 | {Qt::GlobalColor::darkRed, Qt::GlobalColor::red}, | ||
| 33 | {Qt::GlobalColor::darkYellow, Qt::GlobalColor::yellow}, | ||
| 34 | {Qt::GlobalColor::red, Qt::GlobalColor::red}, | ||
| 35 | {Qt::GlobalColor::darkCyan, Qt::GlobalColor::cyan}, | ||
| 36 | {Qt::GlobalColor::gray, Qt::GlobalColor::gray}, | ||
| 37 | }}; | ||
| 38 | |||
| 39 | bool IsDarkTheme() { | ||
| 40 | const auto& theme = UISettings::values.theme; | ||
| 41 | return theme == QStringLiteral("qdarkstyle") || theme == QStringLiteral("colorful_dark"); | ||
| 42 | } | ||
| 43 | |||
| 44 | } // namespace | ||
| 45 | |||
| 22 | WaitTreeItem::WaitTreeItem() = default; | 46 | WaitTreeItem::WaitTreeItem() = default; |
| 23 | WaitTreeItem::~WaitTreeItem() = default; | 47 | WaitTreeItem::~WaitTreeItem() = default; |
| 24 | 48 | ||
| 25 | QColor WaitTreeItem::GetColor() const { | 49 | QColor WaitTreeItem::GetColor() const { |
| 26 | return QColor(Qt::GlobalColor::black); | 50 | if (IsDarkTheme()) { |
| 51 | return QColor(Qt::GlobalColor::white); | ||
| 52 | } else { | ||
| 53 | return QColor(Qt::GlobalColor::black); | ||
| 54 | } | ||
| 27 | } | 55 | } |
| 28 | 56 | ||
| 29 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeItem::GetChildren() const { | 57 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeItem::GetChildren() const { |
| @@ -263,36 +291,38 @@ QString WaitTreeThread::GetText() const { | |||
| 263 | } | 291 | } |
| 264 | 292 | ||
| 265 | QColor WaitTreeThread::GetColor() const { | 293 | QColor WaitTreeThread::GetColor() const { |
| 294 | const std::size_t color_index = IsDarkTheme() ? 1 : 0; | ||
| 295 | |||
| 266 | const auto& thread = static_cast<const Kernel::Thread&>(object); | 296 | const auto& thread = static_cast<const Kernel::Thread&>(object); |
| 267 | switch (thread.GetStatus()) { | 297 | switch (thread.GetStatus()) { |
| 268 | case Kernel::ThreadStatus::Running: | 298 | case Kernel::ThreadStatus::Running: |
| 269 | return QColor(Qt::GlobalColor::darkGreen); | 299 | return QColor(WaitTreeColors[0][color_index]); |
| 270 | case Kernel::ThreadStatus::Ready: | 300 | case Kernel::ThreadStatus::Ready: |
| 271 | if (!thread.IsPaused()) { | 301 | if (!thread.IsPaused()) { |
| 272 | if (thread.WasRunning()) { | 302 | if (thread.WasRunning()) { |
| 273 | return QColor(Qt::GlobalColor::darkGreen); | 303 | return QColor(WaitTreeColors[1][color_index]); |
| 274 | } else { | 304 | } else { |
| 275 | return QColor(Qt::GlobalColor::darkBlue); | 305 | return QColor(WaitTreeColors[2][color_index]); |
| 276 | } | 306 | } |
| 277 | } else { | 307 | } else { |
| 278 | return QColor(Qt::GlobalColor::lightGray); | 308 | return QColor(WaitTreeColors[3][color_index]); |
| 279 | } | 309 | } |
| 280 | case Kernel::ThreadStatus::Paused: | 310 | case Kernel::ThreadStatus::Paused: |
| 281 | return QColor(Qt::GlobalColor::lightGray); | 311 | return QColor(WaitTreeColors[4][color_index]); |
| 282 | case Kernel::ThreadStatus::WaitHLEEvent: | 312 | case Kernel::ThreadStatus::WaitHLEEvent: |
| 283 | case Kernel::ThreadStatus::WaitIPC: | 313 | case Kernel::ThreadStatus::WaitIPC: |
| 284 | return QColor(Qt::GlobalColor::darkRed); | 314 | return QColor(WaitTreeColors[5][color_index]); |
| 285 | case Kernel::ThreadStatus::WaitSleep: | 315 | case Kernel::ThreadStatus::WaitSleep: |
| 286 | return QColor(Qt::GlobalColor::darkYellow); | 316 | return QColor(WaitTreeColors[6][color_index]); |
| 287 | case Kernel::ThreadStatus::WaitSynch: | 317 | case Kernel::ThreadStatus::WaitSynch: |
| 288 | case Kernel::ThreadStatus::WaitMutex: | 318 | case Kernel::ThreadStatus::WaitMutex: |
| 289 | case Kernel::ThreadStatus::WaitCondVar: | 319 | case Kernel::ThreadStatus::WaitCondVar: |
| 290 | case Kernel::ThreadStatus::WaitArb: | 320 | case Kernel::ThreadStatus::WaitArb: |
| 291 | return QColor(Qt::GlobalColor::red); | 321 | return QColor(WaitTreeColors[7][color_index]); |
| 292 | case Kernel::ThreadStatus::Dormant: | 322 | case Kernel::ThreadStatus::Dormant: |
| 293 | return QColor(Qt::GlobalColor::darkCyan); | 323 | return QColor(WaitTreeColors[8][color_index]); |
| 294 | case Kernel::ThreadStatus::Dead: | 324 | case Kernel::ThreadStatus::Dead: |
| 295 | return QColor(Qt::GlobalColor::gray); | 325 | return QColor(WaitTreeColors[9][color_index]); |
| 296 | default: | 326 | default: |
| 297 | return WaitTreeItem::GetColor(); | 327 | return WaitTreeItem::GetColor(); |
| 298 | } | 328 | } |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 9f758605a..31a635176 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -94,6 +94,8 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 94 | #include "core/perf_stats.h" | 94 | #include "core/perf_stats.h" |
| 95 | #include "core/settings.h" | 95 | #include "core/settings.h" |
| 96 | #include "core/telemetry_session.h" | 96 | #include "core/telemetry_session.h" |
| 97 | #include "video_core/gpu.h" | ||
| 98 | #include "video_core/shader_notify.h" | ||
| 97 | #include "yuzu/about_dialog.h" | 99 | #include "yuzu/about_dialog.h" |
| 98 | #include "yuzu/bootmanager.h" | 100 | #include "yuzu/bootmanager.h" |
| 99 | #include "yuzu/compatdb.h" | 101 | #include "yuzu/compatdb.h" |
| @@ -189,6 +191,8 @@ GMainWindow::GMainWindow() | |||
| 189 | provider(std::make_unique<FileSys::ManualContentProvider>()) { | 191 | provider(std::make_unique<FileSys::ManualContentProvider>()) { |
| 190 | InitializeLogging(); | 192 | InitializeLogging(); |
| 191 | 193 | ||
| 194 | LoadTranslation(); | ||
| 195 | |||
| 192 | setAcceptDrops(true); | 196 | setAcceptDrops(true); |
| 193 | ui.setupUi(this); | 197 | ui.setupUi(this); |
| 194 | statusBar()->hide(); | 198 | statusBar()->hide(); |
| @@ -498,6 +502,8 @@ void GMainWindow::InitializeWidgets() { | |||
| 498 | message_label->setAlignment(Qt::AlignLeft); | 502 | message_label->setAlignment(Qt::AlignLeft); |
| 499 | statusBar()->addPermanentWidget(message_label, 1); | 503 | statusBar()->addPermanentWidget(message_label, 1); |
| 500 | 504 | ||
| 505 | shader_building_label = new QLabel(); | ||
| 506 | shader_building_label->setToolTip(tr("The amount of shaders currently being built")); | ||
| 501 | emu_speed_label = new QLabel(); | 507 | emu_speed_label = new QLabel(); |
| 502 | emu_speed_label->setToolTip( | 508 | emu_speed_label->setToolTip( |
| 503 | tr("Current emulation speed. Values higher or lower than 100% " | 509 | tr("Current emulation speed. Values higher or lower than 100% " |
| @@ -510,7 +516,8 @@ void GMainWindow::InitializeWidgets() { | |||
| 510 | tr("Time taken to emulate a Switch frame, not counting framelimiting or v-sync. For " | 516 | tr("Time taken to emulate a Switch frame, not counting framelimiting or v-sync. For " |
| 511 | "full-speed emulation this should be at most 16.67 ms.")); | 517 | "full-speed emulation this should be at most 16.67 ms.")); |
| 512 | 518 | ||
| 513 | for (auto& label : {emu_speed_label, game_fps_label, emu_frametime_label}) { | 519 | for (auto& label : |
| 520 | {shader_building_label, emu_speed_label, game_fps_label, emu_frametime_label}) { | ||
| 514 | label->setVisible(false); | 521 | label->setVisible(false); |
| 515 | label->setFrameStyle(QFrame::NoFrame); | 522 | label->setFrameStyle(QFrame::NoFrame); |
| 516 | label->setContentsMargins(4, 0, 4, 0); | 523 | label->setContentsMargins(4, 0, 4, 0); |
| @@ -1176,6 +1183,7 @@ void GMainWindow::ShutdownGame() { | |||
| 1176 | 1183 | ||
| 1177 | // Disable status bar updates | 1184 | // Disable status bar updates |
| 1178 | status_bar_update_timer.stop(); | 1185 | status_bar_update_timer.stop(); |
| 1186 | shader_building_label->setVisible(false); | ||
| 1179 | emu_speed_label->setVisible(false); | 1187 | emu_speed_label->setVisible(false); |
| 1180 | game_fps_label->setVisible(false); | 1188 | game_fps_label->setVisible(false); |
| 1181 | emu_frametime_label->setVisible(false); | 1189 | emu_frametime_label->setVisible(false); |
| @@ -2042,6 +2050,9 @@ void GMainWindow::OnConfigure() { | |||
| 2042 | const bool old_discord_presence = UISettings::values.enable_discord_presence; | 2050 | const bool old_discord_presence = UISettings::values.enable_discord_presence; |
| 2043 | 2051 | ||
| 2044 | ConfigureDialog configure_dialog(this, hotkey_registry); | 2052 | ConfigureDialog configure_dialog(this, hotkey_registry); |
| 2053 | connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, | ||
| 2054 | &GMainWindow::OnLanguageChanged); | ||
| 2055 | |||
| 2045 | const auto result = configure_dialog.exec(); | 2056 | const auto result = configure_dialog.exec(); |
| 2046 | if (result != QDialog::Accepted) { | 2057 | if (result != QDialog::Accepted) { |
| 2047 | return; | 2058 | return; |
| @@ -2186,6 +2197,17 @@ void GMainWindow::UpdateStatusBar() { | |||
| 2186 | } | 2197 | } |
| 2187 | 2198 | ||
| 2188 | auto results = Core::System::GetInstance().GetAndResetPerfStats(); | 2199 | auto results = Core::System::GetInstance().GetAndResetPerfStats(); |
| 2200 | auto& shader_notify = Core::System::GetInstance().GPU().ShaderNotify(); | ||
| 2201 | const auto shaders_building = shader_notify.GetShadersBuilding(); | ||
| 2202 | |||
| 2203 | if (shaders_building != 0) { | ||
| 2204 | shader_building_label->setText( | ||
| 2205 | tr("Building: %1 shader").arg(shaders_building) + | ||
| 2206 | (shaders_building != 1 ? QString::fromStdString("s") : QString::fromStdString(""))); | ||
| 2207 | shader_building_label->setVisible(true); | ||
| 2208 | } else { | ||
| 2209 | shader_building_label->setVisible(false); | ||
| 2210 | } | ||
| 2189 | 2211 | ||
| 2190 | if (Settings::values.use_frame_limit.GetValue()) { | 2212 | if (Settings::values.use_frame_limit.GetValue()) { |
| 2191 | emu_speed_label->setText(tr("Speed: %1% / %2%") | 2213 | emu_speed_label->setText(tr("Speed: %1% / %2%") |
| @@ -2315,9 +2337,12 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { | |||
| 2315 | if (behavior == ReinitializeKeyBehavior::Warning) { | 2337 | if (behavior == ReinitializeKeyBehavior::Warning) { |
| 2316 | const auto res = QMessageBox::information( | 2338 | const auto res = QMessageBox::information( |
| 2317 | this, tr("Confirm Key Rederivation"), | 2339 | this, tr("Confirm Key Rederivation"), |
| 2318 | tr("You are about to force rederive all of your keys. \nIf you do not know what this " | 2340 | tr("You are about to force rederive all of your keys. \nIf you do not know what " |
| 2319 | "means or what you are doing, \nthis is a potentially destructive action. \nPlease " | 2341 | "this " |
| 2320 | "make sure this is what you want \nand optionally make backups.\n\nThis will delete " | 2342 | "means or what you are doing, \nthis is a potentially destructive action. " |
| 2343 | "\nPlease " | ||
| 2344 | "make sure this is what you want \nand optionally make backups.\n\nThis will " | ||
| 2345 | "delete " | ||
| 2321 | "your autogenerated key files and re-run the key derivation module."), | 2346 | "your autogenerated key files and re-run the key derivation module."), |
| 2322 | QMessageBox::StandardButtons{QMessageBox::Ok, QMessageBox::Cancel}); | 2347 | QMessageBox::StandardButtons{QMessageBox::Ok, QMessageBox::Cancel}); |
| 2323 | 2348 | ||
| @@ -2600,6 +2625,43 @@ void GMainWindow::UpdateUITheme() { | |||
| 2600 | QIcon::setThemeSearchPaths(theme_paths); | 2625 | QIcon::setThemeSearchPaths(theme_paths); |
| 2601 | } | 2626 | } |
| 2602 | 2627 | ||
| 2628 | void GMainWindow::LoadTranslation() { | ||
| 2629 | // If the selected language is English, no need to install any translation | ||
| 2630 | if (UISettings::values.language == QStringLiteral("en")) { | ||
| 2631 | return; | ||
| 2632 | } | ||
| 2633 | |||
| 2634 | bool loaded; | ||
| 2635 | |||
| 2636 | if (UISettings::values.language.isEmpty()) { | ||
| 2637 | // If the selected language is empty, use system locale | ||
| 2638 | loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/")); | ||
| 2639 | } else { | ||
| 2640 | // Otherwise load from the specified file | ||
| 2641 | loaded = translator.load(UISettings::values.language, QStringLiteral(":/languages/")); | ||
| 2642 | } | ||
| 2643 | |||
| 2644 | if (loaded) { | ||
| 2645 | qApp->installTranslator(&translator); | ||
| 2646 | } else { | ||
| 2647 | UISettings::values.language = QStringLiteral("en"); | ||
| 2648 | } | ||
| 2649 | } | ||
| 2650 | |||
| 2651 | void GMainWindow::OnLanguageChanged(const QString& locale) { | ||
| 2652 | if (UISettings::values.language != QStringLiteral("en")) { | ||
| 2653 | qApp->removeTranslator(&translator); | ||
| 2654 | } | ||
| 2655 | |||
| 2656 | UISettings::values.language = locale; | ||
| 2657 | LoadTranslation(); | ||
| 2658 | ui.retranslateUi(this); | ||
| 2659 | UpdateWindowTitle(); | ||
| 2660 | |||
| 2661 | if (emulation_running) | ||
| 2662 | ui.action_Start->setText(tr("Continue")); | ||
| 2663 | } | ||
| 2664 | |||
| 2603 | void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) { | 2665 | void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) { |
| 2604 | #ifdef USE_DISCORD_PRESENCE | 2666 | #ifdef USE_DISCORD_PRESENCE |
| 2605 | if (state) { | 2667 | if (state) { |
| @@ -2628,8 +2690,8 @@ int main(int argc, char* argv[]) { | |||
| 2628 | 2690 | ||
| 2629 | #ifdef __APPLE__ | 2691 | #ifdef __APPLE__ |
| 2630 | // If you start a bundle (binary) on OSX without the Terminal, the working directory is "/". | 2692 | // If you start a bundle (binary) on OSX without the Terminal, the working directory is "/". |
| 2631 | // But since we require the working directory to be the executable path for the location of the | 2693 | // But since we require the working directory to be the executable path for the location of |
| 2632 | // user folder in the Qt Frontend, we need to cd into that working directory | 2694 | // the user folder in the Qt Frontend, we need to cd into that working directory |
| 2633 | const std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + ".."; | 2695 | const std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + ".."; |
| 2634 | chdir(bin_path.c_str()); | 2696 | chdir(bin_path.c_str()); |
| 2635 | #endif | 2697 | #endif |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index adff65fb5..db573d606 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | #include <QMainWindow> | 11 | #include <QMainWindow> |
| 12 | #include <QTimer> | 12 | #include <QTimer> |
| 13 | #include <QTranslator> | ||
| 13 | 14 | ||
| 14 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 15 | #include "core/core.h" | 16 | #include "core/core.h" |
| @@ -225,6 +226,7 @@ private slots: | |||
| 225 | void OnCaptureScreenshot(); | 226 | void OnCaptureScreenshot(); |
| 226 | void OnCoreError(Core::System::ResultStatus, std::string); | 227 | void OnCoreError(Core::System::ResultStatus, std::string); |
| 227 | void OnReinitializeKeys(ReinitializeKeyBehavior behavior); | 228 | void OnReinitializeKeys(ReinitializeKeyBehavior behavior); |
| 229 | void OnLanguageChanged(const QString& locale); | ||
| 228 | 230 | ||
| 229 | private: | 231 | private: |
| 230 | std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); | 232 | std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); |
| @@ -237,6 +239,7 @@ private: | |||
| 237 | void HideMouseCursor(); | 239 | void HideMouseCursor(); |
| 238 | void ShowMouseCursor(); | 240 | void ShowMouseCursor(); |
| 239 | void OpenURL(const QUrl& url); | 241 | void OpenURL(const QUrl& url); |
| 242 | void LoadTranslation(); | ||
| 240 | 243 | ||
| 241 | Ui::MainWindow ui; | 244 | Ui::MainWindow ui; |
| 242 | 245 | ||
| @@ -248,6 +251,7 @@ private: | |||
| 248 | 251 | ||
| 249 | // Status bar elements | 252 | // Status bar elements |
| 250 | QLabel* message_label = nullptr; | 253 | QLabel* message_label = nullptr; |
| 254 | QLabel* shader_building_label = nullptr; | ||
| 251 | QLabel* emu_speed_label = nullptr; | 255 | QLabel* emu_speed_label = nullptr; |
| 252 | QLabel* game_fps_label = nullptr; | 256 | QLabel* game_fps_label = nullptr; |
| 253 | QLabel* emu_frametime_label = nullptr; | 257 | QLabel* emu_frametime_label = nullptr; |
| @@ -284,6 +288,8 @@ private: | |||
| 284 | 288 | ||
| 285 | HotkeyRegistry hotkey_registry; | 289 | HotkeyRegistry hotkey_registry; |
| 286 | 290 | ||
| 291 | QTranslator translator; | ||
| 292 | |||
| 287 | // Install progress dialog | 293 | // Install progress dialog |
| 288 | QProgressDialog* install_progress; | 294 | QProgressDialog* install_progress; |
| 289 | 295 | ||
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 830932d45..6cc65736d 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h | |||
| @@ -75,6 +75,7 @@ struct Values { | |||
| 75 | bool game_dir_deprecated_deepscan; | 75 | bool game_dir_deprecated_deepscan; |
| 76 | QVector<UISettings::GameDir> game_dirs; | 76 | QVector<UISettings::GameDir> game_dirs; |
| 77 | QStringList recent_files; | 77 | QStringList recent_files; |
| 78 | QString language; | ||
| 78 | 79 | ||
| 79 | QString theme; | 80 | QString theme; |
| 80 | 81 | ||
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 7773228c8..c2a2982fb 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -394,6 +394,10 @@ void Config::ReadValues() { | |||
| 394 | static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync", 1))); | 394 | static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync", 1))); |
| 395 | Settings::values.use_assembly_shaders.SetValue( | 395 | Settings::values.use_assembly_shaders.SetValue( |
| 396 | sdl2_config->GetBoolean("Renderer", "use_assembly_shaders", false)); | 396 | sdl2_config->GetBoolean("Renderer", "use_assembly_shaders", false)); |
| 397 | Settings::values.use_asynchronous_shaders.SetValue( | ||
| 398 | sdl2_config->GetBoolean("Renderer", "use_asynchronous_shaders", false)); | ||
| 399 | Settings::values.use_asynchronous_shaders.SetValue( | ||
| 400 | sdl2_config->GetBoolean("Renderer", "use_asynchronous_shaders", false)); | ||
| 397 | Settings::values.use_fast_gpu_time.SetValue( | 401 | Settings::values.use_fast_gpu_time.SetValue( |
| 398 | sdl2_config->GetBoolean("Renderer", "use_fast_gpu_time", true)); | 402 | sdl2_config->GetBoolean("Renderer", "use_fast_gpu_time", true)); |
| 399 | 403 | ||
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 5bed47fd7..aa9e40380 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -166,6 +166,10 @@ use_vsync = | |||
| 166 | # 0 (default): Off, 1: On | 166 | # 0 (default): Off, 1: On |
| 167 | use_assembly_shaders = | 167 | use_assembly_shaders = |
| 168 | 168 | ||
| 169 | # Whether to allow asynchronous shader building. | ||
| 170 | # 0 (default): Off, 1: On | ||
| 171 | use_asynchronous_shaders = | ||
| 172 | |||
| 169 | # Turns on the frame limiter, which will limit frames output to the target game speed | 173 | # Turns on the frame limiter, which will limit frames output to the target game speed |
| 170 | # 0: Off, 1: On (default) | 174 | # 0: Off, 1: On (default) |
| 171 | use_frame_limit = | 175 | use_frame_limit = |