diff options
43 files changed, 793 insertions, 359 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ff8385e3a..59c610732 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -66,10 +66,12 @@ if (NOT ENABLE_GENERIC) | |||
| 66 | detect_architecture("_M_AMD64" x86_64) | 66 | detect_architecture("_M_AMD64" x86_64) |
| 67 | detect_architecture("_M_IX86" x86) | 67 | detect_architecture("_M_IX86" x86) |
| 68 | detect_architecture("_M_ARM" ARM) | 68 | detect_architecture("_M_ARM" ARM) |
| 69 | detect_architecture("_M_ARM64" ARM64) | ||
| 69 | else() | 70 | else() |
| 70 | detect_architecture("__x86_64__" x86_64) | 71 | detect_architecture("__x86_64__" x86_64) |
| 71 | detect_architecture("__i386__" x86) | 72 | detect_architecture("__i386__" x86) |
| 72 | detect_architecture("__arm__" ARM) | 73 | detect_architecture("__arm__" ARM) |
| 74 | detect_architecture("__aarch64__" ARM64) | ||
| 73 | endif() | 75 | endif() |
| 74 | endif() | 76 | endif() |
| 75 | 77 | ||
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index ec71524a3..82e4850f7 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt | |||
| @@ -1,4 +1,8 @@ | |||
| 1 | add_library(audio_core STATIC | 1 | add_library(audio_core STATIC |
| 2 | algorithm/filter.cpp | ||
| 3 | algorithm/filter.h | ||
| 4 | algorithm/interpolate.cpp | ||
| 5 | algorithm/interpolate.h | ||
| 2 | audio_out.cpp | 6 | audio_out.cpp |
| 3 | audio_out.h | 7 | audio_out.h |
| 4 | audio_renderer.cpp | 8 | audio_renderer.cpp |
| @@ -7,12 +11,12 @@ add_library(audio_core STATIC | |||
| 7 | codec.cpp | 11 | codec.cpp |
| 8 | codec.h | 12 | codec.h |
| 9 | null_sink.h | 13 | null_sink.h |
| 10 | stream.cpp | ||
| 11 | stream.h | ||
| 12 | sink.h | 14 | sink.h |
| 13 | sink_details.cpp | 15 | sink_details.cpp |
| 14 | sink_details.h | 16 | sink_details.h |
| 15 | sink_stream.h | 17 | sink_stream.h |
| 18 | stream.cpp | ||
| 19 | stream.h | ||
| 16 | 20 | ||
| 17 | $<$<BOOL:${ENABLE_CUBEB}>:cubeb_sink.cpp cubeb_sink.h> | 21 | $<$<BOOL:${ENABLE_CUBEB}>:cubeb_sink.cpp cubeb_sink.h> |
| 18 | ) | 22 | ) |
diff --git a/src/audio_core/algorithm/filter.cpp b/src/audio_core/algorithm/filter.cpp new file mode 100644 index 000000000..403b8503f --- /dev/null +++ b/src/audio_core/algorithm/filter.cpp | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #define _USE_MATH_DEFINES | ||
| 6 | |||
| 7 | #include <algorithm> | ||
| 8 | #include <array> | ||
| 9 | #include <cmath> | ||
| 10 | #include <vector> | ||
| 11 | #include "audio_core/algorithm/filter.h" | ||
| 12 | #include "common/common_types.h" | ||
| 13 | |||
| 14 | namespace AudioCore { | ||
| 15 | |||
| 16 | Filter Filter::LowPass(double cutoff, double Q) { | ||
| 17 | const double w0 = 2.0 * M_PI * cutoff; | ||
| 18 | const double sin_w0 = std::sin(w0); | ||
| 19 | const double cos_w0 = std::cos(w0); | ||
| 20 | const double alpha = sin_w0 / (2 * Q); | ||
| 21 | |||
| 22 | const double a0 = 1 + alpha; | ||
| 23 | const double a1 = -2.0 * cos_w0; | ||
| 24 | const double a2 = 1 - alpha; | ||
| 25 | const double b0 = 0.5 * (1 - cos_w0); | ||
| 26 | const double b1 = 1.0 * (1 - cos_w0); | ||
| 27 | const double b2 = 0.5 * (1 - cos_w0); | ||
| 28 | |||
| 29 | return {a0, a1, a2, b0, b1, b2}; | ||
| 30 | } | ||
| 31 | |||
| 32 | Filter::Filter() : Filter(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) {} | ||
| 33 | |||
| 34 | Filter::Filter(double a0, double a1, double a2, double b0, double b1, double b2) | ||
| 35 | : a1(a1 / a0), a2(a2 / a0), b0(b0 / a0), b1(b1 / a0), b2(b2 / a0) {} | ||
| 36 | |||
| 37 | void Filter::Process(std::vector<s16>& signal) { | ||
| 38 | const size_t num_frames = signal.size() / 2; | ||
| 39 | for (size_t i = 0; i < num_frames; i++) { | ||
| 40 | std::rotate(in.begin(), in.end() - 1, in.end()); | ||
| 41 | std::rotate(out.begin(), out.end() - 1, out.end()); | ||
| 42 | |||
| 43 | for (size_t ch = 0; ch < channel_count; ch++) { | ||
| 44 | in[0][ch] = signal[i * channel_count + ch]; | ||
| 45 | |||
| 46 | out[0][ch] = b0 * in[0][ch] + b1 * in[1][ch] + b2 * in[2][ch] - a1 * out[1][ch] - | ||
| 47 | a2 * out[2][ch]; | ||
| 48 | |||
| 49 | signal[i * 2 + ch] = std::clamp(out[0][ch], -32768.0, 32767.0); | ||
| 50 | } | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | /// Calculates the appropriate Q for each biquad in a cascading filter. | ||
| 55 | /// @param total_count The total number of biquads to be cascaded. | ||
| 56 | /// @param index 0-index of the biquad to calculate the Q value for. | ||
| 57 | static double CascadingBiquadQ(size_t total_count, size_t index) { | ||
| 58 | const double pole = M_PI * (2 * index + 1) / (4.0 * total_count); | ||
| 59 | return 1.0 / (2.0 * std::cos(pole)); | ||
| 60 | } | ||
| 61 | |||
| 62 | CascadingFilter CascadingFilter::LowPass(double cutoff, size_t cascade_size) { | ||
| 63 | std::vector<Filter> cascade(cascade_size); | ||
| 64 | for (size_t i = 0; i < cascade_size; i++) { | ||
| 65 | cascade[i] = Filter::LowPass(cutoff, CascadingBiquadQ(cascade_size, i)); | ||
| 66 | } | ||
| 67 | return CascadingFilter{std::move(cascade)}; | ||
| 68 | } | ||
| 69 | |||
| 70 | CascadingFilter::CascadingFilter() = default; | ||
| 71 | CascadingFilter::CascadingFilter(std::vector<Filter> filters) : filters(std::move(filters)) {} | ||
| 72 | |||
| 73 | void CascadingFilter::Process(std::vector<s16>& signal) { | ||
| 74 | for (auto& filter : filters) { | ||
| 75 | filter.Process(signal); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | } // namespace AudioCore | ||
diff --git a/src/audio_core/algorithm/filter.h b/src/audio_core/algorithm/filter.h new file mode 100644 index 000000000..a41beef98 --- /dev/null +++ b/src/audio_core/algorithm/filter.h | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | // Copyright 2018 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 <array> | ||
| 8 | #include <vector> | ||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | namespace AudioCore { | ||
| 12 | |||
| 13 | /// Digital biquad filter: | ||
| 14 | /// | ||
| 15 | /// b0 + b1 z^-1 + b2 z^-2 | ||
| 16 | /// H(z) = ------------------------ | ||
| 17 | /// a0 + a1 z^-1 + b2 z^-2 | ||
| 18 | class Filter { | ||
| 19 | public: | ||
| 20 | /// Creates a low-pass filter. | ||
| 21 | /// @param cutoff Determines the cutoff frequency. A value from 0.0 to 1.0. | ||
| 22 | /// @param Q Determines the quality factor of this filter. | ||
| 23 | static Filter LowPass(double cutoff, double Q = 0.7071); | ||
| 24 | |||
| 25 | /// Passthrough filter. | ||
| 26 | Filter(); | ||
| 27 | |||
| 28 | Filter(double a0, double a1, double a2, double b0, double b1, double b2); | ||
| 29 | |||
| 30 | void Process(std::vector<s16>& signal); | ||
| 31 | |||
| 32 | private: | ||
| 33 | static constexpr size_t channel_count = 2; | ||
| 34 | |||
| 35 | /// Coefficients are in normalized form (a0 = 1.0). | ||
| 36 | double a1, a2, b0, b1, b2; | ||
| 37 | /// Input History | ||
| 38 | std::array<std::array<double, channel_count>, 3> in; | ||
| 39 | /// Output History | ||
| 40 | std::array<std::array<double, channel_count>, 3> out; | ||
| 41 | }; | ||
| 42 | |||
| 43 | /// Cascade filters to build up higher-order filters from lower-order ones. | ||
| 44 | class CascadingFilter { | ||
| 45 | public: | ||
| 46 | /// Creates a cascading low-pass filter. | ||
| 47 | /// @param cutoff Determines the cutoff frequency. A value from 0.0 to 1.0. | ||
| 48 | /// @param cascade_size Number of biquads in cascade. | ||
| 49 | static CascadingFilter LowPass(double cutoff, size_t cascade_size); | ||
| 50 | |||
| 51 | /// Passthrough. | ||
| 52 | CascadingFilter(); | ||
| 53 | |||
| 54 | explicit CascadingFilter(std::vector<Filter> filters); | ||
| 55 | |||
| 56 | void Process(std::vector<s16>& signal); | ||
| 57 | |||
| 58 | private: | ||
| 59 | std::vector<Filter> filters; | ||
| 60 | }; | ||
| 61 | |||
| 62 | } // namespace AudioCore | ||
diff --git a/src/audio_core/algorithm/interpolate.cpp b/src/audio_core/algorithm/interpolate.cpp new file mode 100644 index 000000000..11459821f --- /dev/null +++ b/src/audio_core/algorithm/interpolate.cpp | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #define _USE_MATH_DEFINES | ||
| 6 | |||
| 7 | #include <algorithm> | ||
| 8 | #include <cmath> | ||
| 9 | #include <vector> | ||
| 10 | #include "audio_core/algorithm/interpolate.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "common/logging/log.h" | ||
| 13 | |||
| 14 | namespace AudioCore { | ||
| 15 | |||
| 16 | /// The Lanczos kernel | ||
| 17 | static double Lanczos(size_t a, double x) { | ||
| 18 | if (x == 0.0) | ||
| 19 | return 1.0; | ||
| 20 | const double px = M_PI * x; | ||
| 21 | return a * std::sin(px) * std::sin(px / a) / (px * px); | ||
| 22 | } | ||
| 23 | |||
| 24 | std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input, double ratio) { | ||
| 25 | if (input.size() < 2) | ||
| 26 | return {}; | ||
| 27 | |||
| 28 | if (ratio <= 0) { | ||
| 29 | LOG_CRITICAL(Audio, "Nonsensical interpolation ratio {}", ratio); | ||
| 30 | ratio = 1.0; | ||
| 31 | } | ||
| 32 | |||
| 33 | if (ratio != state.current_ratio) { | ||
| 34 | const double cutoff_frequency = std::min(0.5 / ratio, 0.5 * ratio); | ||
| 35 | state.nyquist = CascadingFilter::LowPass(std::clamp(cutoff_frequency, 0.0, 0.4), 3); | ||
| 36 | state.current_ratio = ratio; | ||
| 37 | } | ||
| 38 | state.nyquist.Process(input); | ||
| 39 | |||
| 40 | constexpr size_t taps = InterpolationState::lanczos_taps; | ||
| 41 | const size_t num_frames = input.size() / 2; | ||
| 42 | |||
| 43 | std::vector<s16> output; | ||
| 44 | output.reserve(static_cast<size_t>(input.size() / ratio + 4)); | ||
| 45 | |||
| 46 | double& pos = state.position; | ||
| 47 | auto& h = state.history; | ||
| 48 | for (size_t i = 0; i < num_frames; ++i) { | ||
| 49 | std::rotate(h.begin(), h.end() - 1, h.end()); | ||
| 50 | h[0][0] = input[i * 2 + 0]; | ||
| 51 | h[0][1] = input[i * 2 + 1]; | ||
| 52 | |||
| 53 | while (pos <= 1.0) { | ||
| 54 | double l = 0.0; | ||
| 55 | double r = 0.0; | ||
| 56 | for (size_t j = 0; j < h.size(); j++) { | ||
| 57 | l += Lanczos(taps, pos + j - taps + 1) * h[j][0]; | ||
| 58 | r += Lanczos(taps, pos + j - taps + 1) * h[j][1]; | ||
| 59 | } | ||
| 60 | output.emplace_back(static_cast<s16>(std::clamp(l, -32768.0, 32767.0))); | ||
| 61 | output.emplace_back(static_cast<s16>(std::clamp(r, -32768.0, 32767.0))); | ||
| 62 | |||
| 63 | pos += ratio; | ||
| 64 | } | ||
| 65 | pos -= 1.0; | ||
| 66 | } | ||
| 67 | |||
| 68 | return output; | ||
| 69 | } | ||
| 70 | |||
| 71 | } // namespace AudioCore | ||
diff --git a/src/audio_core/algorithm/interpolate.h b/src/audio_core/algorithm/interpolate.h new file mode 100644 index 000000000..c79c2eef4 --- /dev/null +++ b/src/audio_core/algorithm/interpolate.h | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | // Copyright 2018 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 <array> | ||
| 8 | #include <vector> | ||
| 9 | #include "audio_core/algorithm/filter.h" | ||
| 10 | #include "common/common_types.h" | ||
| 11 | |||
| 12 | namespace AudioCore { | ||
| 13 | |||
| 14 | struct InterpolationState { | ||
| 15 | static constexpr size_t lanczos_taps = 4; | ||
| 16 | static constexpr size_t history_size = lanczos_taps * 2 - 1; | ||
| 17 | |||
| 18 | double current_ratio = 0.0; | ||
| 19 | CascadingFilter nyquist; | ||
| 20 | std::array<std::array<s16, 2>, history_size> history = {}; | ||
| 21 | double position = 0; | ||
| 22 | }; | ||
| 23 | |||
| 24 | /// Interpolates input signal to produce output signal. | ||
| 25 | /// @param input The signal to interpolate. | ||
| 26 | /// @param ratio Interpolation ratio. | ||
| 27 | /// ratio > 1.0 results in fewer output samples. | ||
| 28 | /// ratio < 1.0 results in more output samples. | ||
| 29 | /// @returns Output signal. | ||
| 30 | std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input, double ratio); | ||
| 31 | |||
| 32 | /// Interpolates input signal to produce output signal. | ||
| 33 | /// @param input The signal to interpolate. | ||
| 34 | /// @param input_rate The sample rate of input. | ||
| 35 | /// @param output_rate The desired sample rate of the output. | ||
| 36 | /// @returns Output signal. | ||
| 37 | inline std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input, | ||
| 38 | u32 input_rate, u32 output_rate) { | ||
| 39 | const double ratio = static_cast<double>(input_rate) / static_cast<double>(output_rate); | ||
| 40 | return Interpolate(state, std::move(input), ratio); | ||
| 41 | } | ||
| 42 | |||
| 43 | } // namespace AudioCore | ||
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp index 6ebed3fb0..397b107f5 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 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 "audio_core/algorithm/interpolate.h" | ||
| 5 | #include "audio_core/audio_renderer.h" | 6 | #include "audio_core/audio_renderer.h" |
| 6 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 7 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| @@ -199,6 +200,8 @@ void AudioRenderer::VoiceState::RefreshBuffer() { | |||
| 199 | break; | 200 | break; |
| 200 | } | 201 | } |
| 201 | 202 | ||
| 203 | samples = Interpolate(interp_state, std::move(samples), Info().sample_rate, STREAM_SAMPLE_RATE); | ||
| 204 | |||
| 202 | is_refresh_pending = false; | 205 | is_refresh_pending = false; |
| 203 | } | 206 | } |
| 204 | 207 | ||
| @@ -224,7 +227,7 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) { | |||
| 224 | break; | 227 | break; |
| 225 | } | 228 | } |
| 226 | 229 | ||
| 227 | samples_remaining -= samples.size(); | 230 | samples_remaining -= samples.size() / stream->GetNumChannels(); |
| 228 | 231 | ||
| 229 | for (const auto& sample : samples) { | 232 | for (const auto& sample : samples) { |
| 230 | const s32 buffer_sample{buffer[offset]}; | 233 | const s32 buffer_sample{buffer[offset]}; |
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h index 13c5d0adc..eba67f28e 100644 --- a/src/audio_core/audio_renderer.h +++ b/src/audio_core/audio_renderer.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include <vector> | 9 | #include <vector> |
| 10 | 10 | ||
| 11 | #include "audio_core/algorithm/interpolate.h" | ||
| 11 | #include "audio_core/audio_out.h" | 12 | #include "audio_core/audio_out.h" |
| 12 | #include "audio_core/codec.h" | 13 | #include "audio_core/codec.h" |
| 13 | #include "audio_core/stream.h" | 14 | #include "audio_core/stream.h" |
| @@ -194,6 +195,7 @@ private: | |||
| 194 | size_t wave_index{}; | 195 | size_t wave_index{}; |
| 195 | size_t offset{}; | 196 | size_t offset{}; |
| 196 | Codec::ADPCMState adpcm_state{}; | 197 | Codec::ADPCMState adpcm_state{}; |
| 198 | InterpolationState interp_state{}; | ||
| 197 | std::vector<s16> samples; | 199 | std::vector<s16> samples; |
| 198 | VoiceOutStatus out_status{}; | 200 | VoiceOutStatus out_status{}; |
| 199 | VoiceInfo info{}; | 201 | VoiceInfo info{}; |
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index d5d4f6f82..939b8a7d3 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -29,8 +29,6 @@ add_library(common STATIC | |||
| 29 | assert.h | 29 | assert.h |
| 30 | bit_field.h | 30 | bit_field.h |
| 31 | bit_set.h | 31 | bit_set.h |
| 32 | break_points.cpp | ||
| 33 | break_points.h | ||
| 34 | cityhash.cpp | 32 | cityhash.cpp |
| 35 | cityhash.h | 33 | cityhash.h |
| 36 | color.h | 34 | color.h |
diff --git a/src/common/break_points.cpp b/src/common/break_points.cpp deleted file mode 100644 index fa367a4ca..000000000 --- a/src/common/break_points.cpp +++ /dev/null | |||
| @@ -1,90 +0,0 @@ | |||
| 1 | // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <sstream> | ||
| 7 | #include "common/break_points.h" | ||
| 8 | |||
| 9 | bool BreakPoints::IsAddressBreakPoint(u32 iAddress) const { | ||
| 10 | auto cond = [&iAddress](const TBreakPoint& bp) { return bp.iAddress == iAddress; }; | ||
| 11 | auto it = std::find_if(m_BreakPoints.begin(), m_BreakPoints.end(), cond); | ||
| 12 | return it != m_BreakPoints.end(); | ||
| 13 | } | ||
| 14 | |||
| 15 | bool BreakPoints::IsTempBreakPoint(u32 iAddress) const { | ||
| 16 | auto cond = [&iAddress](const TBreakPoint& bp) { | ||
| 17 | return bp.iAddress == iAddress && bp.bTemporary; | ||
| 18 | }; | ||
| 19 | auto it = std::find_if(m_BreakPoints.begin(), m_BreakPoints.end(), cond); | ||
| 20 | return it != m_BreakPoints.end(); | ||
| 21 | } | ||
| 22 | |||
| 23 | BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const { | ||
| 24 | TBreakPointsStr bps; | ||
| 25 | for (auto breakpoint : m_BreakPoints) { | ||
| 26 | if (!breakpoint.bTemporary) { | ||
| 27 | std::stringstream bp; | ||
| 28 | bp << std::hex << breakpoint.iAddress << " " << (breakpoint.bOn ? "n" : ""); | ||
| 29 | bps.push_back(bp.str()); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | return bps; | ||
| 34 | } | ||
| 35 | |||
| 36 | void BreakPoints::AddFromStrings(const TBreakPointsStr& bps) { | ||
| 37 | for (auto bps_item : bps) { | ||
| 38 | TBreakPoint bp; | ||
| 39 | std::stringstream bpstr; | ||
| 40 | bpstr << std::hex << bps_item; | ||
| 41 | bpstr >> bp.iAddress; | ||
| 42 | bp.bOn = bps_item.find("n") != bps_item.npos; | ||
| 43 | bp.bTemporary = false; | ||
| 44 | Add(bp); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | void BreakPoints::Add(const TBreakPoint& bp) { | ||
| 49 | if (!IsAddressBreakPoint(bp.iAddress)) { | ||
| 50 | m_BreakPoints.push_back(bp); | ||
| 51 | // if (jit) | ||
| 52 | // jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | void BreakPoints::Add(u32 em_address, bool temp) { | ||
| 57 | if (!IsAddressBreakPoint(em_address)) // only add new addresses | ||
| 58 | { | ||
| 59 | TBreakPoint pt; // breakpoint settings | ||
| 60 | pt.bOn = true; | ||
| 61 | pt.bTemporary = temp; | ||
| 62 | pt.iAddress = em_address; | ||
| 63 | |||
| 64 | m_BreakPoints.push_back(pt); | ||
| 65 | |||
| 66 | // if (jit) | ||
| 67 | // jit->GetBlockCache()->InvalidateICache(em_address, 4); | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | void BreakPoints::Remove(u32 em_address) { | ||
| 72 | auto cond = [&em_address](const TBreakPoint& bp) { return bp.iAddress == em_address; }; | ||
| 73 | auto it = std::find_if(m_BreakPoints.begin(), m_BreakPoints.end(), cond); | ||
| 74 | if (it != m_BreakPoints.end()) | ||
| 75 | m_BreakPoints.erase(it); | ||
| 76 | } | ||
| 77 | |||
| 78 | void BreakPoints::Clear() { | ||
| 79 | // if (jit) | ||
| 80 | //{ | ||
| 81 | // std::for_each(m_BreakPoints.begin(), m_BreakPoints.end(), | ||
| 82 | // [](const TBreakPoint& bp) | ||
| 83 | // { | ||
| 84 | // jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4); | ||
| 85 | // } | ||
| 86 | // ); | ||
| 87 | //} | ||
| 88 | |||
| 89 | m_BreakPoints.clear(); | ||
| 90 | } | ||
diff --git a/src/common/break_points.h b/src/common/break_points.h deleted file mode 100644 index e15b9f842..000000000 --- a/src/common/break_points.h +++ /dev/null | |||
| @@ -1,49 +0,0 @@ | |||
| 1 | // Copyright 2013 Dolphin Emulator Project / 2014 Citra 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 <string> | ||
| 8 | #include <vector> | ||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | class DebugInterface; | ||
| 12 | |||
| 13 | struct TBreakPoint { | ||
| 14 | u32 iAddress; | ||
| 15 | bool bOn; | ||
| 16 | bool bTemporary; | ||
| 17 | }; | ||
| 18 | |||
| 19 | // Code breakpoints. | ||
| 20 | class BreakPoints { | ||
| 21 | public: | ||
| 22 | typedef std::vector<TBreakPoint> TBreakPoints; | ||
| 23 | typedef std::vector<std::string> TBreakPointsStr; | ||
| 24 | |||
| 25 | const TBreakPoints& GetBreakPoints() { | ||
| 26 | return m_BreakPoints; | ||
| 27 | } | ||
| 28 | |||
| 29 | TBreakPointsStr GetStrings() const; | ||
| 30 | void AddFromStrings(const TBreakPointsStr& bps); | ||
| 31 | |||
| 32 | // is address breakpoint | ||
| 33 | bool IsAddressBreakPoint(u32 iAddress) const; | ||
| 34 | bool IsTempBreakPoint(u32 iAddress) const; | ||
| 35 | |||
| 36 | // Add BreakPoint | ||
| 37 | void Add(u32 em_address, bool temp = false); | ||
| 38 | void Add(const TBreakPoint& bp); | ||
| 39 | |||
| 40 | // Remove Breakpoint | ||
| 41 | void Remove(u32 iAddress); | ||
| 42 | void Clear(); | ||
| 43 | |||
| 44 | void DeleteByAddress(u32 Address); | ||
| 45 | |||
| 46 | private: | ||
| 47 | TBreakPoints m_BreakPoints; | ||
| 48 | u32 m_iBreakOnCount; | ||
| 49 | }; | ||
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index e80784c3c..1323f8d0f 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -302,13 +302,14 @@ Backend* GetBackend(std::string_view backend_name) { | |||
| 302 | void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, | 302 | void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, |
| 303 | unsigned int line_num, const char* function, const char* format, | 303 | unsigned int line_num, const char* function, const char* format, |
| 304 | const fmt::format_args& args) { | 304 | const fmt::format_args& args) { |
| 305 | auto filter = Impl::Instance().GetGlobalFilter(); | 305 | auto& instance = Impl::Instance(); |
| 306 | const auto& filter = instance.GetGlobalFilter(); | ||
| 306 | if (!filter.CheckMessage(log_class, log_level)) | 307 | if (!filter.CheckMessage(log_class, log_level)) |
| 307 | return; | 308 | return; |
| 308 | 309 | ||
| 309 | Entry entry = | 310 | Entry entry = |
| 310 | CreateEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args)); | 311 | CreateEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args)); |
| 311 | 312 | ||
| 312 | Impl::Instance().PushEntry(std::move(entry)); | 313 | instance.PushEntry(std::move(entry)); |
| 313 | } | 314 | } |
| 314 | } // namespace Log | 315 | } // namespace Log |
diff --git a/src/common/misc.cpp b/src/common/misc.cpp index 217a87098..3fa8a3bc4 100644 --- a/src/common/misc.cpp +++ b/src/common/misc.cpp | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include <cstddef> | 5 | #include <cstddef> |
| 6 | #ifdef _WIN32 | 6 | #ifdef _WIN32 |
| 7 | #include <Windows.h> | 7 | #include <windows.h> |
| 8 | #else | 8 | #else |
| 9 | #include <cerrno> | 9 | #include <cerrno> |
| 10 | #include <cstring> | 10 | #include <cstring> |
diff --git a/src/common/x64/xbyak_abi.h b/src/common/x64/xbyak_abi.h index fd3fbdd4b..927da9187 100644 --- a/src/common/x64/xbyak_abi.h +++ b/src/common/x64/xbyak_abi.h | |||
| @@ -9,10 +9,9 @@ | |||
| 9 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 10 | #include "common/bit_set.h" | 10 | #include "common/bit_set.h" |
| 11 | 11 | ||
| 12 | namespace Common { | 12 | namespace Common::X64 { |
| 13 | namespace X64 { | ||
| 14 | 13 | ||
| 15 | int RegToIndex(const Xbyak::Reg& reg) { | 14 | inline int RegToIndex(const Xbyak::Reg& reg) { |
| 16 | using Kind = Xbyak::Reg::Kind; | 15 | using Kind = Xbyak::Reg::Kind; |
| 17 | ASSERT_MSG((reg.getKind() & (Kind::REG | Kind::XMM)) != 0, | 16 | ASSERT_MSG((reg.getKind() & (Kind::REG | Kind::XMM)) != 0, |
| 18 | "RegSet only support GPRs and XMM registers."); | 17 | "RegSet only support GPRs and XMM registers."); |
| @@ -152,8 +151,8 @@ constexpr size_t ABI_SHADOW_SPACE = 0; | |||
| 152 | 151 | ||
| 153 | #endif | 152 | #endif |
| 154 | 153 | ||
| 155 | void ABI_CalculateFrameSize(BitSet32 regs, size_t rsp_alignment, size_t needed_frame_size, | 154 | inline void ABI_CalculateFrameSize(BitSet32 regs, size_t rsp_alignment, size_t needed_frame_size, |
| 156 | s32* out_subtraction, s32* out_xmm_offset) { | 155 | s32* out_subtraction, s32* out_xmm_offset) { |
| 157 | int count = (regs & ABI_ALL_GPRS).Count(); | 156 | int count = (regs & ABI_ALL_GPRS).Count(); |
| 158 | rsp_alignment -= count * 8; | 157 | rsp_alignment -= count * 8; |
| 159 | size_t subtraction = 0; | 158 | size_t subtraction = 0; |
| @@ -174,8 +173,8 @@ void ABI_CalculateFrameSize(BitSet32 regs, size_t rsp_alignment, size_t needed_f | |||
| 174 | *out_xmm_offset = (s32)(subtraction - xmm_base_subtraction); | 173 | *out_xmm_offset = (s32)(subtraction - xmm_base_subtraction); |
| 175 | } | 174 | } |
| 176 | 175 | ||
| 177 | size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs, | 176 | inline size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs, |
| 178 | size_t rsp_alignment, size_t needed_frame_size = 0) { | 177 | size_t rsp_alignment, size_t needed_frame_size = 0) { |
| 179 | s32 subtraction, xmm_offset; | 178 | s32 subtraction, xmm_offset; |
| 180 | ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size, &subtraction, &xmm_offset); | 179 | ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size, &subtraction, &xmm_offset); |
| 181 | 180 | ||
| @@ -195,8 +194,8 @@ size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs | |||
| 195 | return ABI_SHADOW_SPACE; | 194 | return ABI_SHADOW_SPACE; |
| 196 | } | 195 | } |
| 197 | 196 | ||
| 198 | void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs, size_t rsp_alignment, | 197 | inline void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs, |
| 199 | size_t needed_frame_size = 0) { | 198 | size_t rsp_alignment, size_t needed_frame_size = 0) { |
| 200 | s32 subtraction, xmm_offset; | 199 | s32 subtraction, xmm_offset; |
| 201 | ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size, &subtraction, &xmm_offset); | 200 | ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size, &subtraction, &xmm_offset); |
| 202 | 201 | ||
| @@ -217,5 +216,4 @@ void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs, s | |||
| 217 | } | 216 | } |
| 218 | } | 217 | } |
| 219 | 218 | ||
| 220 | } // namespace X64 | 219 | } // namespace Common::X64 |
| 221 | } // namespace Common | ||
diff --git a/src/common/x64/xbyak_util.h b/src/common/x64/xbyak_util.h index ec76e0a47..02323a017 100644 --- a/src/common/x64/xbyak_util.h +++ b/src/common/x64/xbyak_util.h | |||
| @@ -8,8 +8,7 @@ | |||
| 8 | #include <xbyak.h> | 8 | #include <xbyak.h> |
| 9 | #include "common/x64/xbyak_abi.h" | 9 | #include "common/x64/xbyak_abi.h" |
| 10 | 10 | ||
| 11 | namespace Common { | 11 | namespace Common::X64 { |
| 12 | namespace X64 { | ||
| 13 | 12 | ||
| 14 | // Constants for use with cmpps/cmpss | 13 | // Constants for use with cmpps/cmpss |
| 15 | enum { | 14 | enum { |
| @@ -45,5 +44,4 @@ inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) { | |||
| 45 | } | 44 | } |
| 46 | } | 45 | } |
| 47 | 46 | ||
| 48 | } // namespace X64 | 47 | } // namespace Common::X64 |
| 49 | } // namespace Common | ||
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index cceb1564b..0b0ae5ccc 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -249,6 +249,10 @@ add_library(core STATIC | |||
| 249 | hle/service/nvdrv/devices/nvhost_gpu.h | 249 | hle/service/nvdrv/devices/nvhost_gpu.h |
| 250 | hle/service/nvdrv/devices/nvhost_nvdec.cpp | 250 | hle/service/nvdrv/devices/nvhost_nvdec.cpp |
| 251 | hle/service/nvdrv/devices/nvhost_nvdec.h | 251 | hle/service/nvdrv/devices/nvhost_nvdec.h |
| 252 | hle/service/nvdrv/devices/nvhost_nvjpg.cpp | ||
| 253 | hle/service/nvdrv/devices/nvhost_nvjpg.h | ||
| 254 | hle/service/nvdrv/devices/nvhost_vic.cpp | ||
| 255 | hle/service/nvdrv/devices/nvhost_vic.h | ||
| 252 | hle/service/nvdrv/devices/nvmap.cpp | 256 | hle/service/nvdrv/devices/nvmap.cpp |
| 253 | hle/service/nvdrv/devices/nvmap.h | 257 | hle/service/nvdrv/devices/nvmap.h |
| 254 | hle/service/nvdrv/interface.cpp | 258 | hle/service/nvdrv/interface.cpp |
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 0996f129c..20e5200a8 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp | |||
| @@ -243,9 +243,7 @@ void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) { | |||
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | void ARM_Dynarmic::PrepareReschedule() { | 245 | void ARM_Dynarmic::PrepareReschedule() { |
| 246 | if (jit->IsExecuting()) { | 246 | jit->HaltExecution(); |
| 247 | jit->HaltExecution(); | ||
| 248 | } | ||
| 249 | } | 247 | } |
| 250 | 248 | ||
| 251 | void ARM_Dynarmic::ClearInstructionCache() { | 249 | void ARM_Dynarmic::ClearInstructionCache() { |
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 384dc7822..7006a37b3 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h | |||
| @@ -34,9 +34,9 @@ class EmuWindow { | |||
| 34 | public: | 34 | public: |
| 35 | /// Data structure to store emuwindow configuration | 35 | /// Data structure to store emuwindow configuration |
| 36 | struct WindowConfig { | 36 | struct WindowConfig { |
| 37 | bool fullscreen; | 37 | bool fullscreen = false; |
| 38 | int res_width; | 38 | int res_width = 0; |
| 39 | int res_height; | 39 | int res_height = 0; |
| 40 | std::pair<unsigned, unsigned> min_client_area_size; | 40 | std::pair<unsigned, unsigned> min_client_area_size; |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index d09ca5992..51a1ec160 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp | |||
| @@ -152,7 +152,7 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) { | |||
| 152 | // Handle scenario when ConvertToDomain command was issued, as we must do the conversion at the | 152 | // Handle scenario when ConvertToDomain command was issued, as we must do the conversion at the |
| 153 | // end of the command such that only commands following this one are handled as domains | 153 | // end of the command such that only commands following this one are handled as domains |
| 154 | if (convert_to_domain) { | 154 | if (convert_to_domain) { |
| 155 | ASSERT_MSG(domain_request_handlers.empty(), "already a domain"); | 155 | ASSERT_MSG(IsSession(), "ServerSession is already a domain instance."); |
| 156 | domain_request_handlers = {hle_handler}; | 156 | domain_request_handlers = {hle_handler}; |
| 157 | convert_to_domain = false; | 157 | convert_to_domain = false; |
| 158 | } | 158 | } |
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index 2bce54fee..1a88e66b9 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h | |||
| @@ -97,7 +97,12 @@ public: | |||
| 97 | 97 | ||
| 98 | /// Returns true if the session has been converted to a domain, otherwise False | 98 | /// Returns true if the session has been converted to a domain, otherwise False |
| 99 | bool IsDomain() const { | 99 | bool IsDomain() const { |
| 100 | return !domain_request_handlers.empty(); | 100 | return !IsSession(); |
| 101 | } | ||
| 102 | |||
| 103 | /// Returns true if this session has not been converted to a domain, otherwise false. | ||
| 104 | bool IsSession() const { | ||
| 105 | return domain_request_handlers.empty(); | ||
| 101 | } | 106 | } |
| 102 | 107 | ||
| 103 | /// Converts the session to a domain at the end of the current command | 108 | /// Converts the session to a domain at the end of the current command |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index b24f409b3..6be5c474e 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -250,8 +250,11 @@ static ResultCode ArbitrateUnlock(VAddr mutex_addr) { | |||
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | /// Break program execution | 252 | /// Break program execution |
| 253 | static void Break(u64 unk_0, u64 unk_1, u64 unk_2) { | 253 | static void Break(u64 reason, u64 info1, u64 info2) { |
| 254 | LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!"); | 254 | LOG_CRITICAL( |
| 255 | Debug_Emulated, | ||
| 256 | "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}", | ||
| 257 | reason, info1, info2); | ||
| 255 | ASSERT(false); | 258 | ASSERT(false); |
| 256 | } | 259 | } |
| 257 | 260 | ||
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 108a7c6eb..ce709ccf4 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -28,7 +28,7 @@ constexpr int DefaultSampleRate{48000}; | |||
| 28 | class IAudioOut final : public ServiceFramework<IAudioOut> { | 28 | class IAudioOut final : public ServiceFramework<IAudioOut> { |
| 29 | public: | 29 | public: |
| 30 | IAudioOut(AudoutParams audio_params, AudioCore::AudioOut& audio_core) | 30 | IAudioOut(AudoutParams audio_params, AudioCore::AudioOut& audio_core) |
| 31 | : ServiceFramework("IAudioOut"), audio_params(audio_params), audio_core(audio_core) { | 31 | : ServiceFramework("IAudioOut"), audio_core(audio_core), audio_params(audio_params) { |
| 32 | 32 | ||
| 33 | static const FunctionInfo functions[] = { | 33 | static const FunctionInfo functions[] = { |
| 34 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, | 34 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, |
diff --git a/src/core/hle/service/mm/mm_u.cpp b/src/core/hle/service/mm/mm_u.cpp index 08f45b78a..7b91bb258 100644 --- a/src/core/hle/service/mm/mm_u.cpp +++ b/src/core/hle/service/mm/mm_u.cpp | |||
| @@ -9,42 +9,63 @@ | |||
| 9 | 9 | ||
| 10 | namespace Service::MM { | 10 | namespace Service::MM { |
| 11 | 11 | ||
| 12 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 12 | class MM_U final : public ServiceFramework<MM_U> { |
| 13 | std::make_shared<MM_U>()->InstallAsService(service_manager); | 13 | public: |
| 14 | } | 14 | explicit MM_U() : ServiceFramework{"mm:u"} { |
| 15 | // clang-format off | ||
| 16 | static const FunctionInfo functions[] = { | ||
| 17 | {0, &MM_U::Initialize, "InitializeOld"}, | ||
| 18 | {1, &MM_U::Finalize, "FinalizeOld"}, | ||
| 19 | {2, &MM_U::SetAndWait, "SetAndWaitOld"}, | ||
| 20 | {3, &MM_U::Get, "GetOld"}, | ||
| 21 | {4, &MM_U::Initialize, "Initialize"}, | ||
| 22 | {5, &MM_U::Finalize, "Finalize"}, | ||
| 23 | {6, &MM_U::SetAndWait, "SetAndWait"}, | ||
| 24 | {7, &MM_U::Get, "Get"}, | ||
| 25 | }; | ||
| 26 | // clang-format on | ||
| 15 | 27 | ||
| 16 | void MM_U::Initialize(Kernel::HLERequestContext& ctx) { | 28 | RegisterHandlers(functions); |
| 17 | LOG_WARNING(Service_MM, "(STUBBED) called"); | 29 | } |
| 18 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 19 | rb.Push(RESULT_SUCCESS); | ||
| 20 | } | ||
| 21 | 30 | ||
| 22 | void MM_U::SetAndWait(Kernel::HLERequestContext& ctx) { | 31 | private: |
| 23 | IPC::RequestParser rp{ctx}; | 32 | void Initialize(Kernel::HLERequestContext& ctx) { |
| 24 | min = rp.Pop<u32>(); | 33 | LOG_WARNING(Service_MM, "(STUBBED) called"); |
| 25 | max = rp.Pop<u32>(); | 34 | IPC::ResponseBuilder rb{ctx, 2}; |
| 26 | current = min; | 35 | rb.Push(RESULT_SUCCESS); |
| 36 | } | ||
| 27 | 37 | ||
| 28 | LOG_WARNING(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max); | 38 | void Finalize(Kernel::HLERequestContext& ctx) { |
| 29 | IPC::ResponseBuilder rb{ctx, 2}; | 39 | LOG_WARNING(Service_MM, "(STUBBED) called"); |
| 30 | rb.Push(RESULT_SUCCESS); | 40 | IPC::ResponseBuilder rb{ctx, 2}; |
| 31 | } | 41 | rb.Push(RESULT_SUCCESS); |
| 42 | } | ||
| 32 | 43 | ||
| 33 | void MM_U::Get(Kernel::HLERequestContext& ctx) { | 44 | void SetAndWait(Kernel::HLERequestContext& ctx) { |
| 34 | LOG_WARNING(Service_MM, "(STUBBED) called"); | 45 | IPC::RequestParser rp{ctx}; |
| 35 | IPC::ResponseBuilder rb{ctx, 3}; | 46 | min = rp.Pop<u32>(); |
| 36 | rb.Push(RESULT_SUCCESS); | 47 | max = rp.Pop<u32>(); |
| 37 | rb.Push(current); | 48 | current = min; |
| 38 | } | ||
| 39 | 49 | ||
| 40 | MM_U::MM_U() : ServiceFramework("mm:u") { | 50 | LOG_WARNING(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max); |
| 41 | static const FunctionInfo functions[] = { | 51 | IPC::ResponseBuilder rb{ctx, 2}; |
| 42 | {0, nullptr, "InitializeOld"}, {1, nullptr, "FinalizeOld"}, | 52 | rb.Push(RESULT_SUCCESS); |
| 43 | {2, nullptr, "SetAndWaitOld"}, {3, nullptr, "GetOld"}, | 53 | } |
| 44 | {4, &MM_U::Initialize, "Initialize"}, {5, nullptr, "Finalize"}, | 54 | |
| 45 | {6, &MM_U::SetAndWait, "SetAndWait"}, {7, &MM_U::Get, "Get"}, | 55 | void Get(Kernel::HLERequestContext& ctx) { |
| 46 | }; | 56 | LOG_WARNING(Service_MM, "(STUBBED) called"); |
| 47 | RegisterHandlers(functions); | 57 | IPC::ResponseBuilder rb{ctx, 3}; |
| 58 | rb.Push(RESULT_SUCCESS); | ||
| 59 | rb.Push(current); | ||
| 60 | } | ||
| 61 | |||
| 62 | u32 min{0}; | ||
| 63 | u32 max{0}; | ||
| 64 | u32 current{0}; | ||
| 65 | }; | ||
| 66 | |||
| 67 | void InstallInterfaces(SM::ServiceManager& service_manager) { | ||
| 68 | std::make_shared<MM_U>()->InstallAsService(service_manager); | ||
| 48 | } | 69 | } |
| 49 | 70 | ||
| 50 | } // namespace Service::MM | 71 | } // namespace Service::MM |
diff --git a/src/core/hle/service/mm/mm_u.h b/src/core/hle/service/mm/mm_u.h index 79eeedf9c..5439fa653 100644 --- a/src/core/hle/service/mm/mm_u.h +++ b/src/core/hle/service/mm/mm_u.h | |||
| @@ -8,21 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::MM { | 9 | namespace Service::MM { |
| 10 | 10 | ||
| 11 | class MM_U final : public ServiceFramework<MM_U> { | ||
| 12 | public: | ||
| 13 | MM_U(); | ||
| 14 | ~MM_U() = default; | ||
| 15 | |||
| 16 | private: | ||
| 17 | void Initialize(Kernel::HLERequestContext& ctx); | ||
| 18 | void SetAndWait(Kernel::HLERequestContext& ctx); | ||
| 19 | void Get(Kernel::HLERequestContext& ctx); | ||
| 20 | |||
| 21 | u32 min{0}; | ||
| 22 | u32 max{0}; | ||
| 23 | u32 current{0}; | ||
| 24 | }; | ||
| 25 | |||
| 26 | /// Registers all MM services with the specified service manager. | 11 | /// Registers all MM services with the specified service manager. |
| 27 | void InstallInterfaces(SM::ServiceManager& service_manager); | 12 | void InstallInterfaces(SM::ServiceManager& service_manager); |
| 28 | 13 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp new file mode 100644 index 000000000..51f01077b --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <cstring> | ||
| 6 | |||
| 7 | #include "common/assert.h" | ||
| 8 | #include "common/logging/log.h" | ||
| 9 | #include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h" | ||
| 10 | |||
| 11 | namespace Service::Nvidia::Devices { | ||
| 12 | |||
| 13 | u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 14 | LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", | ||
| 15 | command.raw, input.size(), output.size()); | ||
| 16 | |||
| 17 | switch (static_cast<IoctlCommand>(command.raw)) { | ||
| 18 | case IoctlCommand::IocSetNVMAPfdCommand: | ||
| 19 | return SetNVMAPfd(input, output); | ||
| 20 | } | ||
| 21 | |||
| 22 | UNIMPLEMENTED_MSG("Unimplemented ioctl"); | ||
| 23 | return 0; | ||
| 24 | } | ||
| 25 | |||
| 26 | u32 nvhost_nvjpg::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 27 | IoctlSetNvmapFD params{}; | ||
| 28 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 29 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | ||
| 30 | nvmap_fd = params.nvmap_fd; | ||
| 31 | return 0; | ||
| 32 | } | ||
| 33 | |||
| 34 | } // namespace Service::Nvidia::Devices | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h new file mode 100644 index 000000000..2b0eb43ee --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <vector> | ||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "common/swap.h" | ||
| 10 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||
| 11 | |||
| 12 | namespace Service::Nvidia::Devices { | ||
| 13 | |||
| 14 | class nvhost_nvjpg final : public nvdevice { | ||
| 15 | public: | ||
| 16 | nvhost_nvjpg() = default; | ||
| 17 | ~nvhost_nvjpg() override = default; | ||
| 18 | |||
| 19 | u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; | ||
| 20 | |||
| 21 | private: | ||
| 22 | enum class IoctlCommand : u32_le { | ||
| 23 | IocSetNVMAPfdCommand = 0x40044801, | ||
| 24 | }; | ||
| 25 | |||
| 26 | struct IoctlSetNvmapFD { | ||
| 27 | u32_le nvmap_fd; | ||
| 28 | }; | ||
| 29 | static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); | ||
| 30 | |||
| 31 | u32_le nvmap_fd{}; | ||
| 32 | |||
| 33 | u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 34 | }; | ||
| 35 | |||
| 36 | } // namespace Service::Nvidia::Devices | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp new file mode 100644 index 000000000..fcb488d50 --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <cstring> | ||
| 6 | |||
| 7 | #include "common/assert.h" | ||
| 8 | #include "common/logging/log.h" | ||
| 9 | #include "core/hle/service/nvdrv/devices/nvhost_vic.h" | ||
| 10 | |||
| 11 | namespace Service::Nvidia::Devices { | ||
| 12 | |||
| 13 | u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 14 | LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", | ||
| 15 | command.raw, input.size(), output.size()); | ||
| 16 | |||
| 17 | switch (static_cast<IoctlCommand>(command.raw)) { | ||
| 18 | case IoctlCommand::IocSetNVMAPfdCommand: | ||
| 19 | return SetNVMAPfd(input, output); | ||
| 20 | } | ||
| 21 | |||
| 22 | UNIMPLEMENTED_MSG("Unimplemented ioctl"); | ||
| 23 | return 0; | ||
| 24 | } | ||
| 25 | |||
| 26 | u32 nvhost_vic::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 27 | IoctlSetNvmapFD params{}; | ||
| 28 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 29 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | ||
| 30 | nvmap_fd = params.nvmap_fd; | ||
| 31 | return 0; | ||
| 32 | } | ||
| 33 | |||
| 34 | } // namespace Service::Nvidia::Devices | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h new file mode 100644 index 000000000..c7d681e52 --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <vector> | ||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "common/swap.h" | ||
| 10 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||
| 11 | |||
| 12 | namespace Service::Nvidia::Devices { | ||
| 13 | |||
| 14 | class nvhost_vic final : public nvdevice { | ||
| 15 | public: | ||
| 16 | nvhost_vic() = default; | ||
| 17 | ~nvhost_vic() override = default; | ||
| 18 | |||
| 19 | u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; | ||
| 20 | |||
| 21 | private: | ||
| 22 | enum class IoctlCommand : u32_le { | ||
| 23 | IocSetNVMAPfdCommand = 0x40044801, | ||
| 24 | }; | ||
| 25 | |||
| 26 | struct IoctlSetNvmapFD { | ||
| 27 | u32_le nvmap_fd; | ||
| 28 | }; | ||
| 29 | static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); | ||
| 30 | |||
| 31 | u32_le nvmap_fd{}; | ||
| 32 | |||
| 33 | u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 34 | }; | ||
| 35 | |||
| 36 | } // namespace Service::Nvidia::Devices | ||
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 427f4b574..2de39822f 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | #include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h" | 12 | #include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h" |
| 13 | #include "core/hle/service/nvdrv/devices/nvhost_gpu.h" | 13 | #include "core/hle/service/nvdrv/devices/nvhost_gpu.h" |
| 14 | #include "core/hle/service/nvdrv/devices/nvhost_nvdec.h" | 14 | #include "core/hle/service/nvdrv/devices/nvhost_nvdec.h" |
| 15 | #include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h" | ||
| 16 | #include "core/hle/service/nvdrv/devices/nvhost_vic.h" | ||
| 15 | #include "core/hle/service/nvdrv/devices/nvmap.h" | 17 | #include "core/hle/service/nvdrv/devices/nvmap.h" |
| 16 | #include "core/hle/service/nvdrv/interface.h" | 18 | #include "core/hle/service/nvdrv/interface.h" |
| 17 | #include "core/hle/service/nvdrv/nvdrv.h" | 19 | #include "core/hle/service/nvdrv/nvdrv.h" |
| @@ -39,6 +41,8 @@ Module::Module() { | |||
| 39 | devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev); | 41 | devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev); |
| 40 | devices["/dev/nvhost-ctrl"] = std::make_shared<Devices::nvhost_ctrl>(); | 42 | devices["/dev/nvhost-ctrl"] = std::make_shared<Devices::nvhost_ctrl>(); |
| 41 | devices["/dev/nvhost-nvdec"] = std::make_shared<Devices::nvhost_nvdec>(); | 43 | devices["/dev/nvhost-nvdec"] = std::make_shared<Devices::nvhost_nvdec>(); |
| 44 | devices["/dev/nvhost-nvjpg"] = std::make_shared<Devices::nvhost_nvjpg>(); | ||
| 45 | devices["/dev/nvhost-vic"] = std::make_shared<Devices::nvhost_vic>(); | ||
| 42 | } | 46 | } |
| 43 | 47 | ||
| 44 | u32 Module::Open(const std::string& device_name) { | 48 | u32 Module::Open(const std::string& device_name) { |
diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp index 518a0cc46..1cef73216 100644 --- a/src/core/hle/service/sm/controller.cpp +++ b/src/core/hle/service/sm/controller.cpp | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | namespace Service::SM { | 10 | namespace Service::SM { |
| 11 | 11 | ||
| 12 | void Controller::ConvertSessionToDomain(Kernel::HLERequestContext& ctx) { | 12 | void Controller::ConvertSessionToDomain(Kernel::HLERequestContext& ctx) { |
| 13 | ASSERT_MSG(!ctx.Session()->IsDomain(), "session is alread a domain"); | 13 | ASSERT_MSG(ctx.Session()->IsSession(), "Session is already a domain"); |
| 14 | ctx.Session()->ConvertToDomain(); | 14 | ctx.Session()->ConvertToDomain(); |
| 15 | 15 | ||
| 16 | IPC::ResponseBuilder rb{ctx, 3}; | 16 | IPC::ResponseBuilder rb{ctx, 3}; |
| @@ -41,7 +41,7 @@ void Controller::DuplicateSessionEx(Kernel::HLERequestContext& ctx) { | |||
| 41 | void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) { | 41 | void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) { |
| 42 | IPC::ResponseBuilder rb{ctx, 3}; | 42 | IPC::ResponseBuilder rb{ctx, 3}; |
| 43 | rb.Push(RESULT_SUCCESS); | 43 | rb.Push(RESULT_SUCCESS); |
| 44 | rb.Push<u32>(0x500); | 44 | rb.Push<u16>(0x500); |
| 45 | 45 | ||
| 46 | LOG_WARNING(Service, "(STUBBED) called"); | 46 | LOG_WARNING(Service, "(STUBBED) called"); |
| 47 | } | 47 | } |
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index de05f21d8..d575a9bea 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp | |||
| @@ -118,7 +118,6 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load( | |||
| 118 | 118 | ||
| 119 | process->program_id = metadata.GetTitleID(); | 119 | process->program_id = metadata.GetTitleID(); |
| 120 | process->svc_access_mask.set(); | 120 | process->svc_access_mask.set(); |
| 121 | process->address_mappings = default_address_mappings; | ||
| 122 | process->resource_limit = | 121 | process->resource_limit = |
| 123 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 122 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); |
| 124 | process->Run(Memory::PROCESS_IMAGE_VADDR, metadata.GetMainThreadPriority(), | 123 | process->Run(Memory::PROCESS_IMAGE_VADDR, metadata.GetMainThreadPriority(), |
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 401cad3ab..6420a7f11 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp | |||
| @@ -398,7 +398,6 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) { | |||
| 398 | 398 | ||
| 399 | process->LoadModule(codeset, codeset->entrypoint); | 399 | process->LoadModule(codeset, codeset->entrypoint); |
| 400 | process->svc_access_mask.set(); | 400 | process->svc_access_mask.set(); |
| 401 | process->address_mappings = default_address_mappings; | ||
| 402 | 401 | ||
| 403 | // Attach the default resource limit (APPLICATION) to the process | 402 | // Attach the default resource limit (APPLICATION) to the process |
| 404 | process->resource_limit = | 403 | process->resource_limit = |
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 1f2f31535..b143f043c 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp | |||
| @@ -17,12 +17,6 @@ | |||
| 17 | 17 | ||
| 18 | namespace Loader { | 18 | namespace Loader { |
| 19 | 19 | ||
| 20 | const std::initializer_list<Kernel::AddressMapping> default_address_mappings = { | ||
| 21 | {0x1FF50000, 0x8000, true}, // part of DSP RAM | ||
| 22 | {0x1FF70000, 0x8000, true}, // part of DSP RAM | ||
| 23 | {0x1F000000, 0x600000, false}, // entire VRAM | ||
| 24 | }; | ||
| 25 | |||
| 26 | FileType IdentifyFile(FileSys::VirtualFile file) { | 20 | FileType IdentifyFile(FileSys::VirtualFile file) { |
| 27 | FileType type; | 21 | FileType type; |
| 28 | 22 | ||
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 285363549..6dffe451a 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <algorithm> | 7 | #include <algorithm> |
| 8 | #include <initializer_list> | ||
| 9 | #include <memory> | 8 | #include <memory> |
| 10 | #include <string> | 9 | #include <string> |
| 11 | #include <utility> | 10 | #include <utility> |
| @@ -208,12 +207,6 @@ protected: | |||
| 208 | }; | 207 | }; |
| 209 | 208 | ||
| 210 | /** | 209 | /** |
| 211 | * Common address mappings found in most games, used for binary formats that don't have this | ||
| 212 | * information. | ||
| 213 | */ | ||
| 214 | extern const std::initializer_list<Kernel::AddressMapping> default_address_mappings; | ||
| 215 | |||
| 216 | /** | ||
| 217 | * Identifies a bootable file and return a suitable loader | 210 | * Identifies a bootable file and return a suitable loader |
| 218 | * @param file The bootable file | 211 | * @param file The bootable file |
| 219 | * @return the best loader for this file | 212 | * @return the best loader for this file |
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 908d91eab..2179cf2ea 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -186,7 +186,6 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) { | |||
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | process->svc_access_mask.set(); | 188 | process->svc_access_mask.set(); |
| 189 | process->address_mappings = default_address_mappings; | ||
| 190 | process->resource_limit = | 189 | process->resource_limit = |
| 191 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 190 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); |
| 192 | process->Run(base_addr, THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); | 191 | process->Run(base_addr, THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index fee7d58c6..a94558ac5 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -152,7 +152,6 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) { | |||
| 152 | LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), Memory::PROCESS_IMAGE_VADDR); | 152 | LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), Memory::PROCESS_IMAGE_VADDR); |
| 153 | 153 | ||
| 154 | process->svc_access_mask.set(); | 154 | process->svc_access_mask.set(); |
| 155 | process->address_mappings = default_address_mappings; | ||
| 156 | process->resource_limit = | 155 | process->resource_limit = |
| 157 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 156 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); |
| 158 | process->Run(Memory::PROCESS_IMAGE_VADDR, THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); | 157 | process->Run(Memory::PROCESS_IMAGE_VADDR, THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 6f0343888..5a593c1f7 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -47,8 +47,10 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { | |||
| 47 | case RenderTargetFormat::RGBA32_UINT: | 47 | case RenderTargetFormat::RGBA32_UINT: |
| 48 | return 16; | 48 | return 16; |
| 49 | case RenderTargetFormat::RGBA16_UINT: | 49 | case RenderTargetFormat::RGBA16_UINT: |
| 50 | case RenderTargetFormat::RGBA16_UNORM: | ||
| 50 | case RenderTargetFormat::RGBA16_FLOAT: | 51 | case RenderTargetFormat::RGBA16_FLOAT: |
| 51 | case RenderTargetFormat::RG32_FLOAT: | 52 | case RenderTargetFormat::RG32_FLOAT: |
| 53 | case RenderTargetFormat::RG32_UINT: | ||
| 52 | return 8; | 54 | return 8; |
| 53 | case RenderTargetFormat::RGBA8_UNORM: | 55 | case RenderTargetFormat::RGBA8_UNORM: |
| 54 | case RenderTargetFormat::RGBA8_SNORM: | 56 | case RenderTargetFormat::RGBA8_SNORM: |
| @@ -62,6 +64,7 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { | |||
| 62 | case RenderTargetFormat::RG16_FLOAT: | 64 | case RenderTargetFormat::RG16_FLOAT: |
| 63 | case RenderTargetFormat::R32_FLOAT: | 65 | case RenderTargetFormat::R32_FLOAT: |
| 64 | case RenderTargetFormat::R11G11B10_FLOAT: | 66 | case RenderTargetFormat::R11G11B10_FLOAT: |
| 67 | case RenderTargetFormat::R32_UINT: | ||
| 65 | return 4; | 68 | return 4; |
| 66 | case RenderTargetFormat::R16_UNORM: | 69 | case RenderTargetFormat::R16_UNORM: |
| 67 | case RenderTargetFormat::R16_SNORM: | 70 | case RenderTargetFormat::R16_SNORM: |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 73abb7a18..97dcccb92 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -20,9 +20,11 @@ enum class RenderTargetFormat : u32 { | |||
| 20 | NONE = 0x0, | 20 | NONE = 0x0, |
| 21 | RGBA32_FLOAT = 0xC0, | 21 | RGBA32_FLOAT = 0xC0, |
| 22 | RGBA32_UINT = 0xC2, | 22 | RGBA32_UINT = 0xC2, |
| 23 | RGBA16_UNORM = 0xC6, | ||
| 23 | RGBA16_UINT = 0xC9, | 24 | RGBA16_UINT = 0xC9, |
| 24 | RGBA16_FLOAT = 0xCA, | 25 | RGBA16_FLOAT = 0xCA, |
| 25 | RG32_FLOAT = 0xCB, | 26 | RG32_FLOAT = 0xCB, |
| 27 | RG32_UINT = 0xCD, | ||
| 26 | BGRA8_UNORM = 0xCF, | 28 | BGRA8_UNORM = 0xCF, |
| 27 | RGB10_A2_UNORM = 0xD1, | 29 | RGB10_A2_UNORM = 0xD1, |
| 28 | RGBA8_UNORM = 0xD5, | 30 | RGBA8_UNORM = 0xD5, |
| @@ -34,6 +36,7 @@ enum class RenderTargetFormat : u32 { | |||
| 34 | RG16_UINT = 0xDD, | 36 | RG16_UINT = 0xDD, |
| 35 | RG16_FLOAT = 0xDE, | 37 | RG16_FLOAT = 0xDE, |
| 36 | R11G11B10_FLOAT = 0xE0, | 38 | R11G11B10_FLOAT = 0xE0, |
| 39 | R32_UINT = 0xE4, | ||
| 37 | R32_FLOAT = 0xE5, | 40 | R32_FLOAT = 0xE5, |
| 38 | B5G6R5_UNORM = 0xE8, | 41 | B5G6R5_UNORM = 0xE8, |
| 39 | RG8_UNORM = 0xEA, | 42 | RG8_UNORM = 0xEA, |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 52a649e2f..9d1549fe9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -648,11 +648,11 @@ std::tuple<u8*, GLintptr, u32> RasterizerOpenGL::SetupConstBuffers( | |||
| 648 | 648 | ||
| 649 | if (used_buffer.IsIndirect()) { | 649 | if (used_buffer.IsIndirect()) { |
| 650 | // Buffer is accessed indirectly, so upload the entire thing | 650 | // Buffer is accessed indirectly, so upload the entire thing |
| 651 | size = buffer.size * sizeof(float); | 651 | size = buffer.size; |
| 652 | 652 | ||
| 653 | if (size > MaxConstbufferSize) { | 653 | if (size > MaxConstbufferSize) { |
| 654 | LOG_ERROR(HW_GPU, "indirect constbuffer size {} exceeds maximum {}", size, | 654 | LOG_CRITICAL(HW_GPU, "indirect constbuffer size {} exceeds maximum {}", size, |
| 655 | MaxConstbufferSize); | 655 | MaxConstbufferSize); |
| 656 | size = MaxConstbufferSize; | 656 | size = MaxConstbufferSize; |
| 657 | } | 657 | } |
| 658 | } else { | 658 | } else { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index d635550d2..b6947b97b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -94,13 +94,14 @@ struct FormatTuple { | |||
| 94 | static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{ | 94 | static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{ |
| 95 | {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // ABGR8U | 95 | {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // ABGR8U |
| 96 | {GL_RGBA8, GL_RGBA, GL_BYTE, ComponentType::SNorm, false}, // ABGR8S | 96 | {GL_RGBA8, GL_RGBA, GL_BYTE, ComponentType::SNorm, false}, // ABGR8S |
| 97 | {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, ComponentType::UNorm, false}, // B5G6R5 | 97 | {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, ComponentType::UNorm, false}, // B5G6R5U |
| 98 | {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, ComponentType::UNorm, | 98 | {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, ComponentType::UNorm, |
| 99 | false}, // A2B10G10R10 | 99 | false}, // A2B10G10R10U |
| 100 | {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, ComponentType::UNorm, false}, // A1B5G5R5 | 100 | {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, ComponentType::UNorm, false}, // A1B5G5R5U |
| 101 | {GL_R8, GL_RED, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // R8 | 101 | {GL_R8, GL_RED, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // R8U |
| 102 | {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, ComponentType::UInt, false}, // R8UI | 102 | {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, ComponentType::UInt, false}, // R8UI |
| 103 | {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, ComponentType::Float, false}, // RGBA16F | 103 | {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, ComponentType::Float, false}, // RGBA16F |
| 104 | {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // RGBA16U | ||
| 104 | {GL_RGBA16UI, GL_RGBA, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // RGBA16UI | 105 | {GL_RGBA16UI, GL_RGBA, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // RGBA16UI |
| 105 | {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, ComponentType::Float, | 106 | {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, ComponentType::Float, |
| 106 | false}, // R11FG11FB10F | 107 | false}, // R11FG11FB10F |
| @@ -115,16 +116,17 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form | |||
| 115 | {GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, | 116 | {GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, |
| 116 | true}, // DXN2UNORM | 117 | true}, // DXN2UNORM |
| 117 | {GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_INT, ComponentType::SNorm, true}, // DXN2SNORM | 118 | {GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_INT, ComponentType::SNorm, true}, // DXN2SNORM |
| 118 | {GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, | 119 | {GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, |
| 119 | true}, // BC7U | 120 | true}, // BC7U |
| 120 | {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4 | 121 | {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4 |
| 121 | {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // G8R8 | 122 | {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // G8R8U |
| 123 | {GL_RG8, GL_RG, GL_BYTE, ComponentType::SNorm, false}, // G8R8S | ||
| 122 | {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // BGRA8 | 124 | {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // BGRA8 |
| 123 | {GL_RGBA32F, GL_RGBA, GL_FLOAT, ComponentType::Float, false}, // RGBA32F | 125 | {GL_RGBA32F, GL_RGBA, GL_FLOAT, ComponentType::Float, false}, // RGBA32F |
| 124 | {GL_RG32F, GL_RG, GL_FLOAT, ComponentType::Float, false}, // RG32F | 126 | {GL_RG32F, GL_RG, GL_FLOAT, ComponentType::Float, false}, // RG32F |
| 125 | {GL_R32F, GL_RED, GL_FLOAT, ComponentType::Float, false}, // R32F | 127 | {GL_R32F, GL_RED, GL_FLOAT, ComponentType::Float, false}, // R32F |
| 126 | {GL_R16F, GL_RED, GL_HALF_FLOAT, ComponentType::Float, false}, // R16F | 128 | {GL_R16F, GL_RED, GL_HALF_FLOAT, ComponentType::Float, false}, // R16F |
| 127 | {GL_R16, GL_RED, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // R16UNORM | 129 | {GL_R16, GL_RED, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // R16U |
| 128 | {GL_R16_SNORM, GL_RED, GL_SHORT, ComponentType::SNorm, false}, // R16S | 130 | {GL_R16_SNORM, GL_RED, GL_SHORT, ComponentType::SNorm, false}, // R16S |
| 129 | {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // R16UI | 131 | {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // R16UI |
| 130 | {GL_R16I, GL_RED_INTEGER, GL_SHORT, ComponentType::SInt, false}, // R16I | 132 | {GL_R16I, GL_RED_INTEGER, GL_SHORT, ComponentType::SInt, false}, // R16I |
| @@ -137,6 +139,8 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form | |||
| 137 | {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // SRGBA8 | 139 | {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // SRGBA8 |
| 138 | {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // RG8U | 140 | {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // RG8U |
| 139 | {GL_RG8, GL_RG, GL_BYTE, ComponentType::SNorm, false}, // RG8S | 141 | {GL_RG8, GL_RG, GL_BYTE, ComponentType::SNorm, false}, // RG8S |
| 142 | {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // RG32UI | ||
| 143 | {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // R32UI | ||
| 140 | 144 | ||
| 141 | // DepthStencil formats | 145 | // DepthStencil formats |
| 142 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm, | 146 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm, |
| @@ -239,12 +243,13 @@ static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, Tegra::GPU | |||
| 239 | // clang-format off | 243 | // clang-format off |
| 240 | MortonCopy<true, PixelFormat::ABGR8U>, | 244 | MortonCopy<true, PixelFormat::ABGR8U>, |
| 241 | MortonCopy<true, PixelFormat::ABGR8S>, | 245 | MortonCopy<true, PixelFormat::ABGR8S>, |
| 242 | MortonCopy<true, PixelFormat::B5G6R5>, | 246 | MortonCopy<true, PixelFormat::B5G6R5U>, |
| 243 | MortonCopy<true, PixelFormat::A2B10G10R10>, | 247 | MortonCopy<true, PixelFormat::A2B10G10R10U>, |
| 244 | MortonCopy<true, PixelFormat::A1B5G5R5>, | 248 | MortonCopy<true, PixelFormat::A1B5G5R5U>, |
| 245 | MortonCopy<true, PixelFormat::R8>, | 249 | MortonCopy<true, PixelFormat::R8U>, |
| 246 | MortonCopy<true, PixelFormat::R8UI>, | 250 | MortonCopy<true, PixelFormat::R8UI>, |
| 247 | MortonCopy<true, PixelFormat::RGBA16F>, | 251 | MortonCopy<true, PixelFormat::RGBA16F>, |
| 252 | MortonCopy<true, PixelFormat::RGBA16U>, | ||
| 248 | MortonCopy<true, PixelFormat::RGBA16UI>, | 253 | MortonCopy<true, PixelFormat::RGBA16UI>, |
| 249 | MortonCopy<true, PixelFormat::R11FG11FB10F>, | 254 | MortonCopy<true, PixelFormat::R11FG11FB10F>, |
| 250 | MortonCopy<true, PixelFormat::RGBA32UI>, | 255 | MortonCopy<true, PixelFormat::RGBA32UI>, |
| @@ -256,13 +261,14 @@ static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, Tegra::GPU | |||
| 256 | MortonCopy<true, PixelFormat::DXN2SNORM>, | 261 | MortonCopy<true, PixelFormat::DXN2SNORM>, |
| 257 | MortonCopy<true, PixelFormat::BC7U>, | 262 | MortonCopy<true, PixelFormat::BC7U>, |
| 258 | MortonCopy<true, PixelFormat::ASTC_2D_4X4>, | 263 | MortonCopy<true, PixelFormat::ASTC_2D_4X4>, |
| 259 | MortonCopy<true, PixelFormat::G8R8>, | 264 | MortonCopy<true, PixelFormat::G8R8U>, |
| 265 | MortonCopy<true, PixelFormat::G8R8S>, | ||
| 260 | MortonCopy<true, PixelFormat::BGRA8>, | 266 | MortonCopy<true, PixelFormat::BGRA8>, |
| 261 | MortonCopy<true, PixelFormat::RGBA32F>, | 267 | MortonCopy<true, PixelFormat::RGBA32F>, |
| 262 | MortonCopy<true, PixelFormat::RG32F>, | 268 | MortonCopy<true, PixelFormat::RG32F>, |
| 263 | MortonCopy<true, PixelFormat::R32F>, | 269 | MortonCopy<true, PixelFormat::R32F>, |
| 264 | MortonCopy<true, PixelFormat::R16F>, | 270 | MortonCopy<true, PixelFormat::R16F>, |
| 265 | MortonCopy<true, PixelFormat::R16UNORM>, | 271 | MortonCopy<true, PixelFormat::R16U>, |
| 266 | MortonCopy<true, PixelFormat::R16S>, | 272 | MortonCopy<true, PixelFormat::R16S>, |
| 267 | MortonCopy<true, PixelFormat::R16UI>, | 273 | MortonCopy<true, PixelFormat::R16UI>, |
| 268 | MortonCopy<true, PixelFormat::R16I>, | 274 | MortonCopy<true, PixelFormat::R16I>, |
| @@ -275,6 +281,8 @@ static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, Tegra::GPU | |||
| 275 | MortonCopy<true, PixelFormat::SRGBA8>, | 281 | MortonCopy<true, PixelFormat::SRGBA8>, |
| 276 | MortonCopy<true, PixelFormat::RG8U>, | 282 | MortonCopy<true, PixelFormat::RG8U>, |
| 277 | MortonCopy<true, PixelFormat::RG8S>, | 283 | MortonCopy<true, PixelFormat::RG8S>, |
| 284 | MortonCopy<true, PixelFormat::RG32UI>, | ||
| 285 | MortonCopy<true, PixelFormat::R32UI>, | ||
| 278 | MortonCopy<true, PixelFormat::Z24S8>, | 286 | MortonCopy<true, PixelFormat::Z24S8>, |
| 279 | MortonCopy<true, PixelFormat::S8Z24>, | 287 | MortonCopy<true, PixelFormat::S8Z24>, |
| 280 | MortonCopy<true, PixelFormat::Z32F>, | 288 | MortonCopy<true, PixelFormat::Z32F>, |
| @@ -289,12 +297,13 @@ static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, Tegra::GPU | |||
| 289 | // clang-format off | 297 | // clang-format off |
| 290 | MortonCopy<false, PixelFormat::ABGR8U>, | 298 | MortonCopy<false, PixelFormat::ABGR8U>, |
| 291 | MortonCopy<false, PixelFormat::ABGR8S>, | 299 | MortonCopy<false, PixelFormat::ABGR8S>, |
| 292 | MortonCopy<false, PixelFormat::B5G6R5>, | 300 | MortonCopy<false, PixelFormat::B5G6R5U>, |
| 293 | MortonCopy<false, PixelFormat::A2B10G10R10>, | 301 | MortonCopy<false, PixelFormat::A2B10G10R10U>, |
| 294 | MortonCopy<false, PixelFormat::A1B5G5R5>, | 302 | MortonCopy<false, PixelFormat::A1B5G5R5U>, |
| 295 | MortonCopy<false, PixelFormat::R8>, | 303 | MortonCopy<false, PixelFormat::R8U>, |
| 296 | MortonCopy<false, PixelFormat::R8UI>, | 304 | MortonCopy<false, PixelFormat::R8UI>, |
| 297 | MortonCopy<false, PixelFormat::RGBA16F>, | 305 | MortonCopy<false, PixelFormat::RGBA16F>, |
| 306 | MortonCopy<false, PixelFormat::RGBA16U>, | ||
| 298 | MortonCopy<false, PixelFormat::RGBA16UI>, | 307 | MortonCopy<false, PixelFormat::RGBA16UI>, |
| 299 | MortonCopy<false, PixelFormat::R11FG11FB10F>, | 308 | MortonCopy<false, PixelFormat::R11FG11FB10F>, |
| 300 | MortonCopy<false, PixelFormat::RGBA32UI>, | 309 | MortonCopy<false, PixelFormat::RGBA32UI>, |
| @@ -308,13 +317,14 @@ static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, Tegra::GPU | |||
| 308 | nullptr, | 317 | nullptr, |
| 309 | nullptr, | 318 | nullptr, |
| 310 | nullptr, | 319 | nullptr, |
| 311 | MortonCopy<false, PixelFormat::G8R8>, | 320 | MortonCopy<false, PixelFormat::G8R8U>, |
| 321 | MortonCopy<false, PixelFormat::G8R8S>, | ||
| 312 | MortonCopy<false, PixelFormat::BGRA8>, | 322 | MortonCopy<false, PixelFormat::BGRA8>, |
| 313 | MortonCopy<false, PixelFormat::RGBA32F>, | 323 | MortonCopy<false, PixelFormat::RGBA32F>, |
| 314 | MortonCopy<false, PixelFormat::RG32F>, | 324 | MortonCopy<false, PixelFormat::RG32F>, |
| 315 | MortonCopy<false, PixelFormat::R32F>, | 325 | MortonCopy<false, PixelFormat::R32F>, |
| 316 | MortonCopy<false, PixelFormat::R16F>, | 326 | MortonCopy<false, PixelFormat::R16F>, |
| 317 | MortonCopy<false, PixelFormat::R16UNORM>, | 327 | MortonCopy<false, PixelFormat::R16U>, |
| 318 | MortonCopy<false, PixelFormat::R16S>, | 328 | MortonCopy<false, PixelFormat::R16S>, |
| 319 | MortonCopy<false, PixelFormat::R16UI>, | 329 | MortonCopy<false, PixelFormat::R16UI>, |
| 320 | MortonCopy<false, PixelFormat::R16I>, | 330 | MortonCopy<false, PixelFormat::R16I>, |
| @@ -327,6 +337,8 @@ static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, Tegra::GPU | |||
| 327 | MortonCopy<false, PixelFormat::SRGBA8>, | 337 | MortonCopy<false, PixelFormat::SRGBA8>, |
| 328 | MortonCopy<false, PixelFormat::RG8U>, | 338 | MortonCopy<false, PixelFormat::RG8U>, |
| 329 | MortonCopy<false, PixelFormat::RG8S>, | 339 | MortonCopy<false, PixelFormat::RG8S>, |
| 340 | MortonCopy<false, PixelFormat::RG32UI>, | ||
| 341 | MortonCopy<false, PixelFormat::R32UI>, | ||
| 330 | MortonCopy<false, PixelFormat::Z24S8>, | 342 | MortonCopy<false, PixelFormat::Z24S8>, |
| 331 | MortonCopy<false, PixelFormat::S8Z24>, | 343 | MortonCopy<false, PixelFormat::S8Z24>, |
| 332 | MortonCopy<false, PixelFormat::Z32F>, | 344 | MortonCopy<false, PixelFormat::Z32F>, |
| @@ -452,7 +464,7 @@ static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) { | |||
| 452 | } | 464 | } |
| 453 | 465 | ||
| 454 | static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) { | 466 | static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) { |
| 455 | const auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::G8R8)}; | 467 | const auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::G8R8U)}; |
| 456 | for (size_t y = 0; y < height; ++y) { | 468 | for (size_t y = 0; y < height; ++y) { |
| 457 | for (size_t x = 0; x < width; ++x) { | 469 | for (size_t x = 0; x < width; ++x) { |
| 458 | const size_t offset{bpp * (y * width + x)}; | 470 | const size_t offset{bpp * (y * width + x)}; |
| @@ -484,7 +496,8 @@ static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelForma | |||
| 484 | ConvertS8Z24ToZ24S8(data, width, height); | 496 | ConvertS8Z24ToZ24S8(data, width, height); |
| 485 | break; | 497 | break; |
| 486 | 498 | ||
| 487 | case PixelFormat::G8R8: | 499 | case PixelFormat::G8R8U: |
| 500 | case PixelFormat::G8R8S: | ||
| 488 | // Convert the G8R8 color format to R8G8, as OpenGL does not support G8R8. | 501 | // Convert the G8R8 color format to R8G8, as OpenGL does not support G8R8. |
| 489 | ConvertG8R8ToR8G8(data, width, height); | 502 | ConvertG8R8ToR8G8(data, width, height); |
| 490 | break; | 503 | break; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 4ab74342e..55cf3782c 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h | |||
| @@ -25,51 +25,55 @@ struct SurfaceParams { | |||
| 25 | enum class PixelFormat { | 25 | enum class PixelFormat { |
| 26 | ABGR8U = 0, | 26 | ABGR8U = 0, |
| 27 | ABGR8S = 1, | 27 | ABGR8S = 1, |
| 28 | B5G6R5 = 2, | 28 | B5G6R5U = 2, |
| 29 | A2B10G10R10 = 3, | 29 | A2B10G10R10U = 3, |
| 30 | A1B5G5R5 = 4, | 30 | A1B5G5R5U = 4, |
| 31 | R8 = 5, | 31 | R8U = 5, |
| 32 | R8UI = 6, | 32 | R8UI = 6, |
| 33 | RGBA16F = 7, | 33 | RGBA16F = 7, |
| 34 | RGBA16UI = 8, | 34 | RGBA16U = 8, |
| 35 | R11FG11FB10F = 9, | 35 | RGBA16UI = 9, |
| 36 | RGBA32UI = 10, | 36 | R11FG11FB10F = 10, |
| 37 | DXT1 = 11, | 37 | RGBA32UI = 11, |
| 38 | DXT23 = 12, | 38 | DXT1 = 12, |
| 39 | DXT45 = 13, | 39 | DXT23 = 13, |
| 40 | DXN1 = 14, // This is also known as BC4 | 40 | DXT45 = 14, |
| 41 | DXN2UNORM = 15, | 41 | DXN1 = 15, // This is also known as BC4 |
| 42 | DXN2SNORM = 16, | 42 | DXN2UNORM = 16, |
| 43 | BC7U = 17, | 43 | DXN2SNORM = 17, |
| 44 | ASTC_2D_4X4 = 18, | 44 | BC7U = 18, |
| 45 | G8R8 = 19, | 45 | ASTC_2D_4X4 = 19, |
| 46 | BGRA8 = 20, | 46 | G8R8U = 20, |
| 47 | RGBA32F = 21, | 47 | G8R8S = 21, |
| 48 | RG32F = 22, | 48 | BGRA8 = 22, |
| 49 | R32F = 23, | 49 | RGBA32F = 23, |
| 50 | R16F = 24, | 50 | RG32F = 24, |
| 51 | R16UNORM = 25, | 51 | R32F = 25, |
| 52 | R16S = 26, | 52 | R16F = 26, |
| 53 | R16UI = 27, | 53 | R16U = 27, |
| 54 | R16I = 28, | 54 | R16S = 28, |
| 55 | RG16 = 29, | 55 | R16UI = 29, |
| 56 | RG16F = 30, | 56 | R16I = 30, |
| 57 | RG16UI = 31, | 57 | RG16 = 31, |
| 58 | RG16I = 32, | 58 | RG16F = 32, |
| 59 | RG16S = 33, | 59 | RG16UI = 33, |
| 60 | RGB32F = 34, | 60 | RG16I = 34, |
| 61 | SRGBA8 = 35, | 61 | RG16S = 35, |
| 62 | RG8U = 36, | 62 | RGB32F = 36, |
| 63 | RG8S = 37, | 63 | SRGBA8 = 37, |
| 64 | RG8U = 38, | ||
| 65 | RG8S = 39, | ||
| 66 | RG32UI = 40, | ||
| 67 | R32UI = 41, | ||
| 64 | 68 | ||
| 65 | MaxColorFormat, | 69 | MaxColorFormat, |
| 66 | 70 | ||
| 67 | // DepthStencil formats | 71 | // DepthStencil formats |
| 68 | Z24S8 = 38, | 72 | Z24S8 = 42, |
| 69 | S8Z24 = 39, | 73 | S8Z24 = 43, |
| 70 | Z32F = 40, | 74 | Z32F = 44, |
| 71 | Z16 = 41, | 75 | Z16 = 45, |
| 72 | Z32FS8 = 42, | 76 | Z32FS8 = 46, |
| 73 | 77 | ||
| 74 | MaxDepthStencilFormat, | 78 | MaxDepthStencilFormat, |
| 75 | 79 | ||
| @@ -109,12 +113,13 @@ struct SurfaceParams { | |||
| 109 | constexpr std::array<u32, MaxPixelFormat> compression_factor_table = {{ | 113 | constexpr std::array<u32, MaxPixelFormat> compression_factor_table = {{ |
| 110 | 1, // ABGR8U | 114 | 1, // ABGR8U |
| 111 | 1, // ABGR8S | 115 | 1, // ABGR8S |
| 112 | 1, // B5G6R5 | 116 | 1, // B5G6R5U |
| 113 | 1, // A2B10G10R10 | 117 | 1, // A2B10G10R10U |
| 114 | 1, // A1B5G5R5 | 118 | 1, // A1B5G5R5U |
| 115 | 1, // R8 | 119 | 1, // R8U |
| 116 | 1, // R8UI | 120 | 1, // R8UI |
| 117 | 1, // RGBA16F | 121 | 1, // RGBA16F |
| 122 | 1, // RGBA16U | ||
| 118 | 1, // RGBA16UI | 123 | 1, // RGBA16UI |
| 119 | 1, // R11FG11FB10F | 124 | 1, // R11FG11FB10F |
| 120 | 1, // RGBA32UI | 125 | 1, // RGBA32UI |
| @@ -126,13 +131,14 @@ struct SurfaceParams { | |||
| 126 | 4, // DXN2SNORM | 131 | 4, // DXN2SNORM |
| 127 | 4, // BC7U | 132 | 4, // BC7U |
| 128 | 4, // ASTC_2D_4X4 | 133 | 4, // ASTC_2D_4X4 |
| 129 | 1, // G8R8 | 134 | 1, // G8R8U |
| 135 | 1, // G8R8S | ||
| 130 | 1, // BGRA8 | 136 | 1, // BGRA8 |
| 131 | 1, // RGBA32F | 137 | 1, // RGBA32F |
| 132 | 1, // RG32F | 138 | 1, // RG32F |
| 133 | 1, // R32F | 139 | 1, // R32F |
| 134 | 1, // R16F | 140 | 1, // R16F |
| 135 | 1, // R16UNORM | 141 | 1, // R16U |
| 136 | 1, // R16S | 142 | 1, // R16S |
| 137 | 1, // R16UI | 143 | 1, // R16UI |
| 138 | 1, // R16I | 144 | 1, // R16I |
| @@ -145,6 +151,8 @@ struct SurfaceParams { | |||
| 145 | 1, // SRGBA8 | 151 | 1, // SRGBA8 |
| 146 | 1, // RG8U | 152 | 1, // RG8U |
| 147 | 1, // RG8S | 153 | 1, // RG8S |
| 154 | 1, // RG32UI | ||
| 155 | 1, // R32UI | ||
| 148 | 1, // Z24S8 | 156 | 1, // Z24S8 |
| 149 | 1, // S8Z24 | 157 | 1, // S8Z24 |
| 150 | 1, // Z32F | 158 | 1, // Z32F |
| @@ -163,12 +171,13 @@ struct SurfaceParams { | |||
| 163 | constexpr std::array<u32, MaxPixelFormat> bpp_table = {{ | 171 | constexpr std::array<u32, MaxPixelFormat> bpp_table = {{ |
| 164 | 32, // ABGR8U | 172 | 32, // ABGR8U |
| 165 | 32, // ABGR8S | 173 | 32, // ABGR8S |
| 166 | 16, // B5G6R5 | 174 | 16, // B5G6R5U |
| 167 | 32, // A2B10G10R10 | 175 | 32, // A2B10G10R10U |
| 168 | 16, // A1B5G5R5 | 176 | 16, // A1B5G5R5U |
| 169 | 8, // R8 | 177 | 8, // R8U |
| 170 | 8, // R8UI | 178 | 8, // R8UI |
| 171 | 64, // RGBA16F | 179 | 64, // RGBA16F |
| 180 | 64, // RGBA16U | ||
| 172 | 64, // RGBA16UI | 181 | 64, // RGBA16UI |
| 173 | 32, // R11FG11FB10F | 182 | 32, // R11FG11FB10F |
| 174 | 128, // RGBA32UI | 183 | 128, // RGBA32UI |
| @@ -180,13 +189,14 @@ struct SurfaceParams { | |||
| 180 | 128, // DXN2SNORM | 189 | 128, // DXN2SNORM |
| 181 | 128, // BC7U | 190 | 128, // BC7U |
| 182 | 32, // ASTC_2D_4X4 | 191 | 32, // ASTC_2D_4X4 |
| 183 | 16, // G8R8 | 192 | 16, // G8R8U |
| 193 | 16, // G8R8S | ||
| 184 | 32, // BGRA8 | 194 | 32, // BGRA8 |
| 185 | 128, // RGBA32F | 195 | 128, // RGBA32F |
| 186 | 64, // RG32F | 196 | 64, // RG32F |
| 187 | 32, // R32F | 197 | 32, // R32F |
| 188 | 16, // R16F | 198 | 16, // R16F |
| 189 | 16, // R16UNORM | 199 | 16, // R16U |
| 190 | 16, // R16S | 200 | 16, // R16S |
| 191 | 16, // R16UI | 201 | 16, // R16UI |
| 192 | 16, // R16I | 202 | 16, // R16I |
| @@ -199,6 +209,8 @@ struct SurfaceParams { | |||
| 199 | 32, // SRGBA8 | 209 | 32, // SRGBA8 |
| 200 | 16, // RG8U | 210 | 16, // RG8U |
| 201 | 16, // RG8S | 211 | 16, // RG8S |
| 212 | 64, // RG32UI | ||
| 213 | 32, // R32UI | ||
| 202 | 32, // Z24S8 | 214 | 32, // Z24S8 |
| 203 | 32, // S8Z24 | 215 | 32, // S8Z24 |
| 204 | 32, // Z32F | 216 | 32, // Z32F |
| @@ -244,9 +256,11 @@ struct SurfaceParams { | |||
| 244 | case Tegra::RenderTargetFormat::BGRA8_UNORM: | 256 | case Tegra::RenderTargetFormat::BGRA8_UNORM: |
| 245 | return PixelFormat::BGRA8; | 257 | return PixelFormat::BGRA8; |
| 246 | case Tegra::RenderTargetFormat::RGB10_A2_UNORM: | 258 | case Tegra::RenderTargetFormat::RGB10_A2_UNORM: |
| 247 | return PixelFormat::A2B10G10R10; | 259 | return PixelFormat::A2B10G10R10U; |
| 248 | case Tegra::RenderTargetFormat::RGBA16_FLOAT: | 260 | case Tegra::RenderTargetFormat::RGBA16_FLOAT: |
| 249 | return PixelFormat::RGBA16F; | 261 | return PixelFormat::RGBA16F; |
| 262 | case Tegra::RenderTargetFormat::RGBA16_UNORM: | ||
| 263 | return PixelFormat::RGBA16U; | ||
| 250 | case Tegra::RenderTargetFormat::RGBA16_UINT: | 264 | case Tegra::RenderTargetFormat::RGBA16_UINT: |
| 251 | return PixelFormat::RGBA16UI; | 265 | return PixelFormat::RGBA16UI; |
| 252 | case Tegra::RenderTargetFormat::RGBA32_FLOAT: | 266 | case Tegra::RenderTargetFormat::RGBA32_FLOAT: |
| @@ -256,11 +270,11 @@ struct SurfaceParams { | |||
| 256 | case Tegra::RenderTargetFormat::R11G11B10_FLOAT: | 270 | case Tegra::RenderTargetFormat::R11G11B10_FLOAT: |
| 257 | return PixelFormat::R11FG11FB10F; | 271 | return PixelFormat::R11FG11FB10F; |
| 258 | case Tegra::RenderTargetFormat::B5G6R5_UNORM: | 272 | case Tegra::RenderTargetFormat::B5G6R5_UNORM: |
| 259 | return PixelFormat::B5G6R5; | 273 | return PixelFormat::B5G6R5U; |
| 260 | case Tegra::RenderTargetFormat::RGBA32_UINT: | 274 | case Tegra::RenderTargetFormat::RGBA32_UINT: |
| 261 | return PixelFormat::RGBA32UI; | 275 | return PixelFormat::RGBA32UI; |
| 262 | case Tegra::RenderTargetFormat::R8_UNORM: | 276 | case Tegra::RenderTargetFormat::R8_UNORM: |
| 263 | return PixelFormat::R8; | 277 | return PixelFormat::R8U; |
| 264 | case Tegra::RenderTargetFormat::R8_UINT: | 278 | case Tegra::RenderTargetFormat::R8_UINT: |
| 265 | return PixelFormat::R8UI; | 279 | return PixelFormat::R8UI; |
| 266 | case Tegra::RenderTargetFormat::RG16_FLOAT: | 280 | case Tegra::RenderTargetFormat::RG16_FLOAT: |
| @@ -280,7 +294,7 @@ struct SurfaceParams { | |||
| 280 | case Tegra::RenderTargetFormat::R16_FLOAT: | 294 | case Tegra::RenderTargetFormat::R16_FLOAT: |
| 281 | return PixelFormat::R16F; | 295 | return PixelFormat::R16F; |
| 282 | case Tegra::RenderTargetFormat::R16_UNORM: | 296 | case Tegra::RenderTargetFormat::R16_UNORM: |
| 283 | return PixelFormat::R16UNORM; | 297 | return PixelFormat::R16U; |
| 284 | case Tegra::RenderTargetFormat::R16_SNORM: | 298 | case Tegra::RenderTargetFormat::R16_SNORM: |
| 285 | return PixelFormat::R16S; | 299 | return PixelFormat::R16S; |
| 286 | case Tegra::RenderTargetFormat::R16_UINT: | 300 | case Tegra::RenderTargetFormat::R16_UINT: |
| @@ -289,6 +303,10 @@ struct SurfaceParams { | |||
| 289 | return PixelFormat::R16I; | 303 | return PixelFormat::R16I; |
| 290 | case Tegra::RenderTargetFormat::R32_FLOAT: | 304 | case Tegra::RenderTargetFormat::R32_FLOAT: |
| 291 | return PixelFormat::R32F; | 305 | return PixelFormat::R32F; |
| 306 | case Tegra::RenderTargetFormat::R32_UINT: | ||
| 307 | return PixelFormat::R32UI; | ||
| 308 | case Tegra::RenderTargetFormat::RG32_UINT: | ||
| 309 | return PixelFormat::RG32UI; | ||
| 292 | default: | 310 | default: |
| 293 | LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); | 311 | LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); |
| 294 | UNREACHABLE(); | 312 | UNREACHABLE(); |
| @@ -310,15 +328,33 @@ struct SurfaceParams { | |||
| 310 | static_cast<u32>(component_type)); | 328 | static_cast<u32>(component_type)); |
| 311 | UNREACHABLE(); | 329 | UNREACHABLE(); |
| 312 | case Tegra::Texture::TextureFormat::B5G6R5: | 330 | case Tegra::Texture::TextureFormat::B5G6R5: |
| 313 | return PixelFormat::B5G6R5; | 331 | switch (component_type) { |
| 332 | case Tegra::Texture::ComponentType::UNORM: | ||
| 333 | return PixelFormat::B5G6R5U; | ||
| 334 | } | ||
| 335 | LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", | ||
| 336 | static_cast<u32>(component_type)); | ||
| 337 | UNREACHABLE(); | ||
| 314 | case Tegra::Texture::TextureFormat::A2B10G10R10: | 338 | case Tegra::Texture::TextureFormat::A2B10G10R10: |
| 315 | return PixelFormat::A2B10G10R10; | 339 | switch (component_type) { |
| 340 | case Tegra::Texture::ComponentType::UNORM: | ||
| 341 | return PixelFormat::A2B10G10R10U; | ||
| 342 | } | ||
| 343 | LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", | ||
| 344 | static_cast<u32>(component_type)); | ||
| 345 | UNREACHABLE(); | ||
| 316 | case Tegra::Texture::TextureFormat::A1B5G5R5: | 346 | case Tegra::Texture::TextureFormat::A1B5G5R5: |
| 317 | return PixelFormat::A1B5G5R5; | 347 | switch (component_type) { |
| 348 | case Tegra::Texture::ComponentType::UNORM: | ||
| 349 | return PixelFormat::A1B5G5R5U; | ||
| 350 | } | ||
| 351 | LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", | ||
| 352 | static_cast<u32>(component_type)); | ||
| 353 | UNREACHABLE(); | ||
| 318 | case Tegra::Texture::TextureFormat::R8: | 354 | case Tegra::Texture::TextureFormat::R8: |
| 319 | switch (component_type) { | 355 | switch (component_type) { |
| 320 | case Tegra::Texture::ComponentType::UNORM: | 356 | case Tegra::Texture::ComponentType::UNORM: |
| 321 | return PixelFormat::R8; | 357 | return PixelFormat::R8U; |
| 322 | case Tegra::Texture::ComponentType::UINT: | 358 | case Tegra::Texture::ComponentType::UINT: |
| 323 | return PixelFormat::R8UI; | 359 | return PixelFormat::R8UI; |
| 324 | } | 360 | } |
| @@ -326,11 +362,33 @@ struct SurfaceParams { | |||
| 326 | static_cast<u32>(component_type)); | 362 | static_cast<u32>(component_type)); |
| 327 | UNREACHABLE(); | 363 | UNREACHABLE(); |
| 328 | case Tegra::Texture::TextureFormat::G8R8: | 364 | case Tegra::Texture::TextureFormat::G8R8: |
| 329 | return PixelFormat::G8R8; | 365 | switch (component_type) { |
| 366 | case Tegra::Texture::ComponentType::UNORM: | ||
| 367 | return PixelFormat::G8R8U; | ||
| 368 | case Tegra::Texture::ComponentType::SNORM: | ||
| 369 | return PixelFormat::G8R8S; | ||
| 370 | } | ||
| 371 | LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", | ||
| 372 | static_cast<u32>(component_type)); | ||
| 373 | UNREACHABLE(); | ||
| 330 | case Tegra::Texture::TextureFormat::R16_G16_B16_A16: | 374 | case Tegra::Texture::TextureFormat::R16_G16_B16_A16: |
| 331 | return PixelFormat::RGBA16F; | 375 | switch (component_type) { |
| 376 | case Tegra::Texture::ComponentType::UNORM: | ||
| 377 | return PixelFormat::RGBA16U; | ||
| 378 | case Tegra::Texture::ComponentType::FLOAT: | ||
| 379 | return PixelFormat::RGBA16F; | ||
| 380 | } | ||
| 381 | LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", | ||
| 382 | static_cast<u32>(component_type)); | ||
| 383 | UNREACHABLE(); | ||
| 332 | case Tegra::Texture::TextureFormat::BF10GF11RF11: | 384 | case Tegra::Texture::TextureFormat::BF10GF11RF11: |
| 333 | return PixelFormat::R11FG11FB10F; | 385 | switch (component_type) { |
| 386 | case Tegra::Texture::ComponentType::FLOAT: | ||
| 387 | return PixelFormat::R11FG11FB10F; | ||
| 388 | } | ||
| 389 | LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", | ||
| 390 | static_cast<u32>(component_type)); | ||
| 391 | UNREACHABLE(); | ||
| 334 | case Tegra::Texture::TextureFormat::R32_G32_B32_A32: | 392 | case Tegra::Texture::TextureFormat::R32_G32_B32_A32: |
| 335 | switch (component_type) { | 393 | switch (component_type) { |
| 336 | case Tegra::Texture::ComponentType::FLOAT: | 394 | case Tegra::Texture::ComponentType::FLOAT: |
| @@ -342,15 +400,29 @@ struct SurfaceParams { | |||
| 342 | static_cast<u32>(component_type)); | 400 | static_cast<u32>(component_type)); |
| 343 | UNREACHABLE(); | 401 | UNREACHABLE(); |
| 344 | case Tegra::Texture::TextureFormat::R32_G32: | 402 | case Tegra::Texture::TextureFormat::R32_G32: |
| 345 | return PixelFormat::RG32F; | 403 | switch (component_type) { |
| 404 | case Tegra::Texture::ComponentType::FLOAT: | ||
| 405 | return PixelFormat::RG32F; | ||
| 406 | case Tegra::Texture::ComponentType::UINT: | ||
| 407 | return PixelFormat::RG32UI; | ||
| 408 | } | ||
| 409 | LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", | ||
| 410 | static_cast<u32>(component_type)); | ||
| 411 | UNREACHABLE(); | ||
| 346 | case Tegra::Texture::TextureFormat::R32_G32_B32: | 412 | case Tegra::Texture::TextureFormat::R32_G32_B32: |
| 347 | return PixelFormat::RGB32F; | 413 | switch (component_type) { |
| 414 | case Tegra::Texture::ComponentType::FLOAT: | ||
| 415 | return PixelFormat::RGB32F; | ||
| 416 | } | ||
| 417 | LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", | ||
| 418 | static_cast<u32>(component_type)); | ||
| 419 | UNREACHABLE(); | ||
| 348 | case Tegra::Texture::TextureFormat::R16: | 420 | case Tegra::Texture::TextureFormat::R16: |
| 349 | switch (component_type) { | 421 | switch (component_type) { |
| 350 | case Tegra::Texture::ComponentType::FLOAT: | 422 | case Tegra::Texture::ComponentType::FLOAT: |
| 351 | return PixelFormat::R16F; | 423 | return PixelFormat::R16F; |
| 352 | case Tegra::Texture::ComponentType::UNORM: | 424 | case Tegra::Texture::ComponentType::UNORM: |
| 353 | return PixelFormat::R16UNORM; | 425 | return PixelFormat::R16U; |
| 354 | case Tegra::Texture::ComponentType::SNORM: | 426 | case Tegra::Texture::ComponentType::SNORM: |
| 355 | return PixelFormat::R16S; | 427 | return PixelFormat::R16S; |
| 356 | case Tegra::Texture::ComponentType::UINT: | 428 | case Tegra::Texture::ComponentType::UINT: |
| @@ -362,9 +434,19 @@ struct SurfaceParams { | |||
| 362 | static_cast<u32>(component_type)); | 434 | static_cast<u32>(component_type)); |
| 363 | UNREACHABLE(); | 435 | UNREACHABLE(); |
| 364 | case Tegra::Texture::TextureFormat::R32: | 436 | case Tegra::Texture::TextureFormat::R32: |
| 365 | return PixelFormat::R32F; | 437 | switch (component_type) { |
| 438 | case Tegra::Texture::ComponentType::FLOAT: | ||
| 439 | return PixelFormat::R32F; | ||
| 440 | case Tegra::Texture::ComponentType::UINT: | ||
| 441 | return PixelFormat::R32UI; | ||
| 442 | } | ||
| 443 | LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", | ||
| 444 | static_cast<u32>(component_type)); | ||
| 445 | UNREACHABLE(); | ||
| 366 | case Tegra::Texture::TextureFormat::ZF32: | 446 | case Tegra::Texture::TextureFormat::ZF32: |
| 367 | return PixelFormat::Z32F; | 447 | return PixelFormat::Z32F; |
| 448 | case Tegra::Texture::TextureFormat::Z16: | ||
| 449 | return PixelFormat::Z16; | ||
| 368 | case Tegra::Texture::TextureFormat::Z24S8: | 450 | case Tegra::Texture::TextureFormat::Z24S8: |
| 369 | return PixelFormat::Z24S8; | 451 | return PixelFormat::Z24S8; |
| 370 | case Tegra::Texture::TextureFormat::DXT1: | 452 | case Tegra::Texture::TextureFormat::DXT1: |
| @@ -443,6 +525,7 @@ struct SurfaceParams { | |||
| 443 | case Tegra::RenderTargetFormat::R16_UNORM: | 525 | case Tegra::RenderTargetFormat::R16_UNORM: |
| 444 | case Tegra::RenderTargetFormat::B5G6R5_UNORM: | 526 | case Tegra::RenderTargetFormat::B5G6R5_UNORM: |
| 445 | case Tegra::RenderTargetFormat::RG8_UNORM: | 527 | case Tegra::RenderTargetFormat::RG8_UNORM: |
| 528 | case Tegra::RenderTargetFormat::RGBA16_UNORM: | ||
| 446 | return ComponentType::UNorm; | 529 | return ComponentType::UNorm; |
| 447 | case Tegra::RenderTargetFormat::RGBA8_SNORM: | 530 | case Tegra::RenderTargetFormat::RGBA8_SNORM: |
| 448 | case Tegra::RenderTargetFormat::RG16_SNORM: | 531 | case Tegra::RenderTargetFormat::RG16_SNORM: |
| @@ -462,6 +545,8 @@ struct SurfaceParams { | |||
| 462 | case Tegra::RenderTargetFormat::RG16_UINT: | 545 | case Tegra::RenderTargetFormat::RG16_UINT: |
| 463 | case Tegra::RenderTargetFormat::R8_UINT: | 546 | case Tegra::RenderTargetFormat::R8_UINT: |
| 464 | case Tegra::RenderTargetFormat::R16_UINT: | 547 | case Tegra::RenderTargetFormat::R16_UINT: |
| 548 | case Tegra::RenderTargetFormat::RG32_UINT: | ||
| 549 | case Tegra::RenderTargetFormat::R32_UINT: | ||
| 465 | return ComponentType::UInt; | 550 | return ComponentType::UInt; |
| 466 | case Tegra::RenderTargetFormat::RG16_SINT: | 551 | case Tegra::RenderTargetFormat::RG16_SINT: |
| 467 | case Tegra::RenderTargetFormat::R16_SINT: | 552 | case Tegra::RenderTargetFormat::R16_SINT: |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 6834d7085..e0dfdbb9f 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -367,31 +367,32 @@ public: | |||
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | /// Generates code representing a uniform (C buffer) register, interpreted as the input type. | 369 | /// Generates code representing a uniform (C buffer) register, interpreted as the input type. |
| 370 | std::string GetUniform(u64 index, u64 offset, GLSLRegister::Type type) { | 370 | std::string GetUniform(u64 index, u64 offset, GLSLRegister::Type type, |
| 371 | Register::Size size = Register::Size::Word) { | ||
| 371 | declr_const_buffers[index].MarkAsUsed(index, offset, stage); | 372 | declr_const_buffers[index].MarkAsUsed(index, offset, stage); |
| 372 | std::string value = 'c' + std::to_string(index) + '[' + std::to_string(offset / 4) + "][" + | 373 | std::string value = 'c' + std::to_string(index) + '[' + std::to_string(offset / 4) + "][" + |
| 373 | std::to_string(offset % 4) + ']'; | 374 | std::to_string(offset % 4) + ']'; |
| 374 | 375 | ||
| 375 | if (type == GLSLRegister::Type::Float) { | 376 | if (type == GLSLRegister::Type::Float) { |
| 376 | return value; | 377 | // Do nothing, default |
| 377 | } else if (type == GLSLRegister::Type::Integer) { | 378 | } else if (type == GLSLRegister::Type::Integer) { |
| 378 | return "floatBitsToInt(" + value + ')'; | 379 | value = "floatBitsToInt(" + value + ')'; |
| 379 | } else if (type == GLSLRegister::Type::UnsignedInteger) { | 380 | } else if (type == GLSLRegister::Type::UnsignedInteger) { |
| 380 | return "floatBitsToUint(" + value + ')'; | 381 | value = "floatBitsToUint(" + value + ')'; |
| 381 | } else { | 382 | } else { |
| 382 | UNREACHABLE(); | 383 | UNREACHABLE(); |
| 383 | } | 384 | } |
| 385 | |||
| 386 | return ConvertIntegerSize(value, size); | ||
| 384 | } | 387 | } |
| 385 | 388 | ||
| 386 | std::string GetUniformIndirect(u64 index, s64 offset, const Register& index_reg, | 389 | std::string GetUniformIndirect(u64 cbuf_index, s64 offset, const std::string& index_str, |
| 387 | GLSLRegister::Type type) { | 390 | GLSLRegister::Type type) { |
| 388 | declr_const_buffers[index].MarkAsUsedIndirect(index, stage); | 391 | declr_const_buffers[cbuf_index].MarkAsUsedIndirect(cbuf_index, stage); |
| 389 | |||
| 390 | std::string final_offset = "((floatBitsToInt(" + GetRegister(index_reg, 0) + ") + " + | ||
| 391 | std::to_string(offset) + ") / 4)"; | ||
| 392 | 392 | ||
| 393 | std::string value = | 393 | std::string final_offset = fmt::format("({} + {})", index_str, offset / 4); |
| 394 | 'c' + std::to_string(index) + '[' + final_offset + " / 4][" + final_offset + " % 4]"; | 394 | std::string value = 'c' + std::to_string(cbuf_index) + '[' + final_offset + " / 4][" + |
| 395 | final_offset + " % 4]"; | ||
| 395 | 396 | ||
| 396 | if (type == GLSLRegister::Type::Float) { | 397 | if (type == GLSLRegister::Type::Float) { |
| 397 | return value; | 398 | return value; |
| @@ -1249,20 +1250,41 @@ private: | |||
| 1249 | op_a = "abs(" + op_a + ')'; | 1250 | op_a = "abs(" + op_a + ')'; |
| 1250 | } | 1251 | } |
| 1251 | 1252 | ||
| 1253 | if (instr.conversion.negate_a) { | ||
| 1254 | op_a = "-(" + op_a + ')'; | ||
| 1255 | } | ||
| 1256 | |||
| 1252 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, | 1257 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, |
| 1253 | 1, instr.alu.saturate_d, 0, instr.conversion.dest_size); | 1258 | 1, instr.alu.saturate_d, 0, instr.conversion.dest_size); |
| 1254 | break; | 1259 | break; |
| 1255 | } | 1260 | } |
| 1256 | case OpCode::Id::I2F_R: { | 1261 | case OpCode::Id::I2F_R: |
| 1262 | case OpCode::Id::I2F_C: { | ||
| 1257 | ASSERT_MSG(instr.conversion.dest_size == Register::Size::Word, "Unimplemented"); | 1263 | ASSERT_MSG(instr.conversion.dest_size == Register::Size::Word, "Unimplemented"); |
| 1258 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | 1264 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); |
| 1259 | std::string op_a = regs.GetRegisterAsInteger( | 1265 | |
| 1260 | instr.gpr20, 0, instr.conversion.is_input_signed, instr.conversion.src_size); | 1266 | std::string op_a{}; |
| 1267 | |||
| 1268 | if (instr.is_b_gpr) { | ||
| 1269 | op_a = | ||
| 1270 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed, | ||
| 1271 | instr.conversion.src_size); | ||
| 1272 | } else { | ||
| 1273 | op_a = regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset, | ||
| 1274 | instr.conversion.is_input_signed | ||
| 1275 | ? GLSLRegister::Type::Integer | ||
| 1276 | : GLSLRegister::Type::UnsignedInteger, | ||
| 1277 | instr.conversion.src_size); | ||
| 1278 | } | ||
| 1261 | 1279 | ||
| 1262 | if (instr.conversion.abs_a) { | 1280 | if (instr.conversion.abs_a) { |
| 1263 | op_a = "abs(" + op_a + ')'; | 1281 | op_a = "abs(" + op_a + ')'; |
| 1264 | } | 1282 | } |
| 1265 | 1283 | ||
| 1284 | if (instr.conversion.negate_a) { | ||
| 1285 | op_a = "-(" + op_a + ')'; | ||
| 1286 | } | ||
| 1287 | |||
| 1266 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); | 1288 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); |
| 1267 | break; | 1289 | break; |
| 1268 | } | 1290 | } |
| @@ -1271,6 +1293,14 @@ private: | |||
| 1271 | ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented"); | 1293 | ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented"); |
| 1272 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | 1294 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); |
| 1273 | 1295 | ||
| 1296 | if (instr.conversion.abs_a) { | ||
| 1297 | op_a = "abs(" + op_a + ')'; | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | if (instr.conversion.negate_a) { | ||
| 1301 | op_a = "-(" + op_a + ')'; | ||
| 1302 | } | ||
| 1303 | |||
| 1274 | switch (instr.conversion.f2f.rounding) { | 1304 | switch (instr.conversion.f2f.rounding) { |
| 1275 | case Tegra::Shader::F2fRoundingOp::None: | 1305 | case Tegra::Shader::F2fRoundingOp::None: |
| 1276 | break; | 1306 | break; |
| @@ -1293,21 +1323,29 @@ private: | |||
| 1293 | break; | 1323 | break; |
| 1294 | } | 1324 | } |
| 1295 | 1325 | ||
| 1296 | if (instr.conversion.abs_a) { | ||
| 1297 | op_a = "abs(" + op_a + ')'; | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1, instr.alu.saturate_d); | 1326 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1, instr.alu.saturate_d); |
| 1301 | break; | 1327 | break; |
| 1302 | } | 1328 | } |
| 1303 | case OpCode::Id::F2I_R: { | 1329 | case OpCode::Id::F2I_R: |
| 1330 | case OpCode::Id::F2I_C: { | ||
| 1304 | ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented"); | 1331 | ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented"); |
| 1305 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | 1332 | std::string op_a{}; |
| 1333 | |||
| 1334 | if (instr.is_b_gpr) { | ||
| 1335 | op_a = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1336 | } else { | ||
| 1337 | op_a = regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset, | ||
| 1338 | GLSLRegister::Type::Float); | ||
| 1339 | } | ||
| 1306 | 1340 | ||
| 1307 | if (instr.conversion.abs_a) { | 1341 | if (instr.conversion.abs_a) { |
| 1308 | op_a = "abs(" + op_a + ')'; | 1342 | op_a = "abs(" + op_a + ')'; |
| 1309 | } | 1343 | } |
| 1310 | 1344 | ||
| 1345 | if (instr.conversion.negate_a) { | ||
| 1346 | op_a = "-(" + op_a + ')'; | ||
| 1347 | } | ||
| 1348 | |||
| 1311 | switch (instr.conversion.f2i.rounding) { | 1349 | switch (instr.conversion.f2i.rounding) { |
| 1312 | case Tegra::Shader::F2iRoundingOp::None: | 1350 | case Tegra::Shader::F2iRoundingOp::None: |
| 1313 | break; | 1351 | break; |
| @@ -1355,11 +1393,16 @@ private: | |||
| 1355 | case OpCode::Id::LD_C: { | 1393 | case OpCode::Id::LD_C: { |
| 1356 | ASSERT_MSG(instr.ld_c.unknown == 0, "Unimplemented"); | 1394 | ASSERT_MSG(instr.ld_c.unknown == 0, "Unimplemented"); |
| 1357 | 1395 | ||
| 1396 | // Add an extra scope and declare the index register inside to prevent | ||
| 1397 | // overwriting it in case it is used as an output of the LD instruction. | ||
| 1398 | shader.AddLine("{"); | ||
| 1399 | ++shader.scope; | ||
| 1400 | |||
| 1401 | shader.AddLine("uint index = (" + regs.GetRegisterAsInteger(instr.gpr8, 0, false) + | ||
| 1402 | " / 4) & (MAX_CONSTBUFFER_ELEMENTS - 1);"); | ||
| 1403 | |||
| 1358 | std::string op_a = | 1404 | std::string op_a = |
| 1359 | regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 0, instr.gpr8, | 1405 | regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 0, "index", |
| 1360 | GLSLRegister::Type::Float); | ||
| 1361 | std::string op_b = | ||
| 1362 | regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 4, instr.gpr8, | ||
| 1363 | GLSLRegister::Type::Float); | 1406 | GLSLRegister::Type::Float); |
| 1364 | 1407 | ||
| 1365 | switch (instr.ld_c.type.Value()) { | 1408 | switch (instr.ld_c.type.Value()) { |
| @@ -1367,16 +1410,22 @@ private: | |||
| 1367 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); | 1410 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); |
| 1368 | break; | 1411 | break; |
| 1369 | 1412 | ||
| 1370 | case Tegra::Shader::UniformType::Double: | 1413 | case Tegra::Shader::UniformType::Double: { |
| 1414 | std::string op_b = | ||
| 1415 | regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 4, | ||
| 1416 | "index", GLSLRegister::Type::Float); | ||
| 1371 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); | 1417 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); |
| 1372 | regs.SetRegisterToFloat(instr.gpr0.Value() + 1, 0, op_b, 1, 1); | 1418 | regs.SetRegisterToFloat(instr.gpr0.Value() + 1, 0, op_b, 1, 1); |
| 1373 | break; | 1419 | break; |
| 1374 | 1420 | } | |
| 1375 | default: | 1421 | default: |
| 1376 | LOG_CRITICAL(HW_GPU, "Unhandled type: {}", | 1422 | LOG_CRITICAL(HW_GPU, "Unhandled type: {}", |
| 1377 | static_cast<unsigned>(instr.ld_c.type.Value())); | 1423 | static_cast<unsigned>(instr.ld_c.type.Value())); |
| 1378 | UNREACHABLE(); | 1424 | UNREACHABLE(); |
| 1379 | } | 1425 | } |
| 1426 | |||
| 1427 | --shader.scope; | ||
| 1428 | shader.AddLine("}"); | ||
| 1380 | break; | 1429 | break; |
| 1381 | } | 1430 | } |
| 1382 | case OpCode::Id::ST_A: { | 1431 | case OpCode::Id::ST_A: { |
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index 679e5ceb2..8f719fdd8 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h | |||
| @@ -24,15 +24,25 @@ using Maxwell = Tegra::Engines::Maxwell3D::Regs; | |||
| 24 | 24 | ||
| 25 | inline GLenum VertexType(Maxwell::VertexAttribute attrib) { | 25 | inline GLenum VertexType(Maxwell::VertexAttribute attrib) { |
| 26 | switch (attrib.type) { | 26 | switch (attrib.type) { |
| 27 | case Maxwell::VertexAttribute::Type::UnsignedInt: | ||
| 27 | case Maxwell::VertexAttribute::Type::UnsignedNorm: { | 28 | case Maxwell::VertexAttribute::Type::UnsignedNorm: { |
| 28 | 29 | ||
| 29 | switch (attrib.size) { | 30 | switch (attrib.size) { |
| 31 | case Maxwell::VertexAttribute::Size::Size_8: | ||
| 30 | case Maxwell::VertexAttribute::Size::Size_8_8: | 32 | case Maxwell::VertexAttribute::Size::Size_8_8: |
| 33 | case Maxwell::VertexAttribute::Size::Size_8_8_8: | ||
| 31 | case Maxwell::VertexAttribute::Size::Size_8_8_8_8: | 34 | case Maxwell::VertexAttribute::Size::Size_8_8_8_8: |
| 32 | return GL_UNSIGNED_BYTE; | 35 | return GL_UNSIGNED_BYTE; |
| 36 | case Maxwell::VertexAttribute::Size::Size_16: | ||
| 33 | case Maxwell::VertexAttribute::Size::Size_16_16: | 37 | case Maxwell::VertexAttribute::Size::Size_16_16: |
| 38 | case Maxwell::VertexAttribute::Size::Size_16_16_16: | ||
| 34 | case Maxwell::VertexAttribute::Size::Size_16_16_16_16: | 39 | case Maxwell::VertexAttribute::Size::Size_16_16_16_16: |
| 35 | return GL_UNSIGNED_SHORT; | 40 | return GL_UNSIGNED_SHORT; |
| 41 | case Maxwell::VertexAttribute::Size::Size_32: | ||
| 42 | case Maxwell::VertexAttribute::Size::Size_32_32: | ||
| 43 | case Maxwell::VertexAttribute::Size::Size_32_32_32: | ||
| 44 | case Maxwell::VertexAttribute::Size::Size_32_32_32_32: | ||
| 45 | return GL_UNSIGNED_INT; | ||
| 36 | case Maxwell::VertexAttribute::Size::Size_10_10_10_2: | 46 | case Maxwell::VertexAttribute::Size::Size_10_10_10_2: |
| 37 | return GL_UNSIGNED_INT_2_10_10_10_REV; | 47 | return GL_UNSIGNED_INT_2_10_10_10_REV; |
| 38 | } | 48 | } |
| @@ -42,16 +52,25 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) { | |||
| 42 | return {}; | 52 | return {}; |
| 43 | } | 53 | } |
| 44 | 54 | ||
| 55 | case Maxwell::VertexAttribute::Type::SignedInt: | ||
| 45 | case Maxwell::VertexAttribute::Type::SignedNorm: { | 56 | case Maxwell::VertexAttribute::Type::SignedNorm: { |
| 46 | 57 | ||
| 47 | switch (attrib.size) { | 58 | switch (attrib.size) { |
| 48 | case Maxwell::VertexAttribute::Size::Size_32_32_32: | 59 | case Maxwell::VertexAttribute::Size::Size_8: |
| 49 | return GL_INT; | ||
| 50 | case Maxwell::VertexAttribute::Size::Size_8_8: | 60 | case Maxwell::VertexAttribute::Size::Size_8_8: |
| 61 | case Maxwell::VertexAttribute::Size::Size_8_8_8: | ||
| 51 | case Maxwell::VertexAttribute::Size::Size_8_8_8_8: | 62 | case Maxwell::VertexAttribute::Size::Size_8_8_8_8: |
| 52 | return GL_BYTE; | 63 | return GL_BYTE; |
| 64 | case Maxwell::VertexAttribute::Size::Size_16: | ||
| 53 | case Maxwell::VertexAttribute::Size::Size_16_16: | 65 | case Maxwell::VertexAttribute::Size::Size_16_16: |
| 66 | case Maxwell::VertexAttribute::Size::Size_16_16_16: | ||
| 67 | case Maxwell::VertexAttribute::Size::Size_16_16_16_16: | ||
| 54 | return GL_SHORT; | 68 | return GL_SHORT; |
| 69 | case Maxwell::VertexAttribute::Size::Size_32: | ||
| 70 | case Maxwell::VertexAttribute::Size::Size_32_32: | ||
| 71 | case Maxwell::VertexAttribute::Size::Size_32_32_32: | ||
| 72 | case Maxwell::VertexAttribute::Size::Size_32_32_32_32: | ||
| 73 | return GL_INT; | ||
| 55 | case Maxwell::VertexAttribute::Size::Size_10_10_10_2: | 74 | case Maxwell::VertexAttribute::Size::Size_10_10_10_2: |
| 56 | return GL_INT_2_10_10_10_REV; | 75 | return GL_INT_2_10_10_10_REV; |
| 57 | } | 76 | } |
| @@ -61,9 +80,6 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) { | |||
| 61 | return {}; | 80 | return {}; |
| 62 | } | 81 | } |
| 63 | 82 | ||
| 64 | case Maxwell::VertexAttribute::Type::UnsignedInt: | ||
| 65 | return GL_UNSIGNED_INT; | ||
| 66 | |||
| 67 | case Maxwell::VertexAttribute::Type::Float: | 83 | case Maxwell::VertexAttribute::Type::Float: |
| 68 | return GL_FLOAT; | 84 | return GL_FLOAT; |
| 69 | } | 85 | } |