early-access version 1850
This commit is contained in:
parent
0d01d9440c
commit
4591272f77
17 changed files with 123 additions and 111 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 1848.
|
This is the source code for early-access 1850.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -45,14 +45,23 @@ if (MSVC)
|
||||||
/Zc:inline
|
/Zc:inline
|
||||||
/Zc:throwingNew
|
/Zc:throwingNew
|
||||||
|
|
||||||
|
# External headers diagnostics
|
||||||
|
/experimental:external # Enables the external headers options. This option isn't required in Visual Studio 2019 version 16.10 and later
|
||||||
|
/external:anglebrackets # Treats all headers included by #include <header>, where the header file is enclosed in angle brackets (< >), as external headers
|
||||||
|
/external:W0 # Sets the default warning level to 0 for external headers, effectively turning off warnings for external headers
|
||||||
|
|
||||||
# Warnings
|
# Warnings
|
||||||
/W3
|
/W3
|
||||||
/we4062 # enumerator 'identifier' in a switch of enum 'enumeration' is not handled
|
/we4018 # 'expression': signed/unsigned mismatch
|
||||||
|
/we4062 # Enumerator 'identifier' in a switch of enum 'enumeration' is not handled
|
||||||
/we4101 # 'identifier': unreferenced local variable
|
/we4101 # 'identifier': unreferenced local variable
|
||||||
/we4189 # 'identifier': local variable is initialized but not referenced
|
/we4189 # 'identifier': local variable is initialized but not referenced
|
||||||
/we4265 # 'class': class has virtual functions, but destructor is not virtual
|
/we4265 # 'class': class has virtual functions, but destructor is not virtual
|
||||||
/we4388 # signed/unsigned mismatch
|
/we4267 # 'var': conversion from 'size_t' to 'type', possible loss of data
|
||||||
/we4547 # 'operator' : operator before comma has no effect; expected operator with side-effect
|
/we4305 # 'context': truncation from 'type1' to 'type2'
|
||||||
|
/we4388 # 'expression': signed/unsigned mismatch
|
||||||
|
/we4389 # 'operator': signed/unsigned mismatch
|
||||||
|
/we4547 # 'operator': operator before comma has no effect; expected operator with side-effect
|
||||||
/we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'?
|
/we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'?
|
||||||
/we4555 # Expression has no effect; expected expression with side-effect
|
/we4555 # Expression has no effect; expected expression with side-effect
|
||||||
/we4715 # 'function': not all control paths return a value
|
/we4715 # 'function': not all control paths return a value
|
||||||
|
|
|
@ -400,7 +400,10 @@ void CommandGenerator::GenerateDataSourceCommand(ServerVoiceInfo& voice_info, Vo
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (in_params.sample_format) {
|
switch (in_params.sample_format) {
|
||||||
|
case SampleFormat::Pcm8:
|
||||||
case SampleFormat::Pcm16:
|
case SampleFormat::Pcm16:
|
||||||
|
case SampleFormat::Pcm32:
|
||||||
|
case SampleFormat::PcmFloat:
|
||||||
DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(channel), dsp_state, channel,
|
DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(channel), dsp_state, channel,
|
||||||
worker_params.sample_rate, worker_params.sample_count,
|
worker_params.sample_rate, worker_params.sample_count,
|
||||||
in_params.node_id);
|
in_params.node_id);
|
||||||
|
@ -1003,7 +1006,8 @@ void CommandGenerator::GenerateFinalMixCommand() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
|
template <typename T>
|
||||||
|
s32 CommandGenerator::DecodePcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
|
||||||
s32 sample_start_offset, s32 sample_end_offset, s32 sample_count,
|
s32 sample_start_offset, s32 sample_end_offset, s32 sample_count,
|
||||||
s32 channel, std::size_t mix_offset) {
|
s32 channel, std::size_t mix_offset) {
|
||||||
const auto& in_params = voice_info.GetInParams();
|
const auto& in_params = voice_info.GetInParams();
|
||||||
|
@ -1019,21 +1023,20 @@ s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_s
|
||||||
}
|
}
|
||||||
const auto samples_remaining = (sample_end_offset - sample_start_offset) - dsp_state.offset;
|
const auto samples_remaining = (sample_end_offset - sample_start_offset) - dsp_state.offset;
|
||||||
const auto start_offset =
|
const auto start_offset =
|
||||||
((dsp_state.offset + sample_start_offset) * in_params.channel_count) * sizeof(s16);
|
((dsp_state.offset + sample_start_offset) * in_params.channel_count) * sizeof(T);
|
||||||
const auto buffer_pos = wave_buffer.buffer_address + start_offset;
|
const auto buffer_pos = wave_buffer.buffer_address + start_offset;
|
||||||
const auto samples_processed = std::min(sample_count, samples_remaining);
|
const auto samples_processed = std::min(sample_count, samples_remaining);
|
||||||
|
|
||||||
if (in_params.channel_count == 1) {
|
const auto channel_count = in_params.channel_count;
|
||||||
std::vector<s16> buffer(samples_processed);
|
std::vector<T> buffer(samples_processed * channel_count);
|
||||||
memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(s16));
|
memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(T));
|
||||||
for (std::size_t i = 0; i < buffer.size(); i++) {
|
|
||||||
sample_buffer[mix_offset + i] = buffer[i];
|
if constexpr (std::is_floating_point_v<T>) {
|
||||||
|
for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) {
|
||||||
|
sample_buffer[mix_offset + i] = static_cast<s32>(buffer[i * channel_count + channel] *
|
||||||
|
std::numeric_limits<s16>::max());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const auto channel_count = in_params.channel_count;
|
|
||||||
std::vector<s16> buffer(samples_processed * channel_count);
|
|
||||||
memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(s16));
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) {
|
for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) {
|
||||||
sample_buffer[mix_offset + i] = buffer[i * channel_count + channel];
|
sample_buffer[mix_offset + i] = buffer[i * channel_count + channel];
|
||||||
}
|
}
|
||||||
|
@ -1249,9 +1252,24 @@ void CommandGenerator::DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, s32* o
|
||||||
|
|
||||||
s32 samples_decoded{0};
|
s32 samples_decoded{0};
|
||||||
switch (in_params.sample_format) {
|
switch (in_params.sample_format) {
|
||||||
|
case SampleFormat::Pcm8:
|
||||||
|
samples_decoded =
|
||||||
|
DecodePcm<s8>(voice_info, dsp_state, samples_offset_start, samples_offset_end,
|
||||||
|
samples_to_read - samples_read, channel, temp_mix_offset);
|
||||||
|
break;
|
||||||
case SampleFormat::Pcm16:
|
case SampleFormat::Pcm16:
|
||||||
samples_decoded =
|
samples_decoded =
|
||||||
DecodePcm16(voice_info, dsp_state, samples_offset_start, samples_offset_end,
|
DecodePcm<s16>(voice_info, dsp_state, samples_offset_start, samples_offset_end,
|
||||||
|
samples_to_read - samples_read, channel, temp_mix_offset);
|
||||||
|
break;
|
||||||
|
case SampleFormat::Pcm32:
|
||||||
|
samples_decoded =
|
||||||
|
DecodePcm<s32>(voice_info, dsp_state, samples_offset_start, samples_offset_end,
|
||||||
|
samples_to_read - samples_read, channel, temp_mix_offset);
|
||||||
|
break;
|
||||||
|
case SampleFormat::PcmFloat:
|
||||||
|
samples_decoded =
|
||||||
|
DecodePcm<f32>(voice_info, dsp_state, samples_offset_start, samples_offset_end,
|
||||||
samples_to_read - samples_read, channel, temp_mix_offset);
|
samples_to_read - samples_read, channel, temp_mix_offset);
|
||||||
break;
|
break;
|
||||||
case SampleFormat::Adpcm:
|
case SampleFormat::Adpcm:
|
||||||
|
|
|
@ -86,7 +86,8 @@ private:
|
||||||
std::vector<u8>& work_buffer);
|
std::vector<u8>& work_buffer);
|
||||||
void UpdateI3dl2Reverb(I3dl2ReverbParams& info, I3dl2ReverbState& state, bool should_clear);
|
void UpdateI3dl2Reverb(I3dl2ReverbParams& info, I3dl2ReverbState& state, bool should_clear);
|
||||||
// DSP Code
|
// DSP Code
|
||||||
s32 DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 sample_start_offset,
|
template <typename T>
|
||||||
|
s32 DecodePcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 sample_start_offset,
|
||||||
s32 sample_end_offset, s32 sample_count, s32 channel, std::size_t mix_offset);
|
s32 sample_end_offset, s32 sample_count, s32 channel, std::size_t mix_offset);
|
||||||
s32 DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 sample_start_offset,
|
s32 DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 sample_start_offset,
|
||||||
s32 sample_end_offset, s32 sample_count, s32 channel, std::size_t mix_offset);
|
s32 sample_end_offset, s32 sample_count, s32 channel, std::size_t mix_offset);
|
||||||
|
|
|
@ -656,17 +656,14 @@ endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(core PRIVATE
|
target_compile_options(core PRIVATE
|
||||||
/we4018 # 'expression' : signed/unsigned mismatch
|
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||||
/we4244 # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point)
|
/we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
|
||||||
/we4245 # 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
|
/we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
|
||||||
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||||
/we4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data
|
|
||||||
/we4305 # 'context' : truncation from 'type1' to 'type2'
|
|
||||||
/we4456 # Declaration of 'identifier' hides previous local declaration
|
/we4456 # Declaration of 'identifier' hides previous local declaration
|
||||||
/we4457 # Declaration of 'identifier' hides function parameter
|
/we4457 # Declaration of 'identifier' hides function parameter
|
||||||
/we4458 # Declaration of 'identifier' hides class member
|
/we4458 # Declaration of 'identifier' hides class member
|
||||||
/we4459 # Declaration of 'identifier' hides global declaration
|
/we4459 # Declaration of 'identifier' hides global declaration
|
||||||
/we4715 # 'function' : not all control paths return a value
|
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
target_compile_options(core PRIVATE
|
target_compile_options(core PRIVATE
|
||||||
|
|
|
@ -34,18 +34,10 @@ if (MSVC)
|
||||||
/W4
|
/W4
|
||||||
/WX
|
/WX
|
||||||
|
|
||||||
# 'expression' : signed/unsigned mismatch
|
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||||
/we4018
|
/we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
|
||||||
# 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point)
|
/we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
|
||||||
/we4244
|
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||||
# 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
|
|
||||||
/we4245
|
|
||||||
# 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
|
||||||
/we4254
|
|
||||||
# 'var' : conversion from 'size_t' to 'type', possible loss of data
|
|
||||||
/we4267
|
|
||||||
# 'context' : truncation from 'type1' to 'type2'
|
|
||||||
/we4305
|
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
target_compile_options(input_common PRIVATE
|
target_compile_options(input_common PRIVATE
|
||||||
|
|
|
@ -5,14 +5,7 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union
|
|
||||||
#endif
|
|
||||||
#include <libusb.h>
|
#include <libusb.h>
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/param_package.h"
|
#include "common/param_package.h"
|
||||||
|
|
|
@ -8,14 +8,7 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable : 4701)
|
|
||||||
#endif
|
|
||||||
#include <boost/crc.hpp>
|
#include <boost/crc.hpp>
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
|
|
|
@ -292,13 +292,12 @@ endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(video_core PRIVATE
|
target_compile_options(video_core PRIVATE
|
||||||
/we4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data
|
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||||
/we4244 # 'var' : conversion from integer to 'type', possible loss of data
|
/we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
|
||||||
/we4456 # Declaration of 'identifier' hides previous local declaration
|
/we4456 # Declaration of 'identifier' hides previous local declaration
|
||||||
/we4457 # Declaration of 'identifier' hides function parameter
|
/we4457 # Declaration of 'identifier' hides function parameter
|
||||||
/we4458 # Declaration of 'identifier' hides class member
|
/we4458 # Declaration of 'identifier' hides class member
|
||||||
/we4459 # Declaration of 'identifier' hides global declaration
|
/we4459 # Declaration of 'identifier' hides global declaration
|
||||||
/we4715 # 'function' : not all control paths return a value
|
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
target_compile_options(video_core PRIVATE
|
target_compile_options(video_core PRIVATE
|
||||||
|
|
|
@ -14,18 +14,10 @@ extern "C" {
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wconversion"
|
#pragma GCC diagnostic ignored "-Wconversion"
|
||||||
#endif
|
#endif
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable : 4242) // conversion from 'type' to 'type', possible loss of data
|
|
||||||
#pragma warning(disable : 4244) // conversion from 'type' to 'type', possible loss of data
|
|
||||||
#endif
|
|
||||||
#include <libavcodec/avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
|
|
|
@ -9,17 +9,10 @@ extern "C" {
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wconversion"
|
#pragma GCC diagnostic ignored "-Wconversion"
|
||||||
#endif
|
#endif
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable : 4244) // conversion from 'type' to 'type', possible loss of data
|
|
||||||
#pragma warning(push)
|
|
||||||
#endif
|
|
||||||
#include <libswscale/swscale.h>
|
#include <libswscale/swscale.h>
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
|
|
@ -7,10 +7,6 @@
|
||||||
#include "video_core/engines/fermi_2d.h"
|
#include "video_core/engines/fermi_2d.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
#include "video_core/surface.h"
|
|
||||||
|
|
||||||
using VideoCore::Surface::BytesPerBlock;
|
|
||||||
using VideoCore::Surface::PixelFormatFromRenderTargetFormat;
|
|
||||||
|
|
||||||
namespace Tegra::Engines {
|
namespace Tegra::Engines {
|
||||||
|
|
||||||
|
@ -53,7 +49,7 @@ void Fermi2D::Blit() {
|
||||||
UNIMPLEMENTED_IF_MSG(regs.clip_enable != 0, "Clipped blit enabled");
|
UNIMPLEMENTED_IF_MSG(regs.clip_enable != 0, "Clipped blit enabled");
|
||||||
|
|
||||||
const auto& args = regs.pixels_from_memory;
|
const auto& args = regs.pixels_from_memory;
|
||||||
Config config{
|
const Config config{
|
||||||
.operation = regs.operation,
|
.operation = regs.operation,
|
||||||
.filter = args.sample_mode.filter,
|
.filter = args.sample_mode.filter,
|
||||||
.dst_x0 = args.dst_x0,
|
.dst_x0 = args.dst_x0,
|
||||||
|
@ -65,20 +61,7 @@ void Fermi2D::Blit() {
|
||||||
.src_x1 = static_cast<s32>((args.du_dx * args.dst_width + args.src_x0) >> 32),
|
.src_x1 = static_cast<s32>((args.du_dx * args.dst_width + args.src_x0) >> 32),
|
||||||
.src_y1 = static_cast<s32>((args.dv_dy * args.dst_height + args.src_y0) >> 32),
|
.src_y1 = static_cast<s32>((args.dv_dy * args.dst_height + args.src_y0) >> 32),
|
||||||
};
|
};
|
||||||
Surface src = regs.src;
|
if (!rasterizer->AccelerateSurfaceCopy(regs.src, regs.dst, config)) {
|
||||||
const auto bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(src.format));
|
|
||||||
const auto need_align_to_pitch =
|
|
||||||
src.linear == Tegra::Engines::Fermi2D::MemoryLayout::Pitch && src.width == config.src_x1 &&
|
|
||||||
config.src_x1 > static_cast<s32>(src.pitch / bytes_per_pixel) && config.src_x0 > 0;
|
|
||||||
if (need_align_to_pitch) {
|
|
||||||
auto address = src.Address() + config.src_x0 * bytes_per_pixel;
|
|
||||||
src.addr_upper = static_cast<u32>(address >> 32);
|
|
||||||
src.addr_lower = static_cast<u32>(address);
|
|
||||||
src.width -= config.src_x0;
|
|
||||||
config.src_x1 -= config.src_x0;
|
|
||||||
config.src_x0 = 0;
|
|
||||||
}
|
|
||||||
if (!rasterizer->AccelerateSurfaceCopy(src, regs.dst, config)) {
|
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -327,7 +327,8 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4
|
||||||
if (format_info.is_compressed) {
|
if (format_info.is_compressed) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (std::ranges::find(ACCELERATED_FORMATS, internal_format) == ACCELERATED_FORMATS.end()) {
|
if (std::ranges::find(ACCELERATED_FORMATS, static_cast<int>(internal_format)) ==
|
||||||
|
ACCELERATED_FORMATS.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (format_info.compatibility_by_size) {
|
if (format_info.compatibility_by_size) {
|
||||||
|
|
|
@ -85,7 +85,7 @@ std::optional<SubresourceBase> ImageBase::TryFindBase(GPUVAddr other_addr) const
|
||||||
if (info.type != ImageType::e3D) {
|
if (info.type != ImageType::e3D) {
|
||||||
const auto [layer, mip_offset] = LayerMipOffset(diff, info.layer_stride);
|
const auto [layer, mip_offset] = LayerMipOffset(diff, info.layer_stride);
|
||||||
const auto end = mip_level_offsets.begin() + info.resources.levels;
|
const auto end = mip_level_offsets.begin() + info.resources.levels;
|
||||||
const auto it = std::find(mip_level_offsets.begin(), end, mip_offset);
|
const auto it = std::find(mip_level_offsets.begin(), end, static_cast<u32>(mip_offset));
|
||||||
if (layer > info.resources.layers || it == end) {
|
if (layer > info.resources.layers || it == end) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,7 +159,9 @@ public:
|
||||||
/// Blit an image with the given parameters
|
/// Blit an image with the given parameters
|
||||||
void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
|
void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
|
||||||
const Tegra::Engines::Fermi2D::Surface& src,
|
const Tegra::Engines::Fermi2D::Surface& src,
|
||||||
const Tegra::Engines::Fermi2D::Config& copy);
|
const Tegra::Engines::Fermi2D::Config& copy,
|
||||||
|
std::optional<Region2D> src_region_override = {},
|
||||||
|
std::optional<Region2D> dst_region_override = {});
|
||||||
|
|
||||||
/// Invalidate the contents of the color buffer index
|
/// Invalidate the contents of the color buffer index
|
||||||
/// These contents become unspecified, the cache can assume aggressive optimizations.
|
/// These contents become unspecified, the cache can assume aggressive optimizations.
|
||||||
|
@ -758,7 +760,9 @@ void TextureCache<P>::UnmapGPUMemory(GPUVAddr gpu_addr, size_t size) {
|
||||||
template <class P>
|
template <class P>
|
||||||
void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
|
void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
|
||||||
const Tegra::Engines::Fermi2D::Surface& src,
|
const Tegra::Engines::Fermi2D::Surface& src,
|
||||||
const Tegra::Engines::Fermi2D::Config& copy) {
|
const Tegra::Engines::Fermi2D::Config& copy,
|
||||||
|
std::optional<Region2D> src_override,
|
||||||
|
std::optional<Region2D> dst_override) {
|
||||||
const BlitImages images = GetBlitImages(dst, src);
|
const BlitImages images = GetBlitImages(dst, src);
|
||||||
const ImageId dst_id = images.dst_id;
|
const ImageId dst_id = images.dst_id;
|
||||||
const ImageId src_id = images.src_id;
|
const ImageId src_id = images.src_id;
|
||||||
|
@ -769,25 +773,47 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
|
||||||
const ImageBase& src_image = slot_images[src_id];
|
const ImageBase& src_image = slot_images[src_id];
|
||||||
|
|
||||||
// TODO: Deduplicate
|
// TODO: Deduplicate
|
||||||
const std::optional src_base = src_image.TryFindBase(src.Address());
|
|
||||||
const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}};
|
|
||||||
const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range);
|
|
||||||
const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info);
|
|
||||||
const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples);
|
|
||||||
const Region2D src_region{
|
|
||||||
Offset2D{.x = copy.src_x0 >> src_samples_x, .y = copy.src_y0 >> src_samples_y},
|
|
||||||
Offset2D{.x = copy.src_x1 >> src_samples_x, .y = copy.src_y1 >> src_samples_y},
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::optional dst_base = dst_image.TryFindBase(dst.Address());
|
const std::optional dst_base = dst_image.TryFindBase(dst.Address());
|
||||||
const SubresourceRange dst_range{.base = dst_base.value(), .extent = {1, 1}};
|
const SubresourceRange dst_range{.base = dst_base.value(), .extent = {1, 1}};
|
||||||
const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range);
|
const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range);
|
||||||
const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info);
|
const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info);
|
||||||
const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples);
|
const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples);
|
||||||
const Region2D dst_region{
|
|
||||||
Offset2D{.x = copy.dst_x0 >> dst_samples_x, .y = copy.dst_y0 >> dst_samples_y},
|
// out of bounds texture blit checking
|
||||||
Offset2D{.x = copy.dst_x1 >> dst_samples_x, .y = copy.dst_y1 >> dst_samples_y},
|
const bool use_override = src_override.has_value();
|
||||||
|
const s32 src_x0 = copy.src_x0 >> src_samples_x;
|
||||||
|
s32 src_x1 = use_override ? src_override->end.x : copy.src_x1 >> src_samples_x;
|
||||||
|
const s32 src_y0 = copy.src_y0 >> src_samples_y;
|
||||||
|
const s32 src_y1 = copy.src_y1 >> src_samples_y;
|
||||||
|
|
||||||
|
const auto src_width = static_cast<s32>(src_image.info.size.width);
|
||||||
|
const bool width_oob = src_x1 > src_width;
|
||||||
|
const auto width_diff = width_oob ? src_x1 - src_width : 0;
|
||||||
|
if (width_oob) {
|
||||||
|
src_x1 = src_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Region2D src_dimensions{
|
||||||
|
Offset2D{.x = src_x0, .y = src_y0},
|
||||||
|
Offset2D{.x = src_x1, .y = src_y1},
|
||||||
};
|
};
|
||||||
|
const auto src_region = use_override ? *src_override : src_dimensions;
|
||||||
|
|
||||||
|
const std::optional src_base = src_image.TryFindBase(src.Address());
|
||||||
|
const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}};
|
||||||
|
const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range);
|
||||||
|
const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info);
|
||||||
|
const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples);
|
||||||
|
|
||||||
|
const s32 dst_x0 = copy.dst_x0 >> dst_samples_x;
|
||||||
|
const s32 dst_x1 = copy.dst_x1 >> dst_samples_x;
|
||||||
|
const s32 dst_y0 = copy.dst_y0 >> dst_samples_y;
|
||||||
|
const s32 dst_y1 = copy.dst_y1 >> dst_samples_y;
|
||||||
|
const Region2D dst_dimensions{
|
||||||
|
Offset2D{.x = dst_x0, .y = dst_y0},
|
||||||
|
Offset2D{.x = dst_x1 - width_diff, .y = dst_y1},
|
||||||
|
};
|
||||||
|
const auto dst_region = use_override ? *dst_override : dst_dimensions;
|
||||||
|
|
||||||
// Always call this after src_framebuffer_id was queried, as the address might be invalidated.
|
// Always call this after src_framebuffer_id was queried, as the address might be invalidated.
|
||||||
Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id];
|
Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id];
|
||||||
|
@ -804,6 +830,21 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
|
||||||
runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter,
|
runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter,
|
||||||
copy.operation);
|
copy.operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (width_oob) {
|
||||||
|
// Continue copy of the oob region of the texture on the next row
|
||||||
|
auto oob_src = src;
|
||||||
|
oob_src.height++;
|
||||||
|
const Region2D src_region_override{
|
||||||
|
Offset2D{.x = 0, .y = src_y0 + 1},
|
||||||
|
Offset2D{.x = width_diff, .y = src_y1 + 1},
|
||||||
|
};
|
||||||
|
const Region2D dst_region_override{
|
||||||
|
Offset2D{.x = dst_x1 - width_diff, .y = dst_y0},
|
||||||
|
Offset2D{.x = dst_x1, .y = dst_y1},
|
||||||
|
};
|
||||||
|
BlitImage(dst, oob_src, copy, src_region_override, dst_region_override);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
|
|
|
@ -394,7 +394,7 @@ template <u32 GOB_EXTENT>
|
||||||
const s32 mip_offset = diff % layer_stride;
|
const s32 mip_offset = diff % layer_stride;
|
||||||
const std::array offsets = CalculateMipLevelOffsets(new_info);
|
const std::array offsets = CalculateMipLevelOffsets(new_info);
|
||||||
const auto end = offsets.begin() + new_info.resources.levels;
|
const auto end = offsets.begin() + new_info.resources.levels;
|
||||||
const auto it = std::find(offsets.begin(), end, mip_offset);
|
const auto it = std::find(offsets.begin(), end, static_cast<u32>(mip_offset));
|
||||||
if (it == end) {
|
if (it == end) {
|
||||||
// Mipmap is not aligned to any valid size
|
// Mipmap is not aligned to any valid size
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
|
@ -1369,8 +1369,8 @@ static void DecompressBlock(std::span<const u8, 16> inBuf, const u32 blockWidth,
|
||||||
// each partition.
|
// each partition.
|
||||||
|
|
||||||
// Determine partitions, partition index, and color endpoint modes
|
// Determine partitions, partition index, and color endpoint modes
|
||||||
s32 planeIdx = -1;
|
u32 planeIdx{UINT32_MAX};
|
||||||
u32 partitionIndex;
|
u32 partitionIndex{};
|
||||||
u32 colorEndpointMode[4] = {0, 0, 0, 0};
|
u32 colorEndpointMode[4] = {0, 0, 0, 0};
|
||||||
|
|
||||||
// Define color data.
|
// Define color data.
|
||||||
|
|
Loading…
Reference in a new issue