mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-03 05:21:25 +12:00
rsx: Remove surface aa_mode hacks
This commit is contained in:
parent
ac3982d2b0
commit
0d906d6974
17 changed files with 644 additions and 809 deletions
|
@ -1,4 +1,6 @@
|
||||||
#include "types.h"
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
#include "StrFmt.h"
|
#include "StrFmt.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -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
|
// We use index access because we might have to push_back within the loop, which could invalidate the iterators
|
||||||
size_type _size = data.size();
|
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];
|
address_range &existing = data[n];
|
||||||
|
|
||||||
|
@ -453,7 +455,7 @@ namespace utils
|
||||||
{
|
{
|
||||||
size_t _size = data.size();
|
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];
|
const auto &r1 = data[i];
|
||||||
if (!r1.valid())
|
if (!r1.valid())
|
||||||
|
@ -461,7 +463,7 @@ namespace utils
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = i + 1; j < _size; ++j)
|
for (size_t j = i + 1; j < _size; ++j)
|
||||||
{
|
{
|
||||||
const auto &r2 = data[j];
|
const auto &r2 = data[j];
|
||||||
if (!r2.valid())
|
if (!r2.valid())
|
||||||
|
|
|
@ -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
|
* Returns number of texel lines decoded in one pitch-length number of bytes
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -28,6 +28,19 @@ namespace rsx
|
||||||
storage = 2,
|
storage = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum surface_metrics : u32
|
||||||
|
{
|
||||||
|
pixels = 0,
|
||||||
|
samples = 1,
|
||||||
|
bytes = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum surface_access : u32
|
||||||
|
{
|
||||||
|
read = 0,
|
||||||
|
write = 1
|
||||||
|
};
|
||||||
|
|
||||||
//Sampled image descriptor
|
//Sampled image descriptor
|
||||||
struct sampled_image_descriptor_base
|
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_texel(int format);
|
||||||
u8 get_format_block_size_in_bytes(rsx::surface_color_format 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
|
* Returns number of texel rows encoded in one pitch-length line of bytes
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "Utilities/GSL.h"
|
#include "Utilities/GSL.h"
|
||||||
#include "Emu/Memory/vm.h"
|
#include "Emu/Memory/vm.h"
|
||||||
#include "TextureUtils.h"
|
#include "surface_utils.h"
|
||||||
#include "../GCM.h"
|
#include "../GCM.h"
|
||||||
#include "../rsx_utils.h"
|
#include "../rsx_utils.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -25,379 +25,6 @@ namespace rsx
|
||||||
size_t get_packed_pitch(surface_color_format format, u32 width);
|
size_t get_packed_pitch(surface_color_format format, u32 width);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum surface_state_flags : u32
|
|
||||||
{
|
|
||||||
ready = 0,
|
|
||||||
erase_bkgnd = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename surface_type>
|
|
||||||
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 <typename surface_type>
|
|
||||||
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 <typename T>
|
|
||||||
deferred_clipped_region<T> cast() const
|
|
||||||
{
|
|
||||||
deferred_clipped_region<T> 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 <typename T>
|
|
||||||
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 <typename image_storage_type>
|
|
||||||
struct render_target_descriptor
|
|
||||||
{
|
|
||||||
u64 last_use_tag = 0; // tag indicating when this block was last confirmed to have been written to
|
|
||||||
std::array<std::pair<u32, u64>, 5> memory_tag_samples;
|
|
||||||
|
|
||||||
deferred_clipped_region<image_storage_type> 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<u64*>(vm::g_sudo_addr + tag.first))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_rw_barrier()
|
|
||||||
{
|
|
||||||
release_ref(old_contents.source);
|
|
||||||
old_contents = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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<typename T>
|
|
||||||
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<decltype(region.source)>(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<image_storage_type>();
|
|
||||||
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<u64*>(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.
|
* Helper for surface (ie color and depth stencil render target) management.
|
||||||
* It handles surface creation and storage. Backend should only retrieve pointer to surface.
|
* It handles surface creation and storage. Backend should only retrieve pointer to surface.
|
||||||
|
@ -435,7 +62,7 @@ namespace rsx
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
void copy_pitched_src_to_dst(gsl::span<T> dest, gsl::span<const U> src, size_t src_pitch_in_bytes, size_t width, size_t height)
|
void copy_pitched_src_to_dst(gsl::span<T> dest, gsl::span<const U> 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++)
|
for (unsigned col = 0; col < width; col++)
|
||||||
dest[col] = src[col];
|
dest[col] = src[col];
|
||||||
|
@ -548,7 +175,7 @@ namespace rsx
|
||||||
{
|
{
|
||||||
// Split in X
|
// Split in X
|
||||||
const u32 baseaddr = address + _new.width;
|
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<surface_type> copy;
|
deferred_clipped_region<surface_type> copy;
|
||||||
copy.src_x = _new.width / bytes_to_texels_x;
|
copy.src_x = _new.width / bytes_to_texels_x;
|
||||||
|
@ -576,15 +203,15 @@ namespace rsx
|
||||||
{
|
{
|
||||||
// Split in Y
|
// Split in Y
|
||||||
const u32 baseaddr = address + (_new.height * prev_surface->get_rsx_pitch());
|
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<surface_type> copy;
|
deferred_clipped_region<surface_type> copy;
|
||||||
copy.src_x = 0;
|
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_x = 0;
|
||||||
copy.dst_y = 0;
|
copy.dst_y = 0;
|
||||||
copy.width = std::min(_new.width, old.width) / bytes_to_texels_x;
|
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_x = 1.f;
|
||||||
copy.transfer_scale_y = 1.f;
|
copy.transfer_scale_y = 1.f;
|
||||||
copy.target = nullptr;
|
copy.target = nullptr;
|
||||||
|
@ -661,7 +288,6 @@ namespace rsx
|
||||||
if (prev_surface)
|
if (prev_surface)
|
||||||
{
|
{
|
||||||
// Append the previous removed surface to the intersection list
|
// Append the previous removed surface to the intersection list
|
||||||
std::pair<u32, surface_type> e = { address, prev_surface };
|
|
||||||
if constexpr (is_depth_surface)
|
if constexpr (is_depth_surface)
|
||||||
{
|
{
|
||||||
list2.push_back({ address, prev_surface });
|
list2.push_back({ address, prev_surface });
|
||||||
|
@ -873,7 +499,7 @@ namespace rsx
|
||||||
|
|
||||||
#ifndef INCOMPLETE_SURFACE_CACHE_IMPL
|
#ifndef INCOMPLETE_SURFACE_CACHE_IMPL
|
||||||
// TODO: This can be done better after refactoring
|
// 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
|
// Check if old_surface is 'new' and avoid intersection
|
||||||
if (old_surface && old_surface->last_use_tag >= write_tag)
|
if (old_surface && old_surface->last_use_tag >= write_tag)
|
||||||
|
@ -1005,7 +631,7 @@ namespace rsx
|
||||||
|
|
||||||
#ifndef INCOMPLETE_SURFACE_CACHE_IMPL
|
#ifndef INCOMPLETE_SURFACE_CACHE_IMPL
|
||||||
// TODO: Forward this to the management functions
|
// 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
|
// Check if old_surface is 'new' and avoid intersection
|
||||||
if (old_surface && old_surface->last_use_tag >= write_tag)
|
if (old_surface && old_surface->last_use_tag >= write_tag)
|
||||||
|
@ -1044,8 +670,6 @@ namespace rsx
|
||||||
{
|
{
|
||||||
u32 clip_width = clip_horizontal_reg;
|
u32 clip_width = clip_horizontal_reg;
|
||||||
u32 clip_height = clip_vertical_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();
|
cache_tag = rsx::get_shared_tag();
|
||||||
|
|
||||||
|
@ -1267,50 +891,6 @@ namespace rsx
|
||||||
return result;
|
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
|
* Invalidates surface that exists at an address
|
||||||
*/
|
*/
|
||||||
|
@ -1383,10 +963,7 @@ namespace rsx
|
||||||
if (!rsx::pitch_compatible(surface, required_pitch, required_height))
|
if (!rsx::pitch_compatible(surface, required_pitch, required_height))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const u16 scale_x = surface->read_aa_mode > rsx::surface_antialiasing::center_1_sample? 2 : 1;
|
const auto texture_size = pitch * surface->get_surface_height(rsx::surface_metrics::samples);
|
||||||
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;
|
|
||||||
|
|
||||||
if ((this_address + texture_size) <= texaddr)
|
if ((this_address + texture_size) <= texaddr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1401,11 +978,8 @@ namespace rsx
|
||||||
info.base_address = this_address;
|
info.base_address = this_address;
|
||||||
info.is_depth = is_depth;
|
info.is_depth = is_depth;
|
||||||
|
|
||||||
surface_format_info surface_info{};
|
const auto normalized_surface_width = surface->get_native_pitch() / required_bpp;
|
||||||
Traits::get_surface_info(surface, &surface_info);
|
const auto normalized_surface_height = surface->get_surface_height(rsx::surface_metrics::samples);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (LIKELY(this_address >= texaddr))
|
if (LIKELY(this_address >= texaddr))
|
||||||
{
|
{
|
||||||
|
@ -1445,21 +1019,11 @@ namespace rsx
|
||||||
|
|
||||||
info.is_clipped = (info.width < required_width || info.height < required_height);
|
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
|
// Width is calculated in the coordinate-space of the requester; normalize
|
||||||
info.src_x = (info.src_x * required_bpp) / surface_info.bpp;
|
info.src_x = (info.src_x * required_bpp) / surface_bpp;
|
||||||
info.width = (info.width * required_bpp) / surface_info.bpp;
|
info.width = (info.width * required_bpp) / surface_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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push_back(info);
|
result.push_back(info);
|
||||||
|
|
450
rpcs3/Emu/RSX/Common/surface_utils.h
Normal file
450
rpcs3/Emu/RSX/Common/surface_utils.h
Normal file
|
@ -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 <typename surface_type>
|
||||||
|
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 <typename surface_type>
|
||||||
|
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 <typename T>
|
||||||
|
deferred_clipped_region<T> cast() const
|
||||||
|
{
|
||||||
|
deferred_clipped_region<T> 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 <typename T>
|
||||||
|
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 <typename image_storage_type>
|
||||||
|
struct render_target_descriptor
|
||||||
|
{
|
||||||
|
u64 last_use_tag = 0; // tag indicating when this block was last confirmed to have been written to
|
||||||
|
std::array<std::pair<u32, u64>, 5> memory_tag_samples;
|
||||||
|
|
||||||
|
// Obsolete, requires updating
|
||||||
|
deferred_clipped_region<image_storage_type> 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<u64*>(vm::g_sudo_addr + tag.first))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_rw_barrier()
|
||||||
|
{
|
||||||
|
release_ref(old_contents.source);
|
||||||
|
old_contents = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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<typename T>
|
||||||
|
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<decltype(region.source)>(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<image_storage_type>();
|
||||||
|
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<u64*>(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 <typename T>
|
||||||
|
void transform_samples_to_pixels(area_base<T>& area)
|
||||||
|
{
|
||||||
|
if (LIKELY(spp == 1)) return;
|
||||||
|
|
||||||
|
area.x1 /= samples_x;
|
||||||
|
area.x2 /= samples_x;
|
||||||
|
area.y1 /= samples_y;
|
||||||
|
area.y2 /= samples_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -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 <typename T, typename U>
|
|
||||||
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 <typename T, typename U>
|
|
||||||
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 <typename T>
|
|
||||||
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 <typename T>
|
|
||||||
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:
|
public:
|
||||||
|
|
||||||
texture_cache() : m_storage(this), m_predictor(this) {}
|
texture_cache() : m_storage(this), m_predictor(this) {}
|
||||||
|
@ -1700,37 +1626,15 @@ namespace rsx
|
||||||
verify(HERE), dst_y >= slice_begin;
|
verify(HERE), dst_y >= slice_begin;
|
||||||
dst_y = (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;
|
const auto h = std::min(section_end, slice_end) - section.dst_y;
|
||||||
auto src_width = rsx::apply_resolution_scale(section.width, true);
|
const auto src_width = rsx::apply_resolution_scale(section.width, true);
|
||||||
auto src_height = rsx::apply_resolution_scale(h, true);
|
const auto src_height = rsx::apply_resolution_scale(h, true);
|
||||||
auto dst_width = u16(src_width * scale_x);
|
const auto dst_width = src_width;
|
||||||
auto dst_height = u16(src_height * scale_y);
|
const auto dst_height = src_height;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
surfaces.push_back
|
surfaces.push_back
|
||||||
({
|
({
|
||||||
section.surface->get_surface(),
|
section.surface->get_surface(rsx::surface_access::read),
|
||||||
surface_transform::identity,
|
surface_transform::identity,
|
||||||
rsx::apply_resolution_scale(src_x, true),
|
rsx::apply_resolution_scale(src_x, true),
|
||||||
rsx::apply_resolution_scale(src_y, true),
|
rsx::apply_resolution_scale(src_y, true),
|
||||||
|
@ -1894,23 +1798,19 @@ namespace rsx
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto surface_width = texptr->get_surface_width();
|
const auto surface_width = texptr->get_surface_width(rsx::surface_metrics::samples);
|
||||||
const auto surface_height = texptr->get_surface_height();
|
const auto surface_height = texptr->get_surface_height(rsx::surface_metrics::samples);
|
||||||
|
|
||||||
u32 internal_width = tex_width;
|
|
||||||
u32 internal_height = tex_height;
|
|
||||||
get_native_dimensions(internal_width, internal_height, texptr);
|
|
||||||
|
|
||||||
switch (extended_dimension)
|
switch (extended_dimension)
|
||||||
{
|
{
|
||||||
case rsx::texture_dimension_extended::texture_dimension_1d:
|
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:
|
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:
|
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:
|
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;
|
return false;
|
||||||
|
@ -1927,12 +1827,8 @@ namespace rsx
|
||||||
{
|
{
|
||||||
texptr->read_barrier(cmd);
|
texptr->read_barrier(cmd);
|
||||||
|
|
||||||
const auto surface_width = texptr->get_surface_width();
|
const auto surface_width = texptr->get_surface_width(rsx::surface_metrics::samples);
|
||||||
const auto surface_height = texptr->get_surface_height();
|
const auto surface_height = texptr->get_surface_height(rsx::surface_metrics::samples);
|
||||||
|
|
||||||
u32 internal_width = tex_width;
|
|
||||||
u32 internal_height = tex_height;
|
|
||||||
get_native_dimensions(internal_width, internal_height, texptr);
|
|
||||||
|
|
||||||
bool is_depth = texptr->is_depth_surface();
|
bool is_depth = texptr->is_depth_surface();
|
||||||
const bool force_convert = !render_target_format_is_compatible(texptr, format);
|
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)
|
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) ||
|
if ((surface_is_rop_target && g_cfg.video.strict_rendering_mode) ||
|
||||||
internal_width < surface_width ||
|
tex_width < surface_width ||
|
||||||
internal_height < surface_height ||
|
tex_height < surface_height ||
|
||||||
force_convert)
|
force_convert)
|
||||||
{
|
{
|
||||||
const auto scaled_w = rsx::apply_resolution_scale(internal_width, true);
|
const auto scaled_w = rsx::apply_resolution_scale(tex_width, true);
|
||||||
const auto scaled_h = rsx::apply_resolution_scale(internal_height, 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;
|
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,
|
texture_upload_context::framebuffer_storage, is_depth, scale_x, scale_y,
|
||||||
extended_dimension, decoded_remap };
|
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 };
|
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_w = rsx::apply_resolution_scale(tex_width, true);
|
||||||
const auto scaled_h = rsx::apply_resolution_scale(internal_height, true);
|
const auto scaled_h = rsx::apply_resolution_scale(tex_height, true);
|
||||||
|
|
||||||
if (extended_dimension == rsx::texture_dimension_extended::texture_dimension_3d)
|
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,
|
scaled_w, scaled_h, tex_depth,
|
||||||
texture_upload_context::framebuffer_storage, is_depth, 1.f, 1.f,
|
texture_upload_context::framebuffer_storage, is_depth, 1.f, 1.f,
|
||||||
rsx::texture_dimension_extended::texture_dimension_3d, decoded_remap };
|
rsx::texture_dimension_extended::texture_dimension_3d, decoded_remap };
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(HERE), extended_dimension == rsx::texture_dimension_extended::texture_dimension_cubemap;
|
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,
|
scaled_w, scaled_h, 1,
|
||||||
texture_upload_context::framebuffer_storage, is_depth, 1.f, 1.f,
|
texture_upload_context::framebuffer_storage, is_depth, 1.f, 1.f,
|
||||||
rsx::texture_dimension_extended::texture_dimension_cubemap, decoded_remap };
|
rsx::texture_dimension_extended::texture_dimension_cubemap, decoded_remap };
|
||||||
|
@ -2218,12 +2114,8 @@ namespace rsx
|
||||||
const auto& last = overlapping_fbos.back();
|
const auto& last = overlapping_fbos.back();
|
||||||
if (last.src_x == 0 && last.src_y == 0)
|
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;
|
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,
|
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);
|
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 _w = u32(It->width * It->surface->get_bpp()) / bpp;
|
||||||
auto _h = u32(It->height);
|
auto _h = u32(It->height);
|
||||||
get_rsx_dimensions(_w, _h, It->surface);
|
|
||||||
|
|
||||||
if (_w < width)
|
if (_w < width)
|
||||||
{
|
{
|
||||||
|
@ -2596,9 +2487,9 @@ namespace rsx
|
||||||
size2i dst_dimensions = { dst.pitch / dst_bpp, dst.height };
|
size2i dst_dimensions = { dst.pitch / dst_bpp, dst.height };
|
||||||
if (src_is_render_target)
|
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))
|
else if (LIKELY(dst_dimensions.width == 1280 || dst_dimensions.width == 2560))
|
||||||
{
|
{
|
||||||
|
@ -2673,11 +2564,11 @@ namespace rsx
|
||||||
// Destination dimensions are relaxed (true)
|
// Destination dimensions are relaxed (true)
|
||||||
dst_area = dst_subres.get_src_area();
|
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;
|
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_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();
|
max_dst_height = dst_subres.surface->get_surface_height(rsx::surface_metrics::samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if available target is acceptable
|
// Check if available target is acceptable
|
||||||
|
@ -2824,7 +2715,7 @@ namespace rsx
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
src_area = src_subres.get_src_area();
|
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;
|
typeless_info.src_context = texture_upload_context::framebuffer_storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2969,13 +2860,13 @@ namespace rsx
|
||||||
const f32 resolution_scale = rsx::get_resolution_scale();
|
const f32 resolution_scale = rsx::get_resolution_scale();
|
||||||
if (src_is_render_target)
|
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.x1 = (u16)(src_area.x1 * resolution_scale);
|
||||||
src_area.x2 = (u16)(src_area.x2 * 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.y1 = (u16)(src_area.y1 * resolution_scale);
|
||||||
src_area.y2 = (u16)(src_area.y2 * resolution_scale);
|
src_area.y2 = (u16)(src_area.y2 * resolution_scale);
|
||||||
|
@ -2984,13 +2875,13 @@ namespace rsx
|
||||||
|
|
||||||
if (dst_is_render_target)
|
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.x1 = (u16)(dst_area.x1 * resolution_scale);
|
||||||
dst_area.x2 = (u16)(dst_area.x2 * 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.y1 = (u16)(dst_area.y1 * resolution_scale);
|
||||||
dst_area.y2 = (u16)(dst_area.y2 * 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();
|
typeless_info.analyse();
|
||||||
blitter.scale_image(cmd, vram_texture, dest_texture, src_area, dst_area, interpolate, is_depth_blit, typeless_info);
|
blitter.scale_image(cmd, vram_texture, dest_texture, src_area, dst_area, interpolate, is_depth_blit, typeless_info);
|
||||||
|
|
||||||
|
|
|
@ -1685,7 +1685,7 @@ void GLGSRender::flip(int buffer, bool emu_flip)
|
||||||
// TODO: Take AA scaling into account
|
// 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",
|
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,
|
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_width = render_target_texture->width();
|
||||||
buffer_height = render_target_texture->height();
|
buffer_height = render_target_texture->height();
|
||||||
|
|
|
@ -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
|
// Nothing has changed, we're still using the same framebuffer
|
||||||
// Update flags to match current
|
// 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();
|
m_draw_fbo->bind();
|
||||||
set_viewport();
|
set_viewport();
|
||||||
set_scissor();
|
set_scissor();
|
||||||
|
@ -223,9 +210,6 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
||||||
layout.color_addresses, layout.zeta_address,
|
layout.color_addresses, layout.zeta_address,
|
||||||
layout.actual_color_pitch, layout.actual_zeta_pitch);
|
layout.actual_color_pitch, layout.actual_zeta_pitch);
|
||||||
|
|
||||||
bool old_format_found = false;
|
|
||||||
gl::texture::format old_format;
|
|
||||||
|
|
||||||
std::array<GLuint, 4> color_targets;
|
std::array<GLuint, 4> color_targets;
|
||||||
GLuint depth_stencil_target;
|
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 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 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)
|
for (int i = 0; i < rsx::limits::color_buffers_count; ++i)
|
||||||
{
|
{
|
||||||
if (m_surface_info[i].pitch && g_cfg.video.write_color_buffers)
|
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();
|
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.set_memory_read_flags(surface_range, rsx::memory_read_flags::flush_once);
|
||||||
m_gl_texture_cache.flush_if_cache_miss_likely(cmd, surface_range);
|
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();
|
color_targets[i] = rtt->id();
|
||||||
|
|
||||||
verify("Pitch mismatch!" HERE), rtt->get_rsx_pitch() == layout.actual_color_pitch[i];
|
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 };
|
m_surface_info[i].address = layout.color_addresses[i];
|
||||||
|
m_surface_info[i].pitch = layout.actual_color_pitch[i];
|
||||||
rtt->tile = find_tile(color_offsets[i], color_locations[i]);
|
m_surface_info[i].width = layout.width;
|
||||||
rtt->write_aa_mode = layout.aa_mode;
|
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));
|
m_gl_texture_cache.notify_surface_changed(m_surface_info[i].get_memory_range(layout.aa_factors));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -285,9 +267,14 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
||||||
depth_stencil_target = ds->id();
|
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;
|
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));
|
m_gl_texture_cache.notify_surface_changed(m_depth_surface_info.get_memory_range(layout.aa_factors));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -457,7 +444,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
||||||
|
|
||||||
m_gl_texture_cache.lock_memory_region(
|
m_gl_texture_cache.lock_memory_region(
|
||||||
cmd, surface, surface->get_memory_range(), false,
|
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);
|
format, type, swap_bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,11 +51,6 @@ namespace gl
|
||||||
{
|
{
|
||||||
class render_target : public viewable_image, public rsx::ref_counted, public rsx::render_target_descriptor<texture*>
|
class render_target : public viewable_image, public rsx::ref_counted, public rsx::render_target_descriptor<texture*>
|
||||||
{
|
{
|
||||||
u32 rsx_pitch = 0;
|
|
||||||
u16 native_pitch = 0;
|
|
||||||
|
|
||||||
u16 surface_height = 0;
|
|
||||||
u16 surface_width = 0;
|
|
||||||
u16 surface_pixel_size = 0;
|
u16 surface_pixel_size = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -69,11 +64,6 @@ namespace gl
|
||||||
native_pitch = pitch;
|
native_pitch = pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 get_native_pitch() const override
|
|
||||||
{
|
|
||||||
return native_pitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_surface_dimensions(u16 w, u16 h, u16 pitch)
|
void set_surface_dimensions(u16 w, u16 h, u16 pitch)
|
||||||
{
|
{
|
||||||
surface_width = w;
|
surface_width = w;
|
||||||
|
@ -91,16 +81,6 @@ namespace gl
|
||||||
return rsx_pitch;
|
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
|
bool is_depth_surface() const override
|
||||||
{
|
{
|
||||||
switch (get_internal_format())
|
switch (get_internal_format())
|
||||||
|
@ -119,8 +99,9 @@ namespace gl
|
||||||
static_cast<gl::render_target*>(t)->release();
|
static_cast<gl::render_target*>(t)->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
texture* get_surface() override
|
texture* get_surface(rsx::surface_access access_type) override
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
return (gl::texture*)this;
|
return (gl::texture*)this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,8 +203,8 @@ struct gl_render_target_traits
|
||||||
if (!sink)
|
if (!sink)
|
||||||
{
|
{
|
||||||
auto internal_format = (GLenum)ref->get_internal_format();
|
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_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());
|
const auto new_h = rsx::apply_resolution_scale(prev.height, true, ref->get_surface_height(rsx::surface_metrics::pixels));
|
||||||
|
|
||||||
sink = std::make_unique<gl::render_target>(new_w, new_h, internal_format);
|
sink = std::make_unique<gl::render_target>(new_w, new_h, internal_format);
|
||||||
sink->add_ref();
|
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*/)
|
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() &&
|
return (surface->get_internal_format() == ref->get_internal_format() &&
|
||||||
surface->get_surface_width() >= width &&
|
surface->get_surface_width(rsx::surface_metrics::pixels) >= width &&
|
||||||
surface->get_surface_height() >= height);
|
surface->get_surface_height(rsx::surface_metrics::pixels) >= 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prepare_rtt_for_drawing(gl::command_context&, gl::render_target* rtt)
|
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)
|
void invalidate_surface_contents(gl::command_context&, gl::render_target *surface, u32 address, size_t pitch)
|
||||||
{
|
{
|
||||||
surface->set_rsx_pitch((u16)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->queue_tag(address);
|
||||||
surface->last_use_tag = 0;
|
surface->last_use_tag = 0;
|
||||||
surface->memory_usage_flags = rsx::surface_usage_flags::unknown;
|
surface->memory_usage_flags = rsx::surface_usage_flags::unknown;
|
||||||
|
@ -310,9 +281,7 @@ struct gl_render_target_traits
|
||||||
|
|
||||||
static
|
static
|
||||||
void notify_surface_persist(const std::unique_ptr<gl::render_target>& surface)
|
void notify_surface_persist(const std::unique_ptr<gl::render_target>& surface)
|
||||||
{
|
{}
|
||||||
surface->save_aa_mode();
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
void notify_surface_reused(const std::unique_ptr<gl::render_target>& surface)
|
void notify_surface_reused(const std::unique_ptr<gl::render_target>& surface)
|
||||||
|
|
|
@ -245,18 +245,9 @@ namespace gl
|
||||||
|
|
||||||
if (context == rsx::texture_upload_context::framebuffer_storage)
|
if (context == rsx::texture_upload_context::framebuffer_storage)
|
||||||
{
|
{
|
||||||
switch (static_cast<gl::render_target*>(vram_texture)->read_aa_mode)
|
auto surface = gl::as_rtt(vram_texture);
|
||||||
{
|
real_width *= surface->samples_x;
|
||||||
case rsx::surface_antialiasing::center_1_sample:
|
real_height *= surface->samples_y;
|
||||||
break;
|
|
||||||
case rsx::surface_antialiasing::diagonal_centered_2_samples:
|
|
||||||
real_width *= 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
real_width *= 2;
|
|
||||||
real_height *= 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
areai src_area = { 0, 0, 0, 0 };
|
areai src_area = { 0, 0, 0, 0 };
|
||||||
|
@ -628,9 +619,17 @@ namespace gl
|
||||||
const bool typeless = dst_aspect != slice.src->aspect() ||
|
const bool typeless = dst_aspect != slice.src->aspect() ||
|
||||||
!formats_are_bitcast_compatible((GLenum)slice.src->get_internal_format(), (GLenum)dst_image->get_internal_format());
|
!formats_are_bitcast_compatible((GLenum)slice.src->get_internal_format(), (GLenum)dst_image->get_internal_format());
|
||||||
|
|
||||||
|
std::unique_ptr<gl::texture> tmp;
|
||||||
auto src_image = slice.src;
|
auto src_image = slice.src;
|
||||||
auto src_x = slice.src_x;
|
auto src_x = slice.src_x;
|
||||||
std::unique_ptr<gl::texture> tmp;
|
auto src_y = slice.src_y;
|
||||||
|
auto src_w = slice.src_w;
|
||||||
|
auto src_h = slice.src_h;
|
||||||
|
|
||||||
|
if (auto surface = dynamic_cast<gl::render_target*>(slice.src))
|
||||||
|
{
|
||||||
|
surface->transform_samples_to_pixels(src_x, src_y, src_w, src_h);
|
||||||
|
}
|
||||||
|
|
||||||
if (UNLIKELY(typeless))
|
if (UNLIKELY(typeless))
|
||||||
{
|
{
|
||||||
|
@ -643,17 +642,17 @@ namespace gl
|
||||||
gl::copy_typeless(src_image, slice.src);
|
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,
|
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, slice.src_w, slice.src_h, 1);
|
dst_image->id(), (GLenum)dst_image->get_target(), 0, slice.dst_x, slice.dst_y, slice.dst_z, src_w, src_h, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
verify(HERE), dst_image->get_target() == gl::texture::target::texture2D;
|
verify(HERE), dst_image->get_target() == gl::texture::target::texture2D;
|
||||||
|
|
||||||
auto _blitter = gl::g_hw_blitter;
|
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 };
|
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;
|
auto _dst = dst_image;
|
||||||
|
|
|
@ -1033,6 +1033,7 @@ namespace rsx
|
||||||
const auto aa_mode = rsx::method_registers.surface_antialias();
|
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_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 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 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;
|
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 (layout.color_addresses[i])
|
||||||
{
|
{
|
||||||
if (m_surface_info[i].width != layout.width ||
|
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;
|
really_changed = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1223,7 +1225,8 @@ namespace rsx
|
||||||
|
|
||||||
if (!really_changed)
|
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
|
// Same target is reused
|
||||||
return layout;
|
return layout;
|
||||||
|
|
|
@ -2725,22 +2725,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
||||||
{
|
{
|
||||||
// Nothing has changed, we're still using the same framebuffer
|
// Nothing has changed, we're still using the same framebuffer
|
||||||
// Update flags to match current
|
// Update flags to match current
|
||||||
|
set_scissor();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2755,6 +2740,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
||||||
// Reset framebuffer information
|
// Reset framebuffer information
|
||||||
VkFormat old_format = VK_FORMAT_UNDEFINED;
|
VkFormat old_format = VK_FORMAT_UNDEFINED;
|
||||||
const auto color_bpp = get_format_block_size_in_bytes(layout.color_format);
|
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)
|
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].height = layout.height;
|
||||||
m_surface_info[i].color_format = layout.color_format;
|
m_surface_info[i].color_format = layout.color_format;
|
||||||
m_surface_info[i].bpp = color_bpp;
|
m_surface_info[i].bpp = color_bpp;
|
||||||
|
m_surface_info[i].samples = samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Process depth surface as well
|
//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.height = layout.height;
|
||||||
m_depth_surface_info.depth_format = layout.depth_format;
|
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.bpp = (layout.depth_format == rsx::surface_depth_format::z16? 2 : 4);
|
||||||
|
m_depth_surface_info.samples = samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Bind created rtts as current fbo...
|
//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];
|
m_surface_info[index].pitch = layout.actual_color_pitch[index];
|
||||||
verify("Pitch mismatch!" HERE), surface->rsx_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_texture_cache.notify_surface_changed(m_surface_info[index].get_memory_range(layout.aa_factors));
|
||||||
m_draw_buffers.push_back(index);
|
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;
|
m_depth_surface_info.pitch = layout.actual_zeta_pitch;
|
||||||
verify("Pitch mismatch!" HERE), ds->rsx_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));
|
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_texture_cache.lock_memory_region(
|
||||||
*m_current_command_buffer, surface, surface->get_memory_range(), false,
|
*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);
|
gcm_format, swap_bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3184,7 +3170,7 @@ void VKGSRender::flip(int buffer, bool emu_flip)
|
||||||
// TODO: Take AA scaling into account
|
// 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",
|
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,
|
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_width = render_target_texture->width();
|
||||||
buffer_height = render_target_texture->height();
|
buffer_height = render_target_texture->height();
|
||||||
|
|
|
@ -13,41 +13,16 @@ namespace vk
|
||||||
{
|
{
|
||||||
struct render_target : public viewable_image, public rsx::ref_counted, public rsx::render_target_descriptor<vk::viewable_image*>
|
struct render_target : public viewable_image, public rsx::ref_counted, public rsx::render_target_descriptor<vk::viewable_image*>
|
||||||
{
|
{
|
||||||
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
|
u64 frame_tag = 0; // frame id when invalidated, 0 if not invalid
|
||||||
|
|
||||||
using viewable_image::viewable_image;
|
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;
|
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
|
bool is_depth_surface() const override
|
||||||
{
|
{
|
||||||
return !!(aspect() & VK_IMAGE_ASPECT_DEPTH_BIT);
|
return !!(aspect() & VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||||
|
@ -273,8 +248,8 @@ namespace rsx
|
||||||
{
|
{
|
||||||
if (!sink)
|
if (!sink)
|
||||||
{
|
{
|
||||||
const auto new_w = rsx::apply_resolution_scale(prev.width, true, ref->get_surface_width());
|
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());
|
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();
|
auto& dev = cmd.get_command_pool().get_owner();
|
||||||
sink = std::make_unique<vk::render_target>(dev, dev.get_memory_mapping().device_local,
|
sink = std::make_unique<vk::render_target>(dev, dev.get_memory_mapping().device_local,
|
||||||
|
@ -282,7 +257,7 @@ namespace rsx
|
||||||
VK_IMAGE_TYPE_2D,
|
VK_IMAGE_TYPE_2D,
|
||||||
ref->format(),
|
ref->format(),
|
||||||
new_w, new_h, 1, 1, 1,
|
new_w, new_h, 1, 1, 1,
|
||||||
VK_SAMPLE_COUNT_1_BIT,
|
(VkSampleCountFlagBits)ref->samples(),
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
VK_IMAGE_TILING_OPTIMAL,
|
VK_IMAGE_TILING_OPTIMAL,
|
||||||
ref->info.usage,
|
ref->info.usage,
|
||||||
|
@ -316,15 +291,6 @@ namespace rsx
|
||||||
surface->get_surface_height() >= height);
|
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)
|
static void prepare_rtt_for_drawing(vk::command_buffer& cmd, vk::render_target *surface)
|
||||||
{
|
{
|
||||||
surface->change_layout(cmd, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
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)
|
static void invalidate_surface_contents(vk::command_buffer& /*cmd*/, vk::render_target *surface, u32 address, size_t pitch)
|
||||||
{
|
{
|
||||||
surface->rsx_pitch = (u16)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->queue_tag(address);
|
||||||
surface->last_use_tag = 0;
|
surface->last_use_tag = 0;
|
||||||
surface->memory_usage_flags = rsx::surface_usage_flags::unknown;
|
surface->memory_usage_flags = rsx::surface_usage_flags::unknown;
|
||||||
|
@ -378,9 +344,7 @@ namespace rsx
|
||||||
}
|
}
|
||||||
|
|
||||||
static void notify_surface_persist(const std::unique_ptr<vk::render_target> &surface)
|
static void notify_surface_persist(const std::unique_ptr<vk::render_target> &surface)
|
||||||
{
|
{}
|
||||||
surface->save_aa_mode();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void notify_surface_reused(const std::unique_ptr<vk::render_target> &surface)
|
static void notify_surface_reused(const std::unique_ptr<vk::render_target> &surface)
|
||||||
{
|
{
|
||||||
|
|
|
@ -211,18 +211,9 @@ namespace vk
|
||||||
{
|
{
|
||||||
if (context == rsx::texture_upload_context::framebuffer_storage)
|
if (context == rsx::texture_upload_context::framebuffer_storage)
|
||||||
{
|
{
|
||||||
switch (static_cast<vk::render_target*>(vram_texture)->read_aa_mode)
|
auto surface = vk::as_rtt(vram_texture);
|
||||||
{
|
transfer_width *= surface->samples_x;
|
||||||
case rsx::surface_antialiasing::center_1_sample:
|
transfer_height *= surface->samples_y;
|
||||||
break;
|
|
||||||
case rsx::surface_antialiasing::diagonal_centered_2_samples:
|
|
||||||
transfer_width *= 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
transfer_width *= 2;
|
|
||||||
transfer_height *= 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transfer_width != vram_texture->width() || transfer_height != vram_texture->height())
|
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);
|
section.src->push_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
|
|
||||||
auto src_image = section.src;
|
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<vk::render_target*>(section.src))
|
||||||
|
{
|
||||||
|
surface->transform_samples_to_pixels(src_x, src_y, src_w, src_h);
|
||||||
|
}
|
||||||
|
|
||||||
if (UNLIKELY(typeless))
|
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);
|
src_image->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
const auto src_bpp = vk::get_format_texel_width(section.src->format());
|
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 u16 convert_w = u16(src_w * dst_bpp) / src_bpp;
|
||||||
const areai src_rect = coordi{{ section.src_x, section.src_y }, { convert_w, section.src_h }};
|
const areai src_rect = coordi{{ src_x, src_y }, { convert_w, src_h }};
|
||||||
const areai dst_rect = coordi{{ section.src_x, section.src_y }, { section.src_w, section.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);
|
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);
|
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
|
// Final aspect mask of the 'final' transfer source
|
||||||
const auto new_src_aspect = src_image->aspect();
|
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;
|
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.dstOffset = { section.dst_x, section.dst_y, 0 };
|
||||||
copy_rgn.dstSubresource = { dst_aspect, 0, 0, 1 };
|
copy_rgn.dstSubresource = { dst_aspect, 0, 0, 1 };
|
||||||
copy_rgn.srcSubresource = { new_src_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)
|
if (dst->info.imageType == VK_IMAGE_TYPE_3D)
|
||||||
{
|
{
|
||||||
|
@ -572,7 +573,7 @@ namespace vk
|
||||||
if (section.xform == surface_transform::identity)
|
if (section.xform == surface_transform::identity)
|
||||||
{
|
{
|
||||||
vk::copy_scaled_image(cmd, src_image->value, _dst->value, section.src->current_layout, _dst->current_layout,
|
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 } },
|
coordi{ { section.dst_x, section.dst_y }, { section.dst_w, section.dst_h } },
|
||||||
1, src_image->aspect(), src_image->info.format == _dst->info.format,
|
1, src_image->aspect(), src_image->info.format == _dst->info.format,
|
||||||
VK_FILTER_NEAREST, 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)
|
else if (section.xform == surface_transform::argb_to_bgra)
|
||||||
{
|
{
|
||||||
VkBufferImageCopy copy{};
|
VkBufferImageCopy copy{};
|
||||||
copy.imageExtent = { section.src_w, section.src_h, 1 };
|
copy.imageExtent = { src_w, src_h, 1 };
|
||||||
copy.imageOffset = { section.src_x, section.src_y, 0 };
|
copy.imageOffset = { src_x, src_y, 0 };
|
||||||
copy.imageSubresource = { src_image->aspect(), 0, 0, 1 };
|
copy.imageSubresource = { src_image->aspect(), 0, 0, 1 };
|
||||||
|
|
||||||
auto scratch_buf = vk::get_scratch_buffer();
|
auto scratch_buf = vk::get_scratch_buffer();
|
||||||
vkCmdCopyImageToBuffer(cmd, src_image->value, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, scratch_buf->value, 1, ©);
|
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::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);
|
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
|
||||||
|
|
||||||
|
@ -606,16 +607,16 @@ namespace vk
|
||||||
dst_x = 0;
|
dst_x = 0;
|
||||||
dst_y = 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
|
// Optionally scale if needed
|
||||||
if (UNLIKELY(tmp == _dst))
|
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,
|
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 } },
|
coordi{ { dst_x, dst_y }, { section.dst_w, section.dst_h } },
|
||||||
1, new_src_aspect, tmp->info.format == _dst->info.format,
|
1, new_src_aspect, tmp->info.format == _dst->info.format,
|
||||||
VK_FILTER_NEAREST, tmp->info.format, _dst->info.format);
|
VK_FILTER_NEAREST, tmp->info.format, _dst->info.format);
|
||||||
|
|
|
@ -80,23 +80,18 @@ namespace rsx
|
||||||
u32 address = 0;
|
u32 address = 0;
|
||||||
u32 pitch = 0;
|
u32 pitch = 0;
|
||||||
|
|
||||||
bool is_depth_surface = false;
|
|
||||||
|
|
||||||
rsx::surface_color_format color_format;
|
rsx::surface_color_format color_format;
|
||||||
rsx::surface_depth_format depth_format;
|
rsx::surface_depth_format depth_format;
|
||||||
|
|
||||||
u16 width = 0;
|
u16 width = 0;
|
||||||
u16 height = 0;
|
u16 height = 0;
|
||||||
u8 bpp = 0;
|
u8 bpp = 0;
|
||||||
|
u8 samples = 0;
|
||||||
|
|
||||||
address_range range{};
|
address_range range{};
|
||||||
|
|
||||||
gcm_framebuffer_info() = default;
|
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)
|
void calculate_memory_range(u32 aa_factor_u, u32 aa_factor_v)
|
||||||
{
|
{
|
||||||
// Account for the last line of the block not reaching the end
|
// 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_w = src_w;
|
||||||
u16 dst_h = src_h;
|
u16 dst_h = src_h;
|
||||||
|
|
||||||
switch (static_cast<const SurfaceType*>(surface->old_contents.source)->read_aa_mode)
|
auto src = static_cast<const SurfaceType*>(surface->old_contents.source);
|
||||||
{
|
dst_w = (dst_w * src->samples_x) / surface->samples_x;
|
||||||
case rsx::surface_antialiasing::center_1_sample:
|
dst_h = (dst_h * src->samples_y) / surface->samples_y;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
const f32 scale_x = (f32)dst_w / src_w;
|
const f32 scale_x = (f32)dst_w / src_w;
|
||||||
const f32 scale_y = (f32)dst_h / src_h;
|
const f32 scale_y = (f32)dst_h / src_h;
|
||||||
|
|
|
@ -547,6 +547,7 @@
|
||||||
<ClInclude Include="Emu\RSX\Capture\rsx_replay.h" />
|
<ClInclude Include="Emu\RSX\Capture\rsx_replay.h" />
|
||||||
<ClInclude Include="Emu\RSX\Capture\rsx_trace.h" />
|
<ClInclude Include="Emu\RSX\Capture\rsx_trace.h" />
|
||||||
<ClInclude Include="Emu\RSX\Common\GLSLCommon.h" />
|
<ClInclude Include="Emu\RSX\Common\GLSLCommon.h" />
|
||||||
|
<ClInclude Include="Emu\RSX\Common\surface_utils.h" />
|
||||||
<ClInclude Include="Emu\RSX\Common\TextGlyphs.h" />
|
<ClInclude Include="Emu\RSX\Common\TextGlyphs.h" />
|
||||||
<ClInclude Include="Emu\RSX\Common\texture_cache.h" />
|
<ClInclude Include="Emu\RSX\Common\texture_cache.h" />
|
||||||
<ClInclude Include="Emu\RSX\Common\texture_cache_checker.h" />
|
<ClInclude Include="Emu\RSX\Common\texture_cache_checker.h" />
|
||||||
|
@ -617,4 +618,4 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -1519,5 +1519,8 @@
|
||||||
<ClInclude Include="Emu\Audio\Null\NullAudioBackend.h">
|
<ClInclude Include="Emu\Audio\Null\NullAudioBackend.h">
|
||||||
<Filter>Emu\Audio\Null</Filter>
|
<Filter>Emu\Audio\Null</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\RSX\Common\surface_utils.h">
|
||||||
|
<Filter>Emu\GPU\RSX\Common</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Add table
Add a link
Reference in a new issue