mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 20:15:27 +00:00
rsx: Preserve read AA state separate from write AA state
- Some applications (e.g Backbreaker) use an evil hack to resolve MSAA. The application respecifies a formerly AA region as a region with no AA then performs a framebuffer feedback lookup. The old memory keeps AA during read, but writes back to itself with AA resolved. This is evil on several levels but it just happens to work on PS3
This commit is contained in:
parent
0f24379c0e
commit
3150619320
11 changed files with 115 additions and 107 deletions
|
@ -61,14 +61,36 @@ namespace rsx
|
|||
template <typename image_storage_type>
|
||||
struct render_target_descriptor
|
||||
{
|
||||
bool dirty = false;
|
||||
image_storage_type old_contents = nullptr;
|
||||
rsx::surface_antialiasing read_aa_mode = rsx::surface_antialiasing::center_1_sample;
|
||||
|
||||
GcmTileInfo *tile = nullptr;
|
||||
rsx::surface_antialiasing aa_mode = rsx::surface_antialiasing::center_1_sample;
|
||||
rsx::surface_antialiasing write_aa_mode = rsx::surface_antialiasing::center_1_sample;
|
||||
|
||||
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;
|
||||
|
||||
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 on_write()
|
||||
{
|
||||
read_aa_mode = write_aa_mode;
|
||||
dirty = false;
|
||||
old_contents = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -134,6 +156,7 @@ namespace rsx
|
|||
|
||||
std::list<surface_storage_type> invalidated_resources;
|
||||
u64 cache_tag = 0ull;
|
||||
u64 write_tag = 0ull;
|
||||
|
||||
surface_store() = default;
|
||||
~surface_store() = default;
|
||||
|
@ -175,6 +198,7 @@ namespace rsx
|
|||
surface_storage_type &rtt = It->second;
|
||||
if (Traits::rtt_has_format_width_height(rtt, color_format, width, height))
|
||||
{
|
||||
Traits::notify_surface_persist(rtt);
|
||||
Traits::prepare_rtt_for_drawing(command_list, Traits::get(rtt));
|
||||
return Traits::get(rtt);
|
||||
}
|
||||
|
@ -206,7 +230,7 @@ namespace rsx
|
|||
invalidated_resources.erase(It);
|
||||
|
||||
new_surface = Traits::get(new_surface_storage);
|
||||
Traits::invalidate_rtt_surface_contents(command_list, new_surface, contents_to_copy, true);
|
||||
Traits::invalidate_surface_contents(command_list, new_surface, contents_to_copy);
|
||||
Traits::prepare_rtt_for_drawing(command_list, new_surface);
|
||||
break;
|
||||
}
|
||||
|
@ -259,6 +283,7 @@ namespace rsx
|
|||
surface_storage_type &ds = It->second;
|
||||
if (Traits::ds_has_format_width_height(ds, depth_format, width, height))
|
||||
{
|
||||
Traits::notify_surface_persist(ds);
|
||||
Traits::prepare_ds_for_drawing(command_list, Traits::get(ds));
|
||||
return Traits::get(ds);
|
||||
}
|
||||
|
@ -290,7 +315,7 @@ namespace rsx
|
|||
|
||||
new_surface = Traits::get(new_surface_storage);
|
||||
Traits::prepare_ds_for_drawing(command_list, new_surface);
|
||||
Traits::invalidate_depth_surface_contents(command_list, new_surface, contents_to_copy, true);
|
||||
Traits::invalidate_surface_contents(command_list, new_surface, contents_to_copy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -527,19 +552,6 @@ namespace rsx
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates cached surface data and marks surface contents as deleteable
|
||||
* Called at the end of a frame (workaround, need to find the proper invalidate command)
|
||||
*/
|
||||
void invalidate_surface_cache_data(command_list_type command_list)
|
||||
{
|
||||
for (auto &rtt : m_render_targets_storage)
|
||||
Traits::invalidate_rtt_surface_contents(command_list, Traits::get(std::get<1>(rtt)), nullptr, false);
|
||||
|
||||
for (auto &ds : m_depth_stencil_storage)
|
||||
Traits::invalidate_depth_surface_contents(command_list, Traits::get(std::get<1>(ds)), nullptr, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -653,7 +665,7 @@ namespace rsx
|
|||
bool doubled_x = false;
|
||||
bool doubled_y = false;
|
||||
|
||||
switch (surface->aa_mode)
|
||||
switch (surface->read_aa_mode)
|
||||
{
|
||||
case rsx::surface_antialiasing::square_rotated_4_samples:
|
||||
case rsx::surface_antialiasing::square_centered_4_samples:
|
||||
|
@ -741,7 +753,7 @@ namespace rsx
|
|||
u16 real_width = requested_width;
|
||||
u16 real_height = requested_height;
|
||||
|
||||
switch (surface->aa_mode)
|
||||
switch (surface->read_aa_mode)
|
||||
{
|
||||
case rsx::surface_antialiasing::diagonal_centered_2_samples:
|
||||
real_width /= 2;
|
||||
|
@ -894,5 +906,26 @@ namespace rsx
|
|||
process_list_function(m_depth_stencil_storage, true);
|
||||
return result;
|
||||
}
|
||||
|
||||
void on_write()
|
||||
{
|
||||
if (write_tag == cache_tag)
|
||||
return;
|
||||
|
||||
for (auto &rtt : m_bound_render_targets)
|
||||
{
|
||||
if (auto surface = std::get<1>(rtt))
|
||||
{
|
||||
surface->on_write();
|
||||
}
|
||||
}
|
||||
|
||||
if (auto ds = std::get<1>(m_bound_depth_stencil))
|
||||
{
|
||||
ds->on_write();
|
||||
}
|
||||
|
||||
write_tag = cache_tag;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -740,7 +740,7 @@ namespace rsx
|
|||
template <typename T, typename U>
|
||||
inline void get_native_dimensions(T &width, T &height, U surface)
|
||||
{
|
||||
switch (surface->aa_mode)
|
||||
switch (surface->read_aa_mode)
|
||||
{
|
||||
case rsx::surface_antialiasing::center_1_sample:
|
||||
return;
|
||||
|
@ -758,7 +758,7 @@ namespace rsx
|
|||
template <typename T, typename U>
|
||||
inline void get_rsx_dimensions(T &width, T &height, U surface)
|
||||
{
|
||||
switch (surface->aa_mode)
|
||||
switch (surface->read_aa_mode)
|
||||
{
|
||||
case rsx::surface_antialiasing::center_1_sample:
|
||||
return;
|
||||
|
@ -776,7 +776,7 @@ namespace rsx
|
|||
template <typename T>
|
||||
inline f32 get_internal_scaling_x(T surface)
|
||||
{
|
||||
switch (surface->aa_mode)
|
||||
switch (surface->read_aa_mode)
|
||||
{
|
||||
default:
|
||||
case rsx::surface_antialiasing::center_1_sample:
|
||||
|
@ -791,7 +791,7 @@ namespace rsx
|
|||
template <typename T>
|
||||
inline f32 get_internal_scaling_y(T surface)
|
||||
{
|
||||
switch (surface->aa_mode)
|
||||
switch (surface->read_aa_mode)
|
||||
{
|
||||
default:
|
||||
case rsx::surface_antialiasing::center_1_sample:
|
||||
|
|
|
@ -129,21 +129,17 @@ struct render_target_traits
|
|||
}
|
||||
|
||||
static
|
||||
void invalidate_rtt_surface_contents(
|
||||
void invalidate_surface_contents(
|
||||
gsl::not_null<ID3D12GraphicsCommandList*>,
|
||||
ID3D12Resource*, ID3D12Resource*, bool)
|
||||
ID3D12Resource*, ID3D12Resource*)
|
||||
{}
|
||||
|
||||
static
|
||||
void invalidate_depth_surface_contents(
|
||||
gsl::not_null<ID3D12GraphicsCommandList*>,
|
||||
ID3D12Resource*, ID3D12Resource*, bool)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
void notify_surface_invalidated(const ComPtr<ID3D12Resource>&)
|
||||
{}
|
||||
|
||||
static
|
||||
void notify_surface_invalidated(const ComPtr<ID3D12Resource>&)
|
||||
void notify_surface_persist(const ComPtr<ID3D12Resource>&)
|
||||
{}
|
||||
|
||||
static
|
||||
|
|
|
@ -214,11 +214,8 @@ void GLGSRender::end()
|
|||
//Copy data from old contents onto this one
|
||||
const auto region = rsx::get_transferable_region(surface);
|
||||
gl::g_hw_blitter->scale_image(surface->old_contents, surface, { 0, 0, std::get<0>(region), std::get<1>(region) }, { 0, 0, std::get<2>(region) , std::get<3>(region) }, !is_depth, is_depth, {});
|
||||
surface->set_cleared();
|
||||
}
|
||||
//TODO: download image contents and reupload them or do a memory cast to copy memory contents if not compatible
|
||||
|
||||
surface->old_contents = nullptr;
|
||||
};
|
||||
|
||||
//Check if we have any 'recycled' surfaces in memory and if so, clear them
|
||||
|
@ -273,15 +270,12 @@ void GLGSRender::end()
|
|||
|
||||
if (clear_depth)
|
||||
gl_state.depth_mask(rsx::method_registers.depth_write_enabled());
|
||||
|
||||
ds->set_cleared();
|
||||
}
|
||||
|
||||
if (ds && ds->old_contents != nullptr && ds->get_rsx_pitch() == ds->old_contents->get_rsx_pitch() &&
|
||||
if (ds && ds->old_contents != nullptr && ds->get_rsx_pitch() == static_cast<gl::render_target*>(ds->old_contents)->get_rsx_pitch() &&
|
||||
ds->old_contents->get_internal_format() == gl::texture::internal_format::rgba8)
|
||||
{
|
||||
m_depth_converter.run(ds->width(), ds->height(), ds->id(), ds->old_contents->id());
|
||||
ds->old_contents = nullptr;
|
||||
}
|
||||
|
||||
if (g_cfg.video.strict_rendering_mode)
|
||||
|
@ -298,11 +292,6 @@ void GLGSRender::end()
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Old contents are one use only. Keep the depth conversion check from firing over and over
|
||||
if (ds) ds->old_contents = nullptr;
|
||||
}
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
|
@ -571,6 +560,8 @@ void GLGSRender::end()
|
|||
}
|
||||
}
|
||||
|
||||
m_rtts.on_write();
|
||||
|
||||
m_attrib_ring_buffer->notify();
|
||||
m_index_ring_buffer->notify();
|
||||
m_vertex_state_buffer->notify();
|
||||
|
@ -988,11 +979,9 @@ void GLGSRender::clear_surface(u32 arg)
|
|||
gl_state.clear_depth(f32(clear_depth) / max_depth_value);
|
||||
mask |= GLenum(gl::buffers::depth);
|
||||
|
||||
gl::render_target *ds = std::get<1>(m_rtts.m_bound_depth_stencil);
|
||||
if (ds && !ds->cleared())
|
||||
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil))
|
||||
{
|
||||
ds->set_cleared();
|
||||
ds->old_contents = nullptr;
|
||||
ds->on_write();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1036,10 +1025,9 @@ void GLGSRender::clear_surface(u32 arg)
|
|||
|
||||
for (auto &rtt : m_rtts.m_bound_render_targets)
|
||||
{
|
||||
if (std::get<0>(rtt) != 0)
|
||||
if (auto surface = std::get<1>(rtt))
|
||||
{
|
||||
std::get<1>(rtt)->set_cleared(true);
|
||||
std::get<1>(rtt)->old_contents = nullptr;
|
||||
surface->on_write();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -375,13 +375,13 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
{
|
||||
if (auto surface = std::get<1>(m_rtts.m_bound_render_targets[index]))
|
||||
{
|
||||
surface->aa_mode = aa_mode;
|
||||
surface->write_aa_mode = aa_mode;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil))
|
||||
{
|
||||
ds->aa_mode = aa_mode;
|
||||
ds->write_aa_mode = aa_mode;
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -426,7 +426,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
m_surface_info[i] = { surface_addresses[i], pitchs[i], false, surface_format, depth_format, clip_horizontal, clip_vertical };
|
||||
|
||||
rtt->tile = find_tile(color_offsets[i], color_locations[i]);
|
||||
rtt->aa_mode = aa_mode;
|
||||
rtt->write_aa_mode = aa_mode;
|
||||
m_gl_texture_cache.notify_surface_changed(surface_addresses[i]);
|
||||
m_gl_texture_cache.tag_framebuffer(surface_addresses[i]);
|
||||
}
|
||||
|
@ -455,7 +455,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
std::get<1>(m_rtts.m_bound_depth_stencil)->set_rsx_pitch(rsx::method_registers.surface_z_pitch());
|
||||
m_depth_surface_info = { depth_address, depth_surface_pitch, true, surface_format, depth_format, clip_horizontal, clip_vertical };
|
||||
|
||||
ds->aa_mode = aa_mode;
|
||||
ds->write_aa_mode = aa_mode;
|
||||
m_gl_texture_cache.notify_surface_changed(depth_address);
|
||||
|
||||
m_gl_texture_cache.tag_framebuffer(depth_address);
|
||||
|
|
|
@ -51,8 +51,6 @@ namespace gl
|
|||
{
|
||||
class render_target : public texture, public rsx::ref_counted, public rsx::render_target_descriptor<texture*>
|
||||
{
|
||||
bool is_cleared = false;
|
||||
|
||||
u32 rsx_pitch = 0;
|
||||
u16 native_pitch = 0;
|
||||
|
||||
|
@ -65,20 +63,18 @@ namespace gl
|
|||
std::unordered_map<u32, std::unique_ptr<texture_view>> views;
|
||||
|
||||
public:
|
||||
render_target *old_contents = nullptr;
|
||||
|
||||
render_target(GLuint width, GLuint height, GLenum sized_format)
|
||||
:texture(GL_TEXTURE_2D, width, height, 1, 1, sized_format)
|
||||
{}
|
||||
|
||||
void set_cleared(bool clear=true)
|
||||
{
|
||||
is_cleared = clear;
|
||||
dirty = !clear;
|
||||
}
|
||||
|
||||
bool cleared() const
|
||||
{
|
||||
return is_cleared;
|
||||
return !dirty;
|
||||
}
|
||||
|
||||
// Internal pitch is the actual row length in bytes of the openGL texture
|
||||
|
@ -228,13 +224,24 @@ struct gl_render_target_traits
|
|||
static void prepare_ds_for_drawing(void *, gl::render_target *ds) { ds->reset_refs(); }
|
||||
static void prepare_ds_for_sampling(void *, gl::render_target*) {}
|
||||
|
||||
static void invalidate_rtt_surface_contents(void *, gl::render_target *rtt, gl::render_target* /*old*/, bool forced) { if (forced) rtt->set_cleared(false); }
|
||||
static void invalidate_depth_surface_contents(void *, gl::render_target *ds, gl::render_target* /*old*/, bool) { ds->set_cleared(false); }
|
||||
static
|
||||
void invalidate_surface_contents(void *, gl::render_target *surface, gl::render_target* old_surface)
|
||||
{
|
||||
surface->set_cleared(false);
|
||||
surface->old_contents = old_surface;
|
||||
surface->reset_aa_mode();
|
||||
}
|
||||
|
||||
static
|
||||
void notify_surface_invalidated(const std::unique_ptr<gl::render_target>&)
|
||||
{}
|
||||
|
||||
static
|
||||
void notify_surface_persist(const std::unique_ptr<gl::render_target>& surface)
|
||||
{
|
||||
surface->save_aa_mode();
|
||||
}
|
||||
|
||||
static
|
||||
bool rtt_has_format_width_height(const std::unique_ptr<gl::render_target> &rtt, rsx::surface_color_format format, size_t width, size_t height, bool check_refs=false)
|
||||
{
|
||||
|
|
|
@ -265,7 +265,7 @@ namespace gl
|
|||
if (pbo_id == 0)
|
||||
init_buffer();
|
||||
|
||||
aa_mode = static_cast<gl::render_target*>(image)->aa_mode;
|
||||
aa_mode = static_cast<gl::render_target*>(image)->read_aa_mode;
|
||||
}
|
||||
|
||||
flushed = false;
|
||||
|
|
|
@ -1115,7 +1115,6 @@ void VKGSRender::end()
|
|||
VkClearValue clear_value = {};
|
||||
clear_value.depthStencil = { 1.f, 255 };
|
||||
buffers_to_clear.push_back({ vk::get_aspect_flags(ds->info.format), 0, clear_value });
|
||||
ds->dirty = false;
|
||||
}
|
||||
|
||||
for (u32 index = 0; index < targets.size(); ++index)
|
||||
|
@ -1125,7 +1124,6 @@ void VKGSRender::end()
|
|||
if (rtt->dirty)
|
||||
{
|
||||
buffers_to_clear.push_back({ VK_IMAGE_ASPECT_COLOR_BIT, index, {} });
|
||||
rtt->dirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1148,14 +1146,9 @@ void VKGSRender::end()
|
|||
{
|
||||
auto rp = vk::get_render_pass_location(VK_FORMAT_UNDEFINED, ds->info.format, 0);
|
||||
auto render_pass = m_render_passes[rp];
|
||||
m_depth_converter->run(*m_current_command_buffer, ds->width(), ds->height(), ds, ds->old_contents->get_view(0xAAE4, rsx::default_remap_vector), render_pass, m_framebuffers_to_clean);
|
||||
|
||||
ds->old_contents = nullptr;
|
||||
}
|
||||
else if (!g_cfg.video.strict_rendering_mode)
|
||||
{
|
||||
//Clear this to avoid dereferencing stale ptr
|
||||
ds->old_contents = nullptr;
|
||||
m_depth_converter->run(*m_current_command_buffer, ds->width(), ds->height(), ds,
|
||||
static_cast<vk::render_target*>(ds->old_contents)->get_view(0xAAE4, rsx::default_remap_vector),
|
||||
render_pass, m_framebuffers_to_clean);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1187,14 +1180,9 @@ void VKGSRender::end()
|
|||
vk::change_image_layout(*m_current_command_buffer, surface->old_contents, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
|
||||
m_depth_scaler->run(*m_current_command_buffer, { 0, 0, (f32)src_w, (f32)src_h }, { 0, 0, (f32)dst_w, (f32)dst_h }, surface,
|
||||
surface->old_contents, surface->old_contents->get_view(0xAAE4, rsx::default_remap_vector), render_pass, m_framebuffers_to_clean);
|
||||
surface->old_contents, static_cast<vk::render_target*>(surface->old_contents)->get_view(0xAAE4, rsx::default_remap_vector), render_pass, m_framebuffers_to_clean);
|
||||
}
|
||||
|
||||
surface->dirty = false;
|
||||
}
|
||||
//TODO: download image contents and reupload them or do a memory cast to copy memory contents if not compatible
|
||||
|
||||
surface->old_contents = nullptr;
|
||||
};
|
||||
|
||||
//Prepare surfaces if needed
|
||||
|
@ -1519,6 +1507,8 @@ void VKGSRender::end()
|
|||
close_render_pass();
|
||||
vk::leave_uninterruptible();
|
||||
|
||||
m_rtts.on_write();
|
||||
|
||||
std::chrono::time_point<steady_clock> draw_end = steady_clock::now();
|
||||
m_draw_time += std::chrono::duration_cast<std::chrono::microseconds>(draw_end - textures_end).count();
|
||||
|
||||
|
@ -1792,10 +1782,9 @@ void VKGSRender::clear_surface(u32 mask)
|
|||
|
||||
for (auto &rtt : m_rtts.m_bound_render_targets)
|
||||
{
|
||||
if (std::get<0>(rtt) != 0)
|
||||
if (auto surface = std::get<1>(rtt))
|
||||
{
|
||||
std::get<1>(rtt)->dirty = false;
|
||||
std::get<1>(rtt)->old_contents = nullptr;
|
||||
surface->on_write();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1804,11 +1793,9 @@ void VKGSRender::clear_surface(u32 mask)
|
|||
|
||||
if (mask & 0x3)
|
||||
{
|
||||
if (std::get<0>(m_rtts.m_bound_depth_stencil) != 0)
|
||||
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil))
|
||||
{
|
||||
std::get<1>(m_rtts.m_bound_depth_stencil)->dirty = false;
|
||||
std::get<1>(m_rtts.m_bound_depth_stencil)->old_contents = nullptr;
|
||||
|
||||
ds->on_write();
|
||||
clear_descriptors.push_back({ (VkImageAspectFlags)depth_stencil_mask, 0, depth_stencil_clear_values });
|
||||
}
|
||||
}
|
||||
|
@ -2744,13 +2731,13 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
|||
{
|
||||
if (auto surface = std::get<1>(m_rtts.m_bound_render_targets[index]))
|
||||
{
|
||||
surface->aa_mode = aa_mode;
|
||||
surface->write_aa_mode = aa_mode;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil))
|
||||
{
|
||||
ds->aa_mode = aa_mode;
|
||||
ds->write_aa_mode = aa_mode;
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -2820,7 +2807,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
|||
m_surface_info[index].pitch = surface_pitchs[index];
|
||||
surface->rsx_pitch = surface_pitchs[index];
|
||||
|
||||
surface->aa_mode = aa_mode;
|
||||
surface->write_aa_mode = aa_mode;
|
||||
m_texture_cache.notify_surface_changed(surface_addresses[index]);
|
||||
|
||||
m_texture_cache.tag_framebuffer(surface_addresses[index]);
|
||||
|
@ -2837,7 +2824,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
|||
m_depth_surface_info.pitch = rsx::method_registers.surface_z_pitch();
|
||||
ds->rsx_pitch = m_depth_surface_info.pitch;
|
||||
|
||||
ds->aa_mode = aa_mode;
|
||||
ds->write_aa_mode = aa_mode;
|
||||
m_texture_cache.notify_surface_changed(zeta_address);
|
||||
|
||||
m_texture_cache.tag_framebuffer(zeta_address);
|
||||
|
|
|
@ -12,7 +12,6 @@ namespace vk
|
|||
{
|
||||
struct render_target : public image, public rsx::ref_counted, public rsx::render_target_descriptor<vk::image*>
|
||||
{
|
||||
bool dirty = false;
|
||||
u16 native_pitch = 0;
|
||||
u16 rsx_pitch = 0;
|
||||
|
||||
|
@ -22,7 +21,6 @@ namespace vk
|
|||
VkImageAspectFlags attachment_aspect_flag = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
std::unordered_map<u32, std::unique_ptr<vk::image_view>> views;
|
||||
|
||||
render_target *old_contents = nullptr; //Data occupying the memory location that this surface is replacing
|
||||
u64 frame_tag = 0; //frame id when invalidated, 0 if not invalid
|
||||
|
||||
render_target(vk::render_device &dev,
|
||||
|
@ -240,19 +238,12 @@ namespace rsx
|
|||
change_image_layout(*pcmd, surface, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, range);
|
||||
}
|
||||
|
||||
static void invalidate_rtt_surface_contents(vk::command_buffer* /*pcmd*/, vk::render_target *rtt, vk::render_target *old_surface, bool forced)
|
||||
static
|
||||
void invalidate_surface_contents(vk::command_buffer* /*pcmd*/, vk::render_target *surface, vk::render_target *old_surface)
|
||||
{
|
||||
if (forced)
|
||||
{
|
||||
rtt->old_contents = old_surface;
|
||||
rtt->dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void invalidate_depth_surface_contents(vk::command_buffer* /*pcmd*/, vk::render_target *ds, vk::render_target *old_surface, bool /*forced*/)
|
||||
{
|
||||
ds->dirty = true;
|
||||
ds->old_contents = old_surface;
|
||||
surface->old_contents = old_surface;
|
||||
surface->dirty = true;
|
||||
surface->reset_aa_mode();
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -262,6 +253,12 @@ namespace rsx
|
|||
if (!surface->frame_tag) surface->frame_tag = 1;
|
||||
}
|
||||
|
||||
static
|
||||
void notify_surface_persist(const std::unique_ptr<vk::render_target> &surface)
|
||||
{
|
||||
surface->save_aa_mode();
|
||||
}
|
||||
|
||||
static bool rtt_has_format_width_height(const std::unique_ptr<vk::render_target> &rtt, surface_color_format format, size_t width, size_t height, bool check_refs=false)
|
||||
{
|
||||
if (check_refs && rtt->deref_count == 0) //Surface may still have read refs from data 'copy'
|
||||
|
|
|
@ -296,7 +296,7 @@ namespace vk
|
|||
//Scale image to fit
|
||||
//usually we can just get away with nearest filtering
|
||||
u8 samples_u = 1, samples_v = 1;
|
||||
switch (static_cast<vk::render_target*>(vram_texture)->aa_mode)
|
||||
switch (static_cast<vk::render_target*>(vram_texture)->read_aa_mode)
|
||||
{
|
||||
case rsx::surface_antialiasing::diagonal_centered_2_samples:
|
||||
samples_u = 2;
|
||||
|
|
|
@ -597,7 +597,7 @@ namespace rsx
|
|||
u16 dst_w = src_w;
|
||||
u16 dst_h = src_h;
|
||||
|
||||
switch (surface->old_contents->aa_mode)
|
||||
switch (static_cast<SurfaceType*>(surface->old_contents)->read_aa_mode)
|
||||
{
|
||||
case rsx::surface_antialiasing::center_1_sample:
|
||||
break;
|
||||
|
@ -611,7 +611,7 @@ namespace rsx
|
|||
break;
|
||||
}
|
||||
|
||||
switch (surface->aa_mode)
|
||||
switch (surface->write_aa_mode)
|
||||
{
|
||||
case rsx::surface_antialiasing::center_1_sample:
|
||||
break;
|
||||
|
|
Loading…
Add table
Reference in a new issue