diff --git a/Utilities/address_range.h b/Utilities/address_range.h index f13790ec32..6c852f20ff 100644 --- a/Utilities/address_range.h +++ b/Utilities/address_range.h @@ -1,4 +1,6 @@ -#include "types.h" +#pragma once + +#include "types.h" #include "StrFmt.h" #include @@ -376,7 +378,7 @@ namespace utils // We use index access because we might have to push_back within the loop, which could invalidate the iterators size_type _size = data.size(); - for (int n = 0; n < _size; ++n) + for (size_type n = 0; n < _size; ++n) { address_range &existing = data[n]; @@ -453,7 +455,7 @@ namespace utils { size_t _size = data.size(); - for (int i = 0; i < _size; ++i) + for (size_t i = 0; i < _size; ++i) { const auto &r1 = data[i]; if (!r1.valid()) @@ -461,7 +463,7 @@ namespace utils continue; } - for (int j = i + 1; j < _size; ++j) + for (size_t j = i + 1; j < _size; ++j) { const auto &r2 = data[j]; if (!r2.valid()) diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index 582ad86e40..fb06a2859c 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -652,6 +652,23 @@ u8 get_format_block_size_in_bytes(rsx::surface_color_format format) } } +u8 get_format_sample_count(rsx::surface_antialiasing antialias) +{ + switch (antialias) + { + case rsx::surface_antialiasing::center_1_sample: + return 1; + case rsx::surface_antialiasing::diagonal_centered_2_samples: + return 2; + case rsx::surface_antialiasing::square_centered_4_samples: + case rsx::surface_antialiasing::square_rotated_4_samples: + return 4; + default: + ASSUME(0); + return 0; + } +} + /** * Returns number of texel lines decoded in one pitch-length number of bytes */ diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index c2920c5126..356c466d81 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -28,6 +28,19 @@ namespace rsx storage = 2, }; + enum surface_metrics : u32 + { + pixels = 0, + samples = 1, + bytes = 2 + }; + + enum surface_access : u32 + { + read = 0, + write = 1 + }; + //Sampled image descriptor struct sampled_image_descriptor_base { @@ -108,6 +121,8 @@ u8 get_format_block_size_in_bytes(int format); u8 get_format_block_size_in_texel(int format); u8 get_format_block_size_in_bytes(rsx::surface_color_format format); +u8 get_format_sample_count(rsx::surface_antialiasing antialias); + /** * Returns number of texel rows encoded in one pitch-length line of bytes */ diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index 6d30b7c021..1fcee2b66a 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -2,7 +2,7 @@ #include "Utilities/GSL.h" #include "Emu/Memory/vm.h" -#include "TextureUtils.h" +#include "surface_utils.h" #include "../GCM.h" #include "../rsx_utils.h" #include @@ -25,379 +25,6 @@ namespace rsx size_t get_packed_pitch(surface_color_format format, u32 width); } - enum surface_state_flags : u32 - { - ready = 0, - erase_bkgnd = 1 - }; - - template - struct surface_overlap_info_t - { - surface_type surface = nullptr; - u32 base_address = 0; - bool is_depth = false; - bool is_clipped = false; - - u16 src_x = 0; - u16 src_y = 0; - u16 dst_x = 0; - u16 dst_y = 0; - u16 width = 0; - u16 height = 0; - - areai get_src_area() const - { - return coordi{ {src_x, src_y}, {width, height} }; - } - - areai get_dst_area() const - { - return coordi{ {dst_x, dst_y}, {width, height} }; - } - }; - - struct surface_format_info - { - u32 surface_width; - u32 surface_height; - u16 native_pitch; - u16 rsx_pitch; - u8 bpp; - }; - - template - struct deferred_clipped_region - { - u16 src_x, src_y, dst_x, dst_y, width, height; - f32 transfer_scale_x, transfer_scale_y; - surface_type target; - surface_type source; - - template - deferred_clipped_region cast() const - { - deferred_clipped_region ret; - ret.src_x = src_x; - ret.src_y = src_y; - ret.dst_x = dst_x; - ret.dst_y = dst_y; - ret.width = width; - ret.height = height; - ret.transfer_scale_x = transfer_scale_x; - ret.transfer_scale_y = transfer_scale_y; - ret.target = (T)(target); - ret.source = (T)(source); - - return ret; - } - - operator bool() const - { - return (source != nullptr); - } - - template - void init_transfer(T target_surface) - { - if (!width) - { - // Perform intersection here - const auto region = rsx::get_transferable_region(target_surface); - width = std::get<0>(region); - height = std::get<1>(region); - - transfer_scale_x = f32(std::get<2>(region)) / width; - transfer_scale_y = f32(std::get<3>(region)) / height; - - target = target_surface; - } - } - - areai src_rect() const - { - verify(HERE), width; - return { src_x, src_y, src_x + width, src_y + height }; - } - - areai dst_rect() const - { - verify(HERE), width; - return { dst_x, dst_y, dst_x + u16(width * transfer_scale_x + 0.5f), dst_y + u16(height * transfer_scale_y + 0.5f) }; - } - }; - - template - struct render_target_descriptor - { - u64 last_use_tag = 0; // tag indicating when this block was last confirmed to have been written to - std::array, 5> memory_tag_samples; - - deferred_clipped_region old_contents{}; - rsx::surface_antialiasing read_aa_mode = rsx::surface_antialiasing::center_1_sample; - - GcmTileInfo *tile = nullptr; - rsx::surface_antialiasing write_aa_mode = rsx::surface_antialiasing::center_1_sample; - - flags32_t memory_usage_flags = surface_usage_flags::unknown; - flags32_t state_flags = surface_state_flags::ready; - - union - { - rsx::surface_color_format gcm_color_format; - rsx::surface_depth_format gcm_depth_format; - } - format_info; - - render_target_descriptor() = default; - - virtual ~render_target_descriptor() - { - if (old_contents) - { - // Cascade resource derefs - LOG_ERROR(RSX, "Resource was destroyed whilst holding a resource reference!"); - } - } - - virtual image_storage_type get_surface() = 0; - virtual u16 get_surface_width() const = 0; - virtual u16 get_surface_height() const = 0; - virtual u16 get_rsx_pitch() const = 0; - virtual u16 get_native_pitch() const = 0; - virtual bool is_depth_surface() const = 0; - virtual void release_ref(image_storage_type) const = 0; - - u8 get_bpp() const - { - return u8(get_native_pitch() / get_surface_width()); - } - - void save_aa_mode() - { - read_aa_mode = write_aa_mode; - write_aa_mode = rsx::surface_antialiasing::center_1_sample; - } - - void reset_aa_mode() - { - write_aa_mode = read_aa_mode = rsx::surface_antialiasing::center_1_sample; - } - - void set_format(rsx::surface_color_format format) - { - format_info.gcm_color_format = format; - } - - void set_format(rsx::surface_depth_format format) - { - format_info.gcm_depth_format = format; - } - - rsx::surface_color_format get_surface_color_format() - { - return format_info.gcm_color_format; - } - - rsx::surface_depth_format get_surface_depth_format() - { - return format_info.gcm_depth_format; - } - - bool dirty() const - { - return (state_flags != rsx::surface_state_flags::ready) || old_contents; - } - - bool test() const - { - if (dirty()) - { - // TODO - // Should RCB or mem-sync (inherit previous mem) to init memory - LOG_TODO(RSX, "Resource used before memory initialization"); - } - - // Tags are tested in an X pattern - for (const auto &tag : memory_tag_samples) - { - if (!tag.first) - break; - - if (tag.second != *reinterpret_cast(vm::g_sudo_addr + tag.first)) - return false; - } - - return true; - } - - void clear_rw_barrier() - { - release_ref(old_contents.source); - old_contents = {}; - } - - template - void set_old_contents(T* other) - { - verify(HERE), !old_contents; - - if (!other || other->get_rsx_pitch() != this->get_rsx_pitch()) - { - old_contents = {}; - return; - } - - old_contents = {}; - old_contents.source = other; - other->add_ref(); - } - - template - void set_old_contents_region(const T& region, bool normalized) - { - if (old_contents) - { - // This can happen when doing memory splits - auto old_surface = static_cast(old_contents.source); - if (old_surface->last_use_tag > region.source->last_use_tag) - { - return; - } - - clear_rw_barrier(); - } - - // NOTE: This method will not perform pitch verification! - verify(HERE), !old_contents, region.source, region.source != this; - - old_contents = region.template cast(); - region.source->add_ref(); - - // Reverse normalization process if needed - if (normalized) - { - const u16 bytes_to_texels_x = region.source->get_bpp() * (region.source->write_aa_mode == rsx::surface_antialiasing::center_1_sample? 1 : 2); - const u16 rows_to_texels_y = (region.source->write_aa_mode > rsx::surface_antialiasing::diagonal_centered_2_samples? 2 : 1); - old_contents.src_x /= bytes_to_texels_x; - old_contents.src_y /= rows_to_texels_y; - old_contents.width /= bytes_to_texels_x; - old_contents.height /= rows_to_texels_y; - - const u16 bytes_to_texels_x2 = (get_bpp() * (write_aa_mode == rsx::surface_antialiasing::center_1_sample? 1 : 2)); - const u16 rows_to_texels_y2 = (write_aa_mode > rsx::surface_antialiasing::diagonal_centered_2_samples)? 2 : 1; - old_contents.dst_x /= bytes_to_texels_x2; - old_contents.dst_y /= rows_to_texels_y2; - - old_contents.transfer_scale_x = f32(bytes_to_texels_x) / bytes_to_texels_x2; - old_contents.transfer_scale_y = f32(rows_to_texels_y) / rows_to_texels_y2; - } - - // Apply resolution scale if needed - if (g_cfg.video.resolution_scale_percent != 100) - { - auto src_width = rsx::apply_resolution_scale(old_contents.width, true, old_contents.source->width()); - auto src_height = rsx::apply_resolution_scale(old_contents.height, true, old_contents.source->height()); - - auto dst_width = rsx::apply_resolution_scale(old_contents.width, true, old_contents.target->width()); - auto dst_height = rsx::apply_resolution_scale(old_contents.height, true, old_contents.target->height()); - - old_contents.transfer_scale_x *= f32(dst_width) / src_width; - old_contents.transfer_scale_y *= f32(dst_height) / src_height; - - old_contents.width = src_width; - old_contents.height = src_height; - - old_contents.src_x = rsx::apply_resolution_scale(old_contents.src_x, false, old_contents.source->width()); - old_contents.src_y = rsx::apply_resolution_scale(old_contents.src_y, false, old_contents.source->height()); - old_contents.dst_x = rsx::apply_resolution_scale(old_contents.dst_x, false, old_contents.target->width()); - old_contents.dst_y = rsx::apply_resolution_scale(old_contents.dst_y, false, old_contents.target->height()); - } - } - - void queue_tag(u32 address) - { - for (int i = 0; i < memory_tag_samples.size(); ++i) - { - if (LIKELY(i)) - memory_tag_samples[i].first = 0; - else - memory_tag_samples[i].first = address; // Top left - } - - const u32 pitch = get_native_pitch(); - if (UNLIKELY(pitch < 16)) - { - // Not enough area to gather samples if pitch is too small - return; - } - - // Top right corner - memory_tag_samples[1].first = address + pitch - 8; - - if (const u32 h = get_surface_height(); h > 1) - { - // Last row - const u32 pitch2 = get_rsx_pitch(); - const u32 last_row_offset = pitch2 * (h - 1); - memory_tag_samples[2].first = address + last_row_offset; // Bottom left corner - memory_tag_samples[3].first = address + last_row_offset + pitch - 8; // Bottom right corner - - // Centroid - const u32 center_row_offset = pitch2 * (h / 2); - memory_tag_samples[4].first = address + center_row_offset + pitch / 2; - } - } - - void sync_tag() - { - for (auto &tag : memory_tag_samples) - { - if (!tag.first) - break; - - tag.second = *reinterpret_cast(vm::g_sudo_addr + tag.first); - } - } - - void on_write(u64 write_tag = 0) - { - if (write_tag) - { - // Update use tag if requested - last_use_tag = write_tag; - } - - // Tag unconditionally without introducing new data - sync_tag(); - - read_aa_mode = write_aa_mode; - - // HACK!! This should be cleared through memory barriers only - state_flags = rsx::surface_state_flags::ready; - - if (old_contents.source) - { - clear_rw_barrier(); - } - } - - // Returns the rect area occupied by this surface expressed as an 8bpp image with no AA - areau get_normalized_memory_area() const - { - const u16 internal_width = get_native_pitch() * (write_aa_mode > rsx::surface_antialiasing::center_1_sample? 2: 1); - const u16 internal_height = get_surface_height() * (write_aa_mode > rsx::surface_antialiasing::diagonal_centered_2_samples? 2: 1); - - return { 0, 0, internal_width, internal_height }; - } - - rsx::address_range get_memory_range() const - { - const u32 internal_height = get_surface_height() * (write_aa_mode > rsx::surface_antialiasing::diagonal_centered_2_samples? 2: 1); - return rsx::address_range::start_length(memory_tag_samples[0].first, internal_height * get_rsx_pitch()); - } - }; - /** * Helper for surface (ie color and depth stencil render target) management. * It handles surface creation and storage. Backend should only retrieve pointer to surface. @@ -435,7 +62,7 @@ namespace rsx template void copy_pitched_src_to_dst(gsl::span dest, gsl::span src, size_t src_pitch_in_bytes, size_t width, size_t height) { - for (int row = 0; row < height; row++) + for (unsigned row = 0; row < height; row++) { for (unsigned col = 0; col < width; col++) dest[col] = src[col]; @@ -548,7 +175,7 @@ namespace rsx { // Split in X const u32 baseaddr = address + _new.width; - const u32 bytes_to_texels_x = (bpp * get_aa_factor_u(prev_surface->write_aa_mode)); + const u32 bytes_to_texels_x = (bpp * prev_surface->samples_x); deferred_clipped_region copy; copy.src_x = _new.width / bytes_to_texels_x; @@ -576,15 +203,15 @@ namespace rsx { // Split in Y const u32 baseaddr = address + (_new.height * prev_surface->get_rsx_pitch()); - const u32 bytes_to_texels_x = (bpp * get_aa_factor_u(prev_surface->write_aa_mode)); + const u32 bytes_to_texels_x = (bpp * prev_surface->samples_x); deferred_clipped_region copy; copy.src_x = 0; - copy.src_y = _new.height / get_aa_factor_v(prev_surface->write_aa_mode); + copy.src_y = _new.height / prev_surface->samples_y; copy.dst_x = 0; copy.dst_y = 0; copy.width = std::min(_new.width, old.width) / bytes_to_texels_x; - copy.height = (old.height - _new.height) / get_aa_factor_v(prev_surface->write_aa_mode); + copy.height = (old.height - _new.height) / prev_surface->samples_y; copy.transfer_scale_x = 1.f; copy.transfer_scale_y = 1.f; copy.target = nullptr; @@ -661,7 +288,6 @@ namespace rsx if (prev_surface) { // Append the previous removed surface to the intersection list - std::pair e = { address, prev_surface }; if constexpr (is_depth_surface) { list2.push_back({ address, prev_surface }); @@ -873,7 +499,7 @@ namespace rsx #ifndef INCOMPLETE_SURFACE_CACHE_IMPL // TODO: This can be done better after refactoring - new_surface->write_aa_mode = antialias; + new_surface->set_aa_mode(antialias); // Check if old_surface is 'new' and avoid intersection if (old_surface && old_surface->last_use_tag >= write_tag) @@ -1005,7 +631,7 @@ namespace rsx #ifndef INCOMPLETE_SURFACE_CACHE_IMPL // TODO: Forward this to the management functions - new_surface->write_aa_mode = antialias; + new_surface->set_aa_mode(antialias); // Check if old_surface is 'new' and avoid intersection if (old_surface && old_surface->last_use_tag >= write_tag) @@ -1044,8 +670,6 @@ namespace rsx { u32 clip_width = clip_horizontal_reg; u32 clip_height = clip_vertical_reg; -// u32 clip_x = clip_horizontal_reg; -// u32 clip_y = clip_vertical_reg; cache_tag = rsx::get_shared_tag(); @@ -1267,50 +891,6 @@ namespace rsx return result; } - /** - * Moves a single surface from surface storage to invalidated surface store. - * Can be triggered by the texture cache's blit functionality when formats do not match - */ - void invalidate_single_surface(surface_type surface, bool depth) - { - if (!depth) - { - for (auto It = m_render_targets_storage.begin(); It != m_render_targets_storage.end(); It++) - { - const auto address = It->first; - const auto ref = Traits::get(It->second); - - if (surface == ref) - { - Traits::notify_surface_invalidated(It->second); - invalidated_resources.push_back(std::move(It->second)); - m_render_targets_storage.erase(It); - - cache_tag = rsx::get_shared_tag(); - return; - } - } - } - else - { - for (auto It = m_depth_stencil_storage.begin(); It != m_depth_stencil_storage.end(); It++) - { - const auto address = It->first; - const auto ref = Traits::get(It->second); - - if (surface == ref) - { - Traits::notify_surface_invalidated(It->second); - invalidated_resources.push_back(std::move(It->second)); - m_depth_stencil_storage.erase(It); - - cache_tag = rsx::get_shared_tag(); - return; - } - } - } - } - /** * Invalidates surface that exists at an address */ @@ -1383,10 +963,7 @@ namespace rsx if (!rsx::pitch_compatible(surface, required_pitch, required_height)) continue; - const u16 scale_x = surface->read_aa_mode > rsx::surface_antialiasing::center_1_sample? 2 : 1; - const u16 scale_y = surface->read_aa_mode > rsx::surface_antialiasing::diagonal_centered_2_samples? 2 : 1; - const auto texture_size = pitch * surface->get_surface_height() * scale_y; - + const auto texture_size = pitch * surface->get_surface_height(rsx::surface_metrics::samples); if ((this_address + texture_size) <= texaddr) continue; @@ -1401,11 +978,8 @@ namespace rsx info.base_address = this_address; info.is_depth = is_depth; - surface_format_info surface_info{}; - Traits::get_surface_info(surface, &surface_info); - - const auto normalized_surface_width = (surface_info.surface_width * scale_x * surface_info.bpp) / required_bpp; - const auto normalized_surface_height = surface_info.surface_height * scale_y; + const auto normalized_surface_width = surface->get_native_pitch() / required_bpp; + const auto normalized_surface_height = surface->get_surface_height(rsx::surface_metrics::samples); if (LIKELY(this_address >= texaddr)) { @@ -1445,21 +1019,11 @@ namespace rsx info.is_clipped = (info.width < required_width || info.height < required_height); - if (UNLIKELY(surface_info.bpp != required_bpp)) + if (auto surface_bpp = surface->get_bpp(); UNLIKELY(surface_bpp != required_bpp)) { // Width is calculated in the coordinate-space of the requester; normalize - info.src_x = (info.src_x * required_bpp) / surface_info.bpp; - info.width = (info.width * required_bpp) / surface_info.bpp; - } - - if (UNLIKELY(scale_x > 1)) - { - info.src_x /= scale_x; - info.dst_x /= scale_x; - info.width /= scale_x; - info.src_y /= scale_y; - info.dst_y /= scale_y; - info.height /= scale_y; + info.src_x = (info.src_x * required_bpp) / surface_bpp; + info.width = (info.width * required_bpp) / surface_bpp; } result.push_back(info); diff --git a/rpcs3/Emu/RSX/Common/surface_utils.h b/rpcs3/Emu/RSX/Common/surface_utils.h new file mode 100644 index 0000000000..5c72dd33c6 --- /dev/null +++ b/rpcs3/Emu/RSX/Common/surface_utils.h @@ -0,0 +1,450 @@ +#pragma once + +#include "Utilities/types.h" +#include "Utilities/geometry.h" +#include "Utilities/address_range.h" +#include "TextureUtils.h" +#include "../rsx_utils.h" + +namespace rsx +{ + enum surface_state_flags : u32 + { + ready = 0, + erase_bkgnd = 1 + }; + + template + struct surface_overlap_info_t + { + surface_type surface = nullptr; + u32 base_address = 0; + bool is_depth = false; + bool is_clipped = false; + + u16 src_x = 0; + u16 src_y = 0; + u16 dst_x = 0; + u16 dst_y = 0; + u16 width = 0; + u16 height = 0; + + areai get_src_area() const + { + return coordi{ {src_x, src_y}, {width, height} }; + } + + areai get_dst_area() const + { + return coordi{ {dst_x, dst_y}, {width, height} }; + } + }; + + template + struct deferred_clipped_region + { + u16 src_x, src_y, dst_x, dst_y, width, height; + f32 transfer_scale_x, transfer_scale_y; + surface_type target; + surface_type source; + + template + deferred_clipped_region cast() const + { + deferred_clipped_region ret; + ret.src_x = src_x; + ret.src_y = src_y; + ret.dst_x = dst_x; + ret.dst_y = dst_y; + ret.width = width; + ret.height = height; + ret.transfer_scale_x = transfer_scale_x; + ret.transfer_scale_y = transfer_scale_y; + ret.target = (T)(target); + ret.source = (T)(source); + + return ret; + } + + operator bool() const + { + return (source != nullptr); + } + + template + void init_transfer(T target_surface) + { + if (!width) + { + // Perform intersection here + const auto region = rsx::get_transferable_region(target_surface); + width = std::get<0>(region); + height = std::get<1>(region); + + transfer_scale_x = f32(std::get<2>(region)) / width; + transfer_scale_y = f32(std::get<3>(region)) / height; + + target = target_surface; + } + } + + areai src_rect() const + { + verify(HERE), width; + return { src_x, src_y, src_x + width, src_y + height }; + } + + areai dst_rect() const + { + verify(HERE), width; + return { dst_x, dst_y, dst_x + u16(width * transfer_scale_x + 0.5f), dst_y + u16(height * transfer_scale_y + 0.5f) }; + } + }; + + template + struct render_target_descriptor + { + u64 last_use_tag = 0; // tag indicating when this block was last confirmed to have been written to + std::array, 5> memory_tag_samples; + + // Obsolete, requires updating + deferred_clipped_region old_contents{}; + + // Surface properties + u16 rsx_pitch = 0; + u16 native_pitch = 0; + u16 surface_width = 0; + u16 surface_height = 0; + u8 spp = 1; + u8 samples_x = 1; + u8 samples_y = 1; + + flags32_t memory_usage_flags = surface_usage_flags::unknown; + flags32_t state_flags = surface_state_flags::ready; + + union + { + rsx::surface_color_format gcm_color_format; + rsx::surface_depth_format gcm_depth_format; + } + format_info; + + render_target_descriptor() {} + + virtual ~render_target_descriptor() + { + if (old_contents) + { + // Cascade resource derefs + LOG_ERROR(RSX, "Resource was destroyed whilst holding a resource reference!"); + } + } + + virtual image_storage_type get_surface(rsx::surface_access access_type) = 0; + virtual bool is_depth_surface() const = 0; + virtual void release_ref(image_storage_type) const = 0; + + virtual u16 get_surface_width(rsx::surface_metrics metrics = rsx::surface_metrics::pixels) const + { + switch (metrics) + { + case rsx::surface_metrics::samples: + return surface_width * samples_x; + case rsx::surface_metrics::pixels: + return surface_width; + case rsx::surface_metrics::bytes: + return rsx_pitch; + default: + fmt::throw_exception("Unknown surface metric %d", u32(metrics)); + } + } + + virtual u16 get_surface_height(rsx::surface_metrics metrics = rsx::surface_metrics::pixels) const + { + switch (metrics) + { + case rsx::surface_metrics::samples: + case rsx::surface_metrics::bytes: + return surface_height * samples_y; + case rsx::surface_metrics::pixels: + return surface_height; + default: + fmt::throw_exception("Unknown surface metric %d", u32(metrics)); + } + } + + virtual u16 get_rsx_pitch() const + { + return rsx_pitch; + } + + virtual u16 get_native_pitch() const + { + return native_pitch; + } + + u8 get_bpp() const + { + return u8(get_native_pitch() / get_surface_width()); + } + + u8 get_spp() const + { + return spp; + } + + void set_aa_mode(rsx::surface_antialiasing aa) + { + switch (aa) + { + case rsx::surface_antialiasing::center_1_sample: + samples_x = samples_y = spp = 1; + break; + case rsx::surface_antialiasing::diagonal_centered_2_samples: + samples_x = spp = 2; + samples_y = 1; + break; + case rsx::surface_antialiasing::square_centered_4_samples: + case rsx::surface_antialiasing::square_rotated_4_samples: + samples_x = samples_y = 2; + spp = 4; + break; + default: + fmt::throw_exception("Unknown AA mode 0x%x", (u32)aa); + } + } + + void set_format(rsx::surface_color_format format) + { + format_info.gcm_color_format = format; + } + + void set_format(rsx::surface_depth_format format) + { + format_info.gcm_depth_format = format; + } + + rsx::surface_color_format get_surface_color_format() + { + return format_info.gcm_color_format; + } + + rsx::surface_depth_format get_surface_depth_format() + { + return format_info.gcm_depth_format; + } + + bool dirty() const + { + return (state_flags != rsx::surface_state_flags::ready) || old_contents; + } + + bool test() const + { + if (dirty()) + { + // TODO + // Should RCB or mem-sync (inherit previous mem) to init memory + LOG_TODO(RSX, "Resource used before memory initialization"); + } + + // Tags are tested in an X pattern + for (const auto &tag : memory_tag_samples) + { + if (!tag.first) + break; + + if (tag.second != *reinterpret_cast(vm::g_sudo_addr + tag.first)) + return false; + } + + return true; + } + + void clear_rw_barrier() + { + release_ref(old_contents.source); + old_contents = {}; + } + + template + void set_old_contents(T* other) + { + verify(HERE), !old_contents; + + if (!other || other->get_rsx_pitch() != this->get_rsx_pitch()) + { + old_contents = {}; + return; + } + + old_contents = {}; + old_contents.source = other; + other->add_ref(); + } + + template + void set_old_contents_region(const T& region, bool normalized) + { + if (old_contents) + { + // This can happen when doing memory splits + auto old_surface = static_cast(old_contents.source); + if (old_surface->last_use_tag > region.source->last_use_tag) + { + return; + } + + clear_rw_barrier(); + } + + // NOTE: This method will not perform pitch verification! + verify(HERE), !old_contents, region.source, region.source != this; + + old_contents = region.template cast(); + region.source->add_ref(); + + // Reverse normalization process if needed + if (normalized) + { + const u16 bytes_to_texels_x = region.source->get_bpp() * region.source->samples_x; + const u16 rows_to_texels_y = region.source->samples_y; + old_contents.src_x /= bytes_to_texels_x; + old_contents.src_y /= rows_to_texels_y; + old_contents.width /= bytes_to_texels_x; + old_contents.height /= rows_to_texels_y; + + const u16 bytes_to_texels_x2 = (get_bpp() * samples_x); + const u16 rows_to_texels_y2 = samples_y; + old_contents.dst_x /= bytes_to_texels_x2; + old_contents.dst_y /= rows_to_texels_y2; + + old_contents.transfer_scale_x = f32(bytes_to_texels_x) / bytes_to_texels_x2; + old_contents.transfer_scale_y = f32(rows_to_texels_y) / rows_to_texels_y2; + } + + // Apply resolution scale if needed + if (g_cfg.video.resolution_scale_percent != 100) + { + auto src_width = rsx::apply_resolution_scale(old_contents.width, true, old_contents.source->width()); + auto src_height = rsx::apply_resolution_scale(old_contents.height, true, old_contents.source->height()); + + auto dst_width = rsx::apply_resolution_scale(old_contents.width, true, old_contents.target->width()); + auto dst_height = rsx::apply_resolution_scale(old_contents.height, true, old_contents.target->height()); + + old_contents.transfer_scale_x *= f32(dst_width) / src_width; + old_contents.transfer_scale_y *= f32(dst_height) / src_height; + + old_contents.width = src_width; + old_contents.height = src_height; + + old_contents.src_x = rsx::apply_resolution_scale(old_contents.src_x, false, old_contents.source->width()); + old_contents.src_y = rsx::apply_resolution_scale(old_contents.src_y, false, old_contents.source->height()); + old_contents.dst_x = rsx::apply_resolution_scale(old_contents.dst_x, false, old_contents.target->width()); + old_contents.dst_y = rsx::apply_resolution_scale(old_contents.dst_y, false, old_contents.target->height()); + } + } + + void queue_tag(u32 address) + { + for (unsigned i = 0; i < memory_tag_samples.size(); ++i) + { + if (LIKELY(i)) + memory_tag_samples[i].first = 0; + else + memory_tag_samples[i].first = address; // Top left + } + + const u32 pitch = get_native_pitch(); + if (UNLIKELY(pitch < 16)) + { + // Not enough area to gather samples if pitch is too small + return; + } + + // Top right corner + memory_tag_samples[1].first = address + pitch - 8; + + if (const u32 h = get_surface_height(); h > 1) + { + // Last row + const u32 pitch2 = get_rsx_pitch(); + const u32 last_row_offset = pitch2 * (h - 1); + memory_tag_samples[2].first = address + last_row_offset; // Bottom left corner + memory_tag_samples[3].first = address + last_row_offset + pitch - 8; // Bottom right corner + + // Centroid + const u32 center_row_offset = pitch2 * (h / 2); + memory_tag_samples[4].first = address + center_row_offset + pitch / 2; + } + } + + void sync_tag() + { + for (auto &tag : memory_tag_samples) + { + if (!tag.first) + break; + + tag.second = *reinterpret_cast(vm::g_sudo_addr + tag.first); + } + } + + void on_write(u64 write_tag = 0) + { + if (write_tag) + { + // Update use tag if requested + last_use_tag = write_tag; + } + + // Tag unconditionally without introducing new data + sync_tag(); + + // HACK!! This should be cleared through memory barriers only + state_flags = rsx::surface_state_flags::ready; + + if (old_contents.source) + { + clear_rw_barrier(); + } + } + + // Returns the rect area occupied by this surface expressed as an 8bpp image with no AA + areau get_normalized_memory_area() const + { + const u16 internal_width = get_surface_width(rsx::surface_metrics::bytes); + const u16 internal_height = get_surface_height(rsx::surface_metrics::bytes); + + return { 0, 0, internal_width, internal_height }; + } + + rsx::address_range get_memory_range() const + { + const u32 internal_height = get_surface_height(rsx::surface_metrics::samples); + return rsx::address_range::start_length(memory_tag_samples[0].first, internal_height * get_rsx_pitch()); + } + + template + void transform_samples_to_pixels(area_base& area) + { + if (LIKELY(spp == 1)) return; + + area.x1 /= samples_x; + area.x2 /= samples_x; + area.y1 /= samples_y; + area.y2 /= samples_y; + } + + template + void transform_samples_to_pixels(T& x1, T& x2, T& y1, T& y2) + { + if (LIKELY(spp == 1)) return; + + x1 /= samples_x; + x2 /= samples_x; + y1 /= samples_y; + y2 /= samples_y; + } + }; +} diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index b555da12ce..ff76d8edd7 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -1007,80 +1007,6 @@ namespace rsx } } - /** - * Scaling helpers - * - get_native_dimensions() returns w and h for the native texture given rsx dimensions - * on rsx a 512x512 texture with 4x AA is treated as a 1024x1024 texture for example - * - get_rsx_dimensions() inverse, return rsx w and h given a real texture w and h - * - get_internal_scaling_x/y() returns a scaling factor to be multiplied by 1/size - * when sampling with unnormalized coordinates. tcoords passed to rsx will be in rsx dimensions - */ - template - inline void get_native_dimensions(T &width, T &height, U surface) - { - switch (surface->read_aa_mode) - { - case rsx::surface_antialiasing::center_1_sample: - return; - case rsx::surface_antialiasing::diagonal_centered_2_samples: - width /= 2; - return; - case rsx::surface_antialiasing::square_centered_4_samples: - case rsx::surface_antialiasing::square_rotated_4_samples: - width /= 2; - height /= 2; - return; - } - } - - template - inline void get_rsx_dimensions(T &width, T &height, U surface) - { - switch (surface->read_aa_mode) - { - case rsx::surface_antialiasing::center_1_sample: - return; - case rsx::surface_antialiasing::diagonal_centered_2_samples: - width *= 2; - return; - case rsx::surface_antialiasing::square_centered_4_samples: - case rsx::surface_antialiasing::square_rotated_4_samples: - width *= 2; - height *= 2; - return; - } - } - - template - inline f32 get_internal_scaling_x(T surface) - { - switch (surface->read_aa_mode) - { - default: - case rsx::surface_antialiasing::center_1_sample: - return 1.f; - case rsx::surface_antialiasing::diagonal_centered_2_samples: - case rsx::surface_antialiasing::square_centered_4_samples: - case rsx::surface_antialiasing::square_rotated_4_samples: - return 0.5f; - } - } - - template - inline f32 get_internal_scaling_y(T surface) - { - switch (surface->read_aa_mode) - { - default: - case rsx::surface_antialiasing::center_1_sample: - case rsx::surface_antialiasing::diagonal_centered_2_samples: - return 1.f; - case rsx::surface_antialiasing::square_centered_4_samples: - case rsx::surface_antialiasing::square_rotated_4_samples: - return 0.5f; - } - } - public: texture_cache() : m_storage(this), m_predictor(this) {} @@ -1700,37 +1626,15 @@ namespace rsx verify(HERE), dst_y >= slice_begin; dst_y = (dst_y - slice_begin); - const auto scale_x = 1.f / get_internal_scaling_x(section.surface); - const auto scale_y = 1.f / get_internal_scaling_y(section.surface); - const auto h = std::min(section_end, slice_end) - section.dst_y; - auto src_width = rsx::apply_resolution_scale(section.width, true); - auto src_height = rsx::apply_resolution_scale(h, true); - auto dst_width = u16(src_width * scale_x); - auto dst_height = u16(src_height * scale_y); - - if (scale_x > 1.f) - { - // Clipping - const auto limit_x = dst_x + dst_width; - const auto limit_y = dst_x + dst_height; - - if (limit_x > slice_w) - { - dst_width = (slice_w - dst_x); - src_width = u16(dst_width / scale_x); - } - - if (limit_y > slice_h) - { - dst_height = (slice_h - dst_y); - src_height = u16(dst_height / scale_y); - } - } + const auto src_width = rsx::apply_resolution_scale(section.width, true); + const auto src_height = rsx::apply_resolution_scale(h, true); + const auto dst_width = src_width; + const auto dst_height = src_height; surfaces.push_back ({ - section.surface->get_surface(), + section.surface->get_surface(rsx::surface_access::read), surface_transform::identity, rsx::apply_resolution_scale(src_x, true), rsx::apply_resolution_scale(src_y, true), @@ -1894,23 +1798,19 @@ namespace rsx return false; } - const auto surface_width = texptr->get_surface_width(); - const auto surface_height = texptr->get_surface_height(); - - u32 internal_width = tex_width; - u32 internal_height = tex_height; - get_native_dimensions(internal_width, internal_height, texptr); + const auto surface_width = texptr->get_surface_width(rsx::surface_metrics::samples); + const auto surface_height = texptr->get_surface_height(rsx::surface_metrics::samples); switch (extended_dimension) { case rsx::texture_dimension_extended::texture_dimension_1d: - return (surface_width >= internal_width); + return (surface_width >= tex_width); case rsx::texture_dimension_extended::texture_dimension_2d: - return (surface_width >= internal_width && surface_height >= internal_height); + return (surface_width >= tex_width && surface_height >= tex_height); case rsx::texture_dimension_extended::texture_dimension_3d: - return (surface_width >= internal_width && surface_height >= (internal_height * tex_depth)); + return (surface_width >= tex_width && surface_height >= (tex_height * tex_depth)); case rsx::texture_dimension_extended::texture_dimension_cubemap: - return (surface_width == internal_height && surface_width >= internal_width && surface_height >= (internal_height * 6)); + return (surface_width == tex_height && surface_width >= tex_width && surface_height >= (tex_height * 6)); } return false; @@ -1927,12 +1827,8 @@ namespace rsx { texptr->read_barrier(cmd); - const auto surface_width = texptr->get_surface_width(); - const auto surface_height = texptr->get_surface_height(); - - u32 internal_width = tex_width; - u32 internal_height = tex_height; - get_native_dimensions(internal_width, internal_height, texptr); + const auto surface_width = texptr->get_surface_width(rsx::surface_metrics::samples); + const auto surface_height = texptr->get_surface_height(rsx::surface_metrics::samples); bool is_depth = texptr->is_depth_surface(); const bool force_convert = !render_target_format_is_compatible(texptr, format); @@ -1958,19 +1854,19 @@ namespace rsx { if (extended_dimension == rsx::texture_dimension_extended::texture_dimension_1d) { - internal_height = 1; + tex_height = 1; } if ((surface_is_rop_target && g_cfg.video.strict_rendering_mode) || - internal_width < surface_width || - internal_height < surface_height || + tex_width < surface_width || + tex_height < surface_height || force_convert) { - const auto scaled_w = rsx::apply_resolution_scale(internal_width, true); - const auto scaled_h = rsx::apply_resolution_scale(internal_height, true); + const auto scaled_w = rsx::apply_resolution_scale(tex_width, true); + const auto scaled_h = rsx::apply_resolution_scale(tex_height, true); const auto command = surface_is_rop_target ? deferred_request_command::copy_image_dynamic : deferred_request_command::copy_image_static; - return { texptr->get_surface(), command, texaddr, format, 0, 0, scaled_w, scaled_h, 1, + return { texptr->get_surface(rsx::surface_access::read), command, texaddr, format, 0, 0, scaled_w, scaled_h, 1, texture_upload_context::framebuffer_storage, is_depth, scale_x, scale_y, extended_dimension, decoded_remap }; } @@ -1984,19 +1880,19 @@ namespace rsx is_depth, scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d, surface_is_rop_target }; } - const auto scaled_w = rsx::apply_resolution_scale(internal_width, true); - const auto scaled_h = rsx::apply_resolution_scale(internal_height, true); + const auto scaled_w = rsx::apply_resolution_scale(tex_width, true); + const auto scaled_h = rsx::apply_resolution_scale(tex_height, true); if (extended_dimension == rsx::texture_dimension_extended::texture_dimension_3d) { - return{ texptr->get_surface(), deferred_request_command::_3d_unwrap, texaddr, format, 0, 0, + return{ texptr->get_surface(rsx::surface_access::read), deferred_request_command::_3d_unwrap, texaddr, format, 0, 0, scaled_w, scaled_h, tex_depth, texture_upload_context::framebuffer_storage, is_depth, 1.f, 1.f, rsx::texture_dimension_extended::texture_dimension_3d, decoded_remap }; } verify(HERE), extended_dimension == rsx::texture_dimension_extended::texture_dimension_cubemap; - return{ texptr->get_surface(), deferred_request_command::cubemap_unwrap, texaddr, format, 0, 0, + return{ texptr->get_surface(rsx::surface_access::read), deferred_request_command::cubemap_unwrap, texaddr, format, 0, 0, scaled_w, scaled_h, 1, texture_upload_context::framebuffer_storage, is_depth, 1.f, 1.f, rsx::texture_dimension_extended::texture_dimension_cubemap, decoded_remap }; @@ -2218,12 +2114,8 @@ namespace rsx const auto& last = overlapping_fbos.back(); if (last.src_x == 0 && last.src_y == 0) { - u16 internal_width = tex_width; - u16 internal_height = required_surface_height; - get_native_dimensions(internal_width, internal_height, last.surface); - u16 normalized_width = u16(last.width * last.surface->get_bpp()) / bpp; - if (normalized_width >= internal_width && last.height >= internal_height) + if (normalized_width >= tex_width && last.height >= tex_height) { return process_framebuffer_resource_fast(cmd, last.surface, texaddr, format, tex_width, tex_height, depth, scale_x, scale_y, extended_dimension, tex.remap(), tex.decoded_remap(), false); @@ -2486,7 +2378,6 @@ namespace rsx auto _w = u32(It->width * It->surface->get_bpp()) / bpp; auto _h = u32(It->height); - get_rsx_dimensions(_w, _h, It->surface); if (_w < width) { @@ -2596,9 +2487,9 @@ namespace rsx size2i dst_dimensions = { dst.pitch / dst_bpp, dst.height }; if (src_is_render_target) { - if (dst_dimensions.width == src_subres.surface->get_surface_width()) + if (dst_dimensions.width == src_subres.surface->get_surface_width(rsx::surface_metrics::samples)) { - dst_dimensions.height = std::max(src_subres.surface->get_surface_height(), dst.height); + dst_dimensions.height = std::max(src_subres.surface->get_surface_height(rsx::surface_metrics::samples), dst.height); } else if (LIKELY(dst_dimensions.width == 1280 || dst_dimensions.width == 2560)) { @@ -2673,11 +2564,11 @@ namespace rsx // Destination dimensions are relaxed (true) dst_area = dst_subres.get_src_area(); - dest_texture = dst_subres.surface->get_surface(); + dest_texture = dst_subres.surface->get_surface(rsx::surface_access::write); typeless_info.dst_context = texture_upload_context::framebuffer_storage; - max_dst_width = (u16)(dst_subres.surface->get_surface_width() * typeless_info.dst_scaling_hint); - max_dst_height = dst_subres.surface->get_surface_height(); + max_dst_width = (u16)(dst_subres.surface->get_surface_width(rsx::surface_metrics::samples) * typeless_info.dst_scaling_hint); + max_dst_height = dst_subres.surface->get_surface_height(rsx::surface_metrics::samples); } // Check if available target is acceptable @@ -2824,7 +2715,7 @@ namespace rsx else { src_area = src_subres.get_src_area(); - vram_texture = src_subres.surface->get_surface(); + vram_texture = src_subres.surface->get_surface(rsx::surface_access::read); typeless_info.src_context = texture_upload_context::framebuffer_storage; } @@ -2969,13 +2860,13 @@ namespace rsx const f32 resolution_scale = rsx::get_resolution_scale(); if (src_is_render_target) { - if (src_subres.surface->get_surface_width() > g_cfg.video.min_scalable_dimension) + if (src_subres.surface->get_surface_width(rsx::surface_metrics::pixels) > g_cfg.video.min_scalable_dimension) { src_area.x1 = (u16)(src_area.x1 * resolution_scale); src_area.x2 = (u16)(src_area.x2 * resolution_scale); } - if (src_subres.surface->get_surface_height() > g_cfg.video.min_scalable_dimension) + if (src_subres.surface->get_surface_height(rsx::surface_metrics::pixels) > g_cfg.video.min_scalable_dimension) { src_area.y1 = (u16)(src_area.y1 * resolution_scale); src_area.y2 = (u16)(src_area.y2 * resolution_scale); @@ -2984,13 +2875,13 @@ namespace rsx if (dst_is_render_target) { - if (dst_subres.surface->get_surface_width() > g_cfg.video.min_scalable_dimension) + if (dst_subres.surface->get_surface_width(rsx::surface_metrics::pixels) > g_cfg.video.min_scalable_dimension) { dst_area.x1 = (u16)(dst_area.x1 * resolution_scale); dst_area.x2 = (u16)(dst_area.x2 * resolution_scale); } - if (dst_subres.surface->get_surface_height() > g_cfg.video.min_scalable_dimension) + if (dst_subres.surface->get_surface_height(rsx::surface_metrics::pixels) > g_cfg.video.min_scalable_dimension) { dst_area.y1 = (u16)(dst_area.y1 * resolution_scale); dst_area.y2 = (u16)(dst_area.y2 * resolution_scale); @@ -2998,6 +2889,18 @@ namespace rsx } } + if (src_is_render_target) + { + // TODO: Specify typeless for high sample counts + src_subres.surface->transform_samples_to_pixels(src_area); + } + + if (dst_is_render_target) + { + // TODO: Specify typeless for high sample counts + dst_subres.surface->transform_samples_to_pixels(dst_area); + } + typeless_info.analyse(); blitter.scale_image(cmd, vram_texture, dest_texture, src_area, dst_area, interpolate, is_depth_blit, typeless_info); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index dac07cdf6d..e964f8fad4 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -1685,7 +1685,7 @@ void GLGSRender::flip(int buffer, bool emu_flip) // TODO: Take AA scaling into account LOG_WARNING(RSX, "Selected output image does not satisfy the video configuration. Display buffer resolution=%dx%d, avconf resolution=%dx%d, surface=%dx%d", display_buffers[buffer].width, display_buffers[buffer].height, avconfig ? avconfig->resolution_x : 0, avconfig ? avconfig->resolution_y : 0, - render_target_texture->get_surface_width(), render_target_texture->get_surface_height()); + render_target_texture->get_surface_width(rsx::surface_metrics::pixels), render_target_texture->get_surface_height(rsx::surface_metrics::pixels)); buffer_width = render_target_texture->width(); buffer_height = render_target_texture->height(); diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index bf4e1bc994..30bd47042f 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -195,19 +195,6 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk { // Nothing has changed, we're still using the same framebuffer // Update flags to match current - for (u32 index = 0; index < 4; index++) - { - if (auto surface = std::get<1>(m_rtts.m_bound_render_targets[index])) - { - surface->write_aa_mode = layout.aa_mode; - } - } - - if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil)) - { - ds->write_aa_mode = layout.aa_mode; - } - m_draw_fbo->bind(); set_viewport(); set_scissor(); @@ -223,9 +210,6 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk layout.color_addresses, layout.zeta_address, layout.actual_color_pitch, layout.actual_zeta_pitch); - bool old_format_found = false; - gl::texture::format old_format; - std::array color_targets; GLuint depth_stencil_target; @@ -234,17 +218,12 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk const u8 color_bpp = get_format_block_size_in_bytes(layout.color_format); const u8 depth_bpp = (layout.depth_format == rsx::surface_depth_format::z16 ? 2 : 4); + const auto samples = get_format_sample_count(layout.aa_mode); for (int i = 0; i < rsx::limits::color_buffers_count; ++i) { if (m_surface_info[i].pitch && g_cfg.video.write_color_buffers) { - if (!old_format_found) - { - old_format = rsx::internals::surface_color_format_to_gl(m_surface_info[i].color_format).format; - old_format_found = true; - } - const utils::address_range surface_range = m_surface_info[i].get_memory_range(); m_gl_texture_cache.set_memory_read_flags(surface_range, rsx::memory_read_flags::flush_once); m_gl_texture_cache.flush_if_cache_miss_likely(cmd, surface_range); @@ -256,10 +235,13 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk color_targets[i] = rtt->id(); verify("Pitch mismatch!" HERE), rtt->get_rsx_pitch() == layout.actual_color_pitch[i]; - m_surface_info[i] = { layout.color_addresses[i], layout.actual_color_pitch[i], false, layout.color_format, layout.depth_format, layout.width, layout.height, color_bpp }; - - rtt->tile = find_tile(color_offsets[i], color_locations[i]); - rtt->write_aa_mode = layout.aa_mode; + m_surface_info[i].address = layout.color_addresses[i]; + m_surface_info[i].pitch = layout.actual_color_pitch[i]; + m_surface_info[i].width = layout.width; + m_surface_info[i].height = layout.height; + m_surface_info[i].color_format = layout.color_format; + m_surface_info[i].bpp = color_bpp; + m_surface_info[i].samples = samples; m_gl_texture_cache.notify_surface_changed(m_surface_info[i].get_memory_range(layout.aa_factors)); } else @@ -285,9 +267,14 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk depth_stencil_target = ds->id(); verify("Pitch mismatch!" HERE), std::get<1>(m_rtts.m_bound_depth_stencil)->get_rsx_pitch() == layout.actual_zeta_pitch; - m_depth_surface_info = { layout.zeta_address, layout.actual_zeta_pitch, true, layout.color_format, layout.depth_format, layout.width, layout.height, depth_bpp }; - ds->write_aa_mode = layout.aa_mode; + m_depth_surface_info.address = layout.zeta_address; + m_depth_surface_info.pitch = layout.actual_zeta_pitch; + m_depth_surface_info.width = layout.width; + m_depth_surface_info.height = layout.height; + m_depth_surface_info.depth_format = layout.depth_format; + m_depth_surface_info.bpp = (layout.depth_format == rsx::surface_depth_format::z16? 2 : 4); + m_depth_surface_info.samples = samples; m_gl_texture_cache.notify_surface_changed(m_depth_surface_info.get_memory_range(layout.aa_factors)); } else @@ -457,7 +444,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk m_gl_texture_cache.lock_memory_region( cmd, surface, surface->get_memory_range(), false, - surface->get_surface_width(), surface->get_surface_height(), surface->get_rsx_pitch(), + surface->get_surface_width(rsx::surface_metrics::pixels), surface->get_surface_height(rsx::surface_metrics::pixels), surface->get_rsx_pitch(), format, type, swap_bytes); } } diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.h b/rpcs3/Emu/RSX/GL/GLRenderTargets.h index b14cd6b51f..1d12e4428b 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.h +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.h @@ -51,11 +51,6 @@ namespace gl { class render_target : public viewable_image, public rsx::ref_counted, public rsx::render_target_descriptor { - u32 rsx_pitch = 0; - u16 native_pitch = 0; - - u16 surface_height = 0; - u16 surface_width = 0; u16 surface_pixel_size = 0; public: @@ -69,11 +64,6 @@ namespace gl native_pitch = pitch; } - u16 get_native_pitch() const override - { - return native_pitch; - } - void set_surface_dimensions(u16 w, u16 h, u16 pitch) { surface_width = w; @@ -91,16 +81,6 @@ namespace gl return rsx_pitch; } - u16 get_surface_width() const override - { - return surface_width; - } - - u16 get_surface_height() const override - { - return surface_height; - } - bool is_depth_surface() const override { switch (get_internal_format()) @@ -119,8 +99,9 @@ namespace gl static_cast(t)->release(); } - texture* get_surface() override + texture* get_surface(rsx::surface_access access_type) override { + // TODO return (gl::texture*)this; } @@ -222,8 +203,8 @@ struct gl_render_target_traits if (!sink) { auto internal_format = (GLenum)ref->get_internal_format(); - const auto new_w = rsx::apply_resolution_scale(prev.width, true, ref->get_surface_width()); - const auto new_h = rsx::apply_resolution_scale(prev.height, true, ref->get_surface_height()); + const auto new_w = rsx::apply_resolution_scale(prev.width, true, ref->get_surface_width(rsx::surface_metrics::pixels)); + const auto new_h = rsx::apply_resolution_scale(prev.height, true, ref->get_surface_height(rsx::surface_metrics::pixels)); sink = std::make_unique(new_w, new_h, internal_format); sink->add_ref(); @@ -253,18 +234,8 @@ struct gl_render_target_traits bool is_compatible_surface(const gl::render_target* surface, const gl::render_target* ref, u16 width, u16 height, u8 /*sample_count*/) { return (surface->get_internal_format() == ref->get_internal_format() && - surface->get_surface_width() >= width && - surface->get_surface_height() >= height); - } - - static - void get_surface_info(gl::render_target *surface, rsx::surface_format_info *info) - { - info->rsx_pitch = surface->get_rsx_pitch(); - info->native_pitch = surface->get_native_pitch(); - info->surface_width = surface->get_surface_width(); - info->surface_height = surface->get_surface_height(); - info->bpp = surface->get_bpp(); + surface->get_surface_width(rsx::surface_metrics::pixels) >= width && + surface->get_surface_height(rsx::surface_metrics::pixels) >= height); } static void prepare_rtt_for_drawing(gl::command_context&, gl::render_target* rtt) @@ -290,7 +261,7 @@ struct gl_render_target_traits void invalidate_surface_contents(gl::command_context&, gl::render_target *surface, u32 address, size_t pitch) { surface->set_rsx_pitch((u16)pitch); - surface->reset_aa_mode(); + surface->set_aa_mode(rsx::surface_antialiasing::center_1_sample); surface->queue_tag(address); surface->last_use_tag = 0; surface->memory_usage_flags = rsx::surface_usage_flags::unknown; @@ -310,9 +281,7 @@ struct gl_render_target_traits static void notify_surface_persist(const std::unique_ptr& surface) - { - surface->save_aa_mode(); - } + {} static void notify_surface_reused(const std::unique_ptr& surface) diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 0140d8d5ae..cdf5db77ba 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -245,18 +245,9 @@ namespace gl if (context == rsx::texture_upload_context::framebuffer_storage) { - switch (static_cast(vram_texture)->read_aa_mode) - { - case rsx::surface_antialiasing::center_1_sample: - break; - case rsx::surface_antialiasing::diagonal_centered_2_samples: - real_width *= 2; - break; - default: - real_width *= 2; - real_height *= 2; - break; - } + auto surface = gl::as_rtt(vram_texture); + real_width *= surface->samples_x; + real_height *= surface->samples_y; } areai src_area = { 0, 0, 0, 0 }; @@ -628,9 +619,17 @@ namespace gl const bool typeless = dst_aspect != slice.src->aspect() || !formats_are_bitcast_compatible((GLenum)slice.src->get_internal_format(), (GLenum)dst_image->get_internal_format()); + std::unique_ptr tmp; auto src_image = slice.src; auto src_x = slice.src_x; - std::unique_ptr tmp; + auto src_y = slice.src_y; + auto src_w = slice.src_w; + auto src_h = slice.src_h; + + if (auto surface = dynamic_cast(slice.src)) + { + surface->transform_samples_to_pixels(src_x, src_y, src_w, src_h); + } if (UNLIKELY(typeless)) { @@ -643,17 +642,17 @@ namespace gl gl::copy_typeless(src_image, slice.src); } - if (slice.src_w == slice.dst_w && slice.src_h == slice.dst_h) + if (src_w == slice.dst_w && src_h == slice.dst_h) { - glCopyImageSubData(src_image->id(), GL_TEXTURE_2D, 0, src_x, slice.src_y, 0, - dst_image->id(), (GLenum)dst_image->get_target(), 0, slice.dst_x, slice.dst_y, slice.dst_z, slice.src_w, slice.src_h, 1); + glCopyImageSubData(src_image->id(), GL_TEXTURE_2D, 0, src_x, src_y, 0, + dst_image->id(), (GLenum)dst_image->get_target(), 0, slice.dst_x, slice.dst_y, slice.dst_z, src_w, src_h, 1); } else { verify(HERE), dst_image->get_target() == gl::texture::target::texture2D; auto _blitter = gl::g_hw_blitter; - const areai src_rect = { src_x, slice.src_y, src_x + slice.src_w, slice.src_y + slice.src_h }; + const areai src_rect = { src_x, src_y, src_x + src_w, src_y + src_h }; const areai dst_rect = { slice.dst_x, slice.dst_y, slice.dst_x + slice.dst_w, slice.dst_y + slice.dst_h }; auto _dst = dst_image; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 45b572372b..50efb92aa8 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1033,6 +1033,7 @@ namespace rsx const auto aa_mode = rsx::method_registers.surface_antialias(); const u32 aa_factor_u = (aa_mode == rsx::surface_antialiasing::center_1_sample) ? 1 : 2; const u32 aa_factor_v = (aa_mode == rsx::surface_antialiasing::center_1_sample || aa_mode == rsx::surface_antialiasing::diagonal_centered_2_samples) ? 1 : 2; + const u8 sample_count = get_format_sample_count(aa_mode); const auto depth_texel_size = (layout.depth_format == rsx::surface_depth_format::z16 ? 2 : 4) * aa_factor_u; const auto color_texel_size = get_format_block_size_in_bytes(layout.color_format) * aa_factor_u; @@ -1213,7 +1214,8 @@ namespace rsx if (layout.color_addresses[i]) { if (m_surface_info[i].width != layout.width || - m_surface_info[i].height != layout.height) + m_surface_info[i].height != layout.height || + m_surface_info[i].samples != sample_count) { really_changed = true; break; @@ -1223,7 +1225,8 @@ namespace rsx if (!really_changed) { - if (layout.zeta_address == m_depth_surface_info.address) + if (layout.zeta_address == m_depth_surface_info.address && + sample_count == m_depth_surface_info.samples) { // Same target is reused return layout; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index f63a0e582f..872d18efcb 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -2725,22 +2725,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) { // Nothing has changed, we're still using the same framebuffer // Update flags to match current - - const auto aa_mode = rsx::method_registers.surface_antialias(); - - for (u32 index = 0; index < 4; index++) - { - if (auto surface = std::get<1>(m_rtts.m_bound_render_targets[index])) - { - surface->write_aa_mode = layout.aa_mode; - } - } - - if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil)) - { - ds->write_aa_mode = layout.aa_mode; - } - + set_scissor(); return; } @@ -2755,6 +2740,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) // Reset framebuffer information VkFormat old_format = VK_FORMAT_UNDEFINED; const auto color_bpp = get_format_block_size_in_bytes(layout.color_format); + const auto samples = get_format_sample_count(layout.aa_mode); for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i) { @@ -2774,6 +2760,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) m_surface_info[i].height = layout.height; m_surface_info[i].color_format = layout.color_format; m_surface_info[i].bpp = color_bpp; + m_surface_info[i].samples = samples; } //Process depth surface as well @@ -2791,6 +2778,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) m_depth_surface_info.height = layout.height; m_depth_surface_info.depth_format = layout.depth_format; m_depth_surface_info.bpp = (layout.depth_format == rsx::surface_depth_format::z16? 2 : 4); + m_depth_surface_info.samples = samples; } //Bind created rtts as current fbo... @@ -2808,7 +2796,6 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) m_surface_info[index].pitch = layout.actual_color_pitch[index]; verify("Pitch mismatch!" HERE), surface->rsx_pitch == layout.actual_color_pitch[index]; - surface->write_aa_mode = layout.aa_mode; m_texture_cache.notify_surface_changed(m_surface_info[index].get_memory_range(layout.aa_factors)); m_draw_buffers.push_back(index); } @@ -2823,7 +2810,6 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) m_depth_surface_info.pitch = layout.actual_zeta_pitch; verify("Pitch mismatch!" HERE), ds->rsx_pitch == layout.actual_zeta_pitch; - ds->write_aa_mode = layout.aa_mode; m_texture_cache.notify_surface_changed(m_depth_surface_info.get_memory_range(layout.aa_factors)); } @@ -2895,7 +2881,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) m_texture_cache.lock_memory_region( *m_current_command_buffer, surface, surface->get_memory_range(), false, - surface->get_surface_width(), surface->get_surface_height(), surface->get_rsx_pitch(), + surface->get_surface_width(rsx::surface_metrics::pixels), surface->get_surface_height(rsx::surface_metrics::pixels), surface->get_rsx_pitch(), gcm_format, swap_bytes); } } @@ -3184,7 +3170,7 @@ void VKGSRender::flip(int buffer, bool emu_flip) // TODO: Take AA scaling into account LOG_WARNING(RSX, "Selected output image does not satisfy the video configuration. Display buffer resolution=%dx%d, avconf resolution=%dx%d, surface=%dx%d", display_buffers[buffer].width, display_buffers[buffer].height, avconfig? avconfig->resolution_x : 0, avconfig? avconfig->resolution_y : 0, - render_target_texture->get_surface_width(), render_target_texture->get_surface_height()); + render_target_texture->get_surface_width(rsx::surface_metrics::pixels), render_target_texture->get_surface_height(rsx::surface_metrics::pixels)); buffer_width = render_target_texture->width(); buffer_height = render_target_texture->height(); diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index ca14bf0dde..296b422e27 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -13,41 +13,16 @@ namespace vk { struct render_target : public viewable_image, public rsx::ref_counted, public rsx::render_target_descriptor { - u16 native_pitch = 0; - u16 rsx_pitch = 0; - - u16 surface_width = 0; - u16 surface_height = 0; - u64 frame_tag = 0; // frame id when invalidated, 0 if not invalid using viewable_image::viewable_image; - vk::viewable_image* get_surface() override + vk::viewable_image* get_surface(rsx::surface_access access_type) override { + // TODO return (vk::viewable_image*)this; } - u16 get_surface_width() const override - { - return surface_width; - } - - u16 get_surface_height() const override - { - return surface_height; - } - - u16 get_rsx_pitch() const override - { - return rsx_pitch; - } - - u16 get_native_pitch() const override - { - return native_pitch; - } - bool is_depth_surface() const override { return !!(aspect() & VK_IMAGE_ASPECT_DEPTH_BIT); @@ -273,8 +248,8 @@ namespace rsx { if (!sink) { - const auto new_w = rsx::apply_resolution_scale(prev.width, true, ref->get_surface_width()); - const auto new_h = rsx::apply_resolution_scale(prev.height, true, ref->get_surface_height()); + const auto new_w = rsx::apply_resolution_scale(prev.width, true, ref->get_surface_width(rsx::surface_metrics::pixels)); + const auto new_h = rsx::apply_resolution_scale(prev.height, true, ref->get_surface_height(rsx::surface_metrics::pixels)); auto& dev = cmd.get_command_pool().get_owner(); sink = std::make_unique(dev, dev.get_memory_mapping().device_local, @@ -282,7 +257,7 @@ namespace rsx VK_IMAGE_TYPE_2D, ref->format(), new_w, new_h, 1, 1, 1, - VK_SAMPLE_COUNT_1_BIT, + (VkSampleCountFlagBits)ref->samples(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, ref->info.usage, @@ -316,15 +291,6 @@ namespace rsx surface->get_surface_height() >= height); } - static void get_surface_info(vk::render_target *surface, rsx::surface_format_info *info) - { - info->rsx_pitch = surface->rsx_pitch; - info->native_pitch = surface->native_pitch; - info->surface_width = surface->get_surface_width(); - info->surface_height = surface->get_surface_height(); - info->bpp = surface->get_bpp(); - } - static void prepare_rtt_for_drawing(vk::command_buffer& cmd, vk::render_target *surface) { surface->change_layout(cmd, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); @@ -357,7 +323,7 @@ namespace rsx static void invalidate_surface_contents(vk::command_buffer& /*cmd*/, vk::render_target *surface, u32 address, size_t pitch) { surface->rsx_pitch = (u16)pitch; - surface->reset_aa_mode(); + surface->set_aa_mode(rsx::surface_antialiasing::center_1_sample); surface->queue_tag(address); surface->last_use_tag = 0; surface->memory_usage_flags = rsx::surface_usage_flags::unknown; @@ -378,9 +344,7 @@ namespace rsx } static void notify_surface_persist(const std::unique_ptr &surface) - { - surface->save_aa_mode(); - } + {} static void notify_surface_reused(const std::unique_ptr &surface) { diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 3e1c70750a..ac263e7de8 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -211,18 +211,9 @@ namespace vk { if (context == rsx::texture_upload_context::framebuffer_storage) { - switch (static_cast(vram_texture)->read_aa_mode) - { - case rsx::surface_antialiasing::center_1_sample: - break; - case rsx::surface_antialiasing::diagonal_centered_2_samples: - transfer_width *= 2; - break; - default: - transfer_width *= 2; - transfer_height *= 2; - break; - } + auto surface = vk::as_rtt(vram_texture); + transfer_width *= surface->samples_x; + transfer_height *= surface->samples_y; } if (transfer_width != vram_texture->width() || transfer_height != vram_texture->height()) @@ -512,15 +503,25 @@ namespace vk section.src->push_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); auto src_image = section.src; + auto src_x = section.src_x; + auto src_y = section.src_y; + auto src_w = section.src_w; + auto src_h = section.src_h; + + if (auto surface = dynamic_cast(section.src)) + { + surface->transform_samples_to_pixels(src_x, src_y, src_w, src_h); + } + if (UNLIKELY(typeless)) { - src_image = vk::get_typeless_helper(dst->info.format, section.src_x + section.src_w, section.src_y + section.src_h); + src_image = vk::get_typeless_helper(dst->info.format, src_x + src_w, src_y + src_h); src_image->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); const auto src_bpp = vk::get_format_texel_width(section.src->format()); - const u16 convert_w = u16(section.src_w * dst_bpp) / src_bpp; - const areai src_rect = coordi{{ section.src_x, section.src_y }, { convert_w, section.src_h }}; - const areai dst_rect = coordi{{ section.src_x, section.src_y }, { section.src_w, section.src_h }}; + const u16 convert_w = u16(src_w * dst_bpp) / src_bpp; + const areai src_rect = coordi{{ src_x, src_y }, { convert_w, src_h }}; + const areai dst_rect = coordi{{ src_x, src_y }, { src_w, src_h }}; vk::copy_image_typeless(cmd, section.src, src_image, src_rect, dst_rect, 1, section.src->aspect(), dst_aspect); src_image->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); } @@ -530,14 +531,14 @@ namespace vk // Final aspect mask of the 'final' transfer source const auto new_src_aspect = src_image->aspect(); - if (LIKELY(section.src_w == section.dst_w && section.src_h == section.dst_h && section.xform == surface_transform::identity)) + if (LIKELY(src_w == section.dst_w && src_h == section.dst_h && section.xform == surface_transform::identity)) { VkImageCopy copy_rgn; - copy_rgn.srcOffset = { section.src_x, section.src_y, 0 }; + copy_rgn.srcOffset = { src_x, src_y, 0 }; copy_rgn.dstOffset = { section.dst_x, section.dst_y, 0 }; copy_rgn.dstSubresource = { dst_aspect, 0, 0, 1 }; copy_rgn.srcSubresource = { new_src_aspect, 0, 0, 1 }; - copy_rgn.extent = { section.src_w, section.src_h, 1 }; + copy_rgn.extent = { src_w, src_h, 1 }; if (dst->info.imageType == VK_IMAGE_TYPE_3D) { @@ -572,7 +573,7 @@ namespace vk if (section.xform == surface_transform::identity) { vk::copy_scaled_image(cmd, src_image->value, _dst->value, section.src->current_layout, _dst->current_layout, - coordi{ { section.src_x, section.src_y }, { section.src_w, section.src_h } }, + coordi{ { src_x, src_y }, { src_w, src_h } }, coordi{ { section.dst_x, section.dst_y }, { section.dst_w, section.dst_h } }, 1, src_image->aspect(), src_image->info.format == _dst->info.format, VK_FILTER_NEAREST, src_image->info.format, _dst->info.format); @@ -580,14 +581,14 @@ namespace vk else if (section.xform == surface_transform::argb_to_bgra) { VkBufferImageCopy copy{}; - copy.imageExtent = { section.src_w, section.src_h, 1 }; - copy.imageOffset = { section.src_x, section.src_y, 0 }; + copy.imageExtent = { src_w, src_h, 1 }; + copy.imageOffset = { src_x, src_y, 0 }; copy.imageSubresource = { src_image->aspect(), 0, 0, 1 }; auto scratch_buf = vk::get_scratch_buffer(); vkCmdCopyImageToBuffer(cmd, src_image->value, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, scratch_buf->value, 1, ©); - const auto mem_length = section.src_w * section.src_h * dst_bpp; + const auto mem_length = src_w * src_h * dst_bpp; vk::insert_buffer_memory_barrier(cmd, scratch_buf->value, 0, mem_length, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); @@ -606,16 +607,16 @@ namespace vk dst_x = 0; dst_y = 0; - if (section.src_w != section.dst_w || section.src_h != section.dst_h) + if (src_w != section.dst_w || src_h != section.dst_h) { // Optionally scale if needed if (UNLIKELY(tmp == _dst)) { - dst_y = section.src_h; + dst_y = src_h; } vk::copy_scaled_image(cmd, tmp->value, _dst->value, tmp->current_layout, _dst->current_layout, - areai{ 0, 0, section.src_w, (s32)section.src_h }, + areai{ 0, 0, src_w, (s32)src_h }, coordi{ { dst_x, dst_y }, { section.dst_w, section.dst_h } }, 1, new_src_aspect, tmp->info.format == _dst->info.format, VK_FILTER_NEAREST, tmp->info.format, _dst->info.format); diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index 85f21e618d..e1a4712e26 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -80,23 +80,18 @@ namespace rsx u32 address = 0; u32 pitch = 0; - bool is_depth_surface = false; - rsx::surface_color_format color_format; rsx::surface_depth_format depth_format; u16 width = 0; u16 height = 0; u8 bpp = 0; + u8 samples = 0; address_range range{}; gcm_framebuffer_info() = default; - gcm_framebuffer_info(const u32 address_, const u32 pitch_, bool is_depth_, const rsx::surface_color_format fmt_, const rsx::surface_depth_format dfmt_, const u16 w, const u16 h, const u8 bpp_) - :address(address_), pitch(pitch_), is_depth_surface(is_depth_), color_format(fmt_), depth_format(dfmt_), width(w), height(h), bpp(bpp_) - {} - void calculate_memory_range(u32 aa_factor_u, u32 aa_factor_v) { // Account for the last line of the block not reaching the end @@ -587,33 +582,9 @@ namespace rsx u16 dst_w = src_w; u16 dst_h = src_h; - switch (static_cast(surface->old_contents.source)->read_aa_mode) - { - case rsx::surface_antialiasing::center_1_sample: - break; - case rsx::surface_antialiasing::diagonal_centered_2_samples: - dst_w *= 2; - break; - case rsx::surface_antialiasing::square_centered_4_samples: - case rsx::surface_antialiasing::square_rotated_4_samples: - dst_w *= 2; - dst_h *= 2; - break; - } - - switch (surface->write_aa_mode) - { - case rsx::surface_antialiasing::center_1_sample: - break; - case rsx::surface_antialiasing::diagonal_centered_2_samples: - dst_w /= 2; - break; - case rsx::surface_antialiasing::square_centered_4_samples: - case rsx::surface_antialiasing::square_rotated_4_samples: - dst_w /= 2; - dst_h /= 2; - break; - } + auto src = static_cast(surface->old_contents.source); + dst_w = (dst_w * src->samples_x) / surface->samples_x; + dst_h = (dst_h * src->samples_y) / surface->samples_y; const f32 scale_x = (f32)dst_w / src_w; const f32 scale_y = (f32)dst_h / src_h; diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 3072ecf4bb..eba0b0ce61 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -547,6 +547,7 @@ + @@ -617,4 +618,4 @@ - + \ No newline at end of file diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 8bb96617f0..e1541288ee 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1519,5 +1519,8 @@ Emu\Audio\Null + + Emu\GPU\RSX\Common + - + \ No newline at end of file