mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-15 11:18:36 +12:00
rsx: Refactoring and cleanup after d3d12 separation
- Remove deprecated functionality - Refactor to share code between common routines
This commit is contained in:
parent
db5d56a22d
commit
655eff29e8
7 changed files with 298 additions and 593 deletions
|
@ -25,52 +25,9 @@ namespace rsx
|
|||
size_t get_packed_pitch(surface_color_format format, u32 width);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 provides 2 methods get_texture_from_*_if_applicable that should be used when an app
|
||||
* wants to sample a previous surface.
|
||||
* Please note that the backend is still responsible for creating framebuffer/descriptors
|
||||
* and need to inform surface_store everytime surface format/size/addresses change.
|
||||
*
|
||||
* Since it's a template it requires a trait with the followings:
|
||||
* - type surface_storage_type which is a structure containing texture.
|
||||
* - type surface_type which is a pointer to storage_type or a reference.
|
||||
* - type command_list_type that can be void for backend without command list
|
||||
* - type download_buffer_object used by issue_download_command and map_downloaded_buffer functions to handle sync
|
||||
*
|
||||
* - a member function static surface_type(const surface_storage_type&) that returns underlying surface pointer from a storage type.
|
||||
* - 2 member functions static surface_storage_type create_new_surface(u32 address, Surface_color_format/Surface_depth_format format, size_t width, size_t height,...)
|
||||
* used to create a new surface_storage_type holding surface from passed parameters.
|
||||
* - a member function static prepare_rtt_for_drawing(command_list, surface_type) that makes a sampleable surface a color render target one.
|
||||
* - a member function static prepare_rtt_for_drawing(command_list, surface_type) that makes a render target surface a sampleable one.
|
||||
* - a member function static prepare_ds_for_drawing that does the same for depth stencil surface.
|
||||
* - a member function static prepare_ds_for_sampling that does the same for depth stencil surface.
|
||||
* - a member function static bool rtt_has_format_width_height(const surface_storage_type&, Surface_color_format surface_color_format, size_t width, size_t height)
|
||||
* that checks if the given surface has the given format and size
|
||||
* - a member function static bool ds_has_format_width_height that does the same for ds
|
||||
* - a member function static download_buffer_object issue_download_command(surface_type, Surface_color_format color_format, size_t width, size_t height,...)
|
||||
* that generates command to download the given surface to some mappable buffer.
|
||||
* - a member function static issue_depth_download_command that does the same for depth surface
|
||||
* - a member function static issue_stencil_download_command that does the same for stencil surface
|
||||
* - a member function gsl::span<const gsl::byte> map_downloaded_buffer(download_buffer_object, ...) that maps a download_buffer_object
|
||||
* - a member function static unmap_downloaded_buffer that unmaps it.
|
||||
*/
|
||||
template<typename Traits>
|
||||
struct surface_store
|
||||
{
|
||||
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)
|
||||
{
|
||||
for (unsigned row = 0; row < height; row++)
|
||||
{
|
||||
for (unsigned col = 0; col < width; col++)
|
||||
dest[col] = src[col];
|
||||
src = src.subspan(src_pitch_in_bytes / sizeof(U));
|
||||
dest = dest.subspan(width);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr u32 get_aa_factor_u(surface_antialiasing aa_mode)
|
||||
{
|
||||
return (aa_mode == surface_antialiasing::center_1_sample)? 1 : 2;
|
||||
|
@ -92,7 +49,6 @@ namespace rsx
|
|||
using surface_storage_type = typename Traits::surface_storage_type;
|
||||
using surface_type = typename Traits::surface_type;
|
||||
using command_list_type = typename Traits::command_list_type;
|
||||
using download_buffer_object = typename Traits::download_buffer_object;
|
||||
using surface_overlap_info = surface_overlap_info_t<surface_type>;
|
||||
|
||||
protected:
|
||||
|
@ -122,7 +78,6 @@ namespace rsx
|
|||
template <bool is_depth_surface>
|
||||
void split_surface_region(command_list_type cmd, u32 address, surface_type prev_surface, u16 width, u16 height, u8 bpp, rsx::surface_antialiasing aa)
|
||||
{
|
||||
#ifndef INCOMPLETE_SURFACE_CACHE_IMPL
|
||||
auto insert_new_surface = [&](
|
||||
u32 new_address,
|
||||
deferred_clipped_region<surface_type>& region,
|
||||
|
@ -226,13 +181,11 @@ namespace rsx
|
|||
insert_new_surface(baseaddr, copy, m_render_targets_storage);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <bool is_depth_surface>
|
||||
void intersect_surface_region(command_list_type cmd, u32 address, surface_type new_surface, surface_type prev_surface)
|
||||
{
|
||||
#ifndef INCOMPLETE_SURFACE_CACHE_IMPL
|
||||
auto scan_list = [&new_surface, address](const rsx::address_range& mem_range, u64 timestamp_check,
|
||||
std::unordered_map<u32, surface_storage_type>& data) -> std::vector<std::pair<u32, surface_type>>
|
||||
{
|
||||
|
@ -372,7 +325,154 @@ namespace rsx
|
|||
new_surface->set_old_contents_region(region, true);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <bool depth, typename format_type, typename ...Args>
|
||||
surface_type bind_surface_address(
|
||||
command_list_type command_list,
|
||||
u32 address,
|
||||
format_type format,
|
||||
surface_antialiasing antialias,
|
||||
size_t width, size_t height, size_t pitch,
|
||||
u8 bpp,
|
||||
Args&&... extra_params)
|
||||
{
|
||||
surface_storage_type old_surface_storage;
|
||||
surface_storage_type new_surface_storage;
|
||||
surface_type old_surface = nullptr;
|
||||
surface_type new_surface = nullptr;
|
||||
bool store = true;
|
||||
|
||||
address_range *storage_bounds;
|
||||
std::unordered_map<u32, surface_storage_type> *primary_storage, *secondary_storage;
|
||||
if constexpr (depth)
|
||||
{
|
||||
primary_storage = &m_depth_stencil_storage;
|
||||
secondary_storage = &m_render_targets_storage;
|
||||
storage_bounds = &m_depth_stencil_memory_range;
|
||||
}
|
||||
else
|
||||
{
|
||||
primary_storage = &m_render_targets_storage;
|
||||
secondary_storage = &m_depth_stencil_storage;
|
||||
storage_bounds = &m_render_targets_memory_range;
|
||||
}
|
||||
|
||||
// Check if render target already exists
|
||||
auto It = primary_storage->find(address);
|
||||
if (It != primary_storage->end())
|
||||
{
|
||||
surface_storage_type &surface = It->second;
|
||||
const bool pitch_compatible = Traits::surface_is_pitch_compatible(surface, pitch);
|
||||
|
||||
if (pitch_compatible)
|
||||
{
|
||||
// Preserve memory outside the area to be inherited if needed
|
||||
split_surface_region<depth>(command_list, address, Traits::get(surface), (u16)width, (u16)height, bpp, antialias);
|
||||
}
|
||||
|
||||
if (Traits::surface_matches_properties(surface, format, width, height, antialias))
|
||||
{
|
||||
if (pitch_compatible)
|
||||
Traits::notify_surface_persist(surface);
|
||||
else
|
||||
Traits::invalidate_surface_contents(command_list, Traits::get(surface), address, pitch);
|
||||
|
||||
Traits::prepare_surface_for_drawing(command_list, Traits::get(surface));
|
||||
new_surface = Traits::get(surface);
|
||||
store = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
old_surface = Traits::get(surface);
|
||||
old_surface_storage = std::move(surface);
|
||||
primary_storage->erase(It);
|
||||
}
|
||||
}
|
||||
|
||||
if (!new_surface)
|
||||
{
|
||||
// Range test
|
||||
const auto aa_factor_v = get_aa_factor_v(antialias);
|
||||
rsx::address_range range = rsx::address_range::start_length(address, u32(pitch * height * aa_factor_v));
|
||||
*storage_bounds = range.get_min_max(*storage_bounds);
|
||||
|
||||
// Search invalidated resources for a suitable surface
|
||||
for (auto It = invalidated_resources.begin(); It != invalidated_resources.end(); It++)
|
||||
{
|
||||
auto &surface = *It;
|
||||
if (Traits::surface_matches_properties(surface, format, width, height, antialias, true))
|
||||
{
|
||||
new_surface_storage = std::move(surface);
|
||||
Traits::notify_surface_reused(new_surface_storage);
|
||||
|
||||
if (old_surface)
|
||||
{
|
||||
// Exchange this surface with the invalidated one
|
||||
Traits::notify_surface_invalidated(old_surface_storage);
|
||||
surface = std::move(old_surface_storage);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Iterator is now empty - erase it
|
||||
invalidated_resources.erase(It);
|
||||
}
|
||||
|
||||
new_surface = Traits::get(new_surface_storage);
|
||||
Traits::invalidate_surface_contents(command_list, new_surface, address, pitch);
|
||||
Traits::prepare_surface_for_drawing(command_list, new_surface);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for stale storage
|
||||
if (old_surface != nullptr && new_surface == nullptr)
|
||||
{
|
||||
// This was already determined to be invalid and is excluded from testing above
|
||||
Traits::notify_surface_invalidated(old_surface_storage);
|
||||
invalidated_resources.push_back(std::move(old_surface_storage));
|
||||
}
|
||||
|
||||
if (!new_surface)
|
||||
{
|
||||
verify(HERE), store;
|
||||
new_surface_storage = Traits::create_new_surface(address, format, width, height, pitch, antialias, std::forward<Args>(extra_params)...);
|
||||
new_surface = Traits::get(new_surface_storage);
|
||||
}
|
||||
|
||||
if (!old_surface)
|
||||
{
|
||||
// Remove and preserve if possible any overlapping/replaced surface from the other pool
|
||||
auto aliased_surface = secondary_storage->find(address);
|
||||
if (aliased_surface != secondary_storage->end())
|
||||
{
|
||||
old_surface = Traits::get(aliased_surface->second);
|
||||
|
||||
Traits::notify_surface_invalidated(aliased_surface->second);
|
||||
invalidated_resources.push_back(std::move(aliased_surface->second));
|
||||
secondary_storage->erase(aliased_surface);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if old_surface is 'new' and avoid intersection
|
||||
if (old_surface && old_surface->last_use_tag >= write_tag)
|
||||
{
|
||||
new_surface->set_old_contents(old_surface);
|
||||
}
|
||||
else
|
||||
{
|
||||
intersect_surface_region<depth>(command_list, address, new_surface, old_surface);
|
||||
}
|
||||
|
||||
if (store)
|
||||
{
|
||||
// New surface was found among invalidated surfaces or created from scratch
|
||||
(*primary_storage)[address] = std::move(new_surface_storage);
|
||||
}
|
||||
|
||||
verify(HERE), new_surface->get_spp() == get_format_sample_count(antialias);
|
||||
return new_surface;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -390,135 +490,10 @@ namespace rsx
|
|||
size_t width, size_t height, size_t pitch,
|
||||
Args&&... extra_params)
|
||||
{
|
||||
// TODO: Fix corner cases
|
||||
// This doesn't take overlapping surface(s) into account.
|
||||
surface_storage_type old_surface_storage;
|
||||
surface_storage_type new_surface_storage;
|
||||
surface_type old_surface = nullptr;
|
||||
surface_type new_surface = nullptr;
|
||||
bool store = true;
|
||||
|
||||
// Check if render target already exists
|
||||
auto It = m_render_targets_storage.find(address);
|
||||
if (It != m_render_targets_storage.end())
|
||||
{
|
||||
surface_storage_type &rtt = It->second;
|
||||
const bool pitch_compatible = Traits::surface_is_pitch_compatible(rtt, pitch);
|
||||
|
||||
if (pitch_compatible)
|
||||
{
|
||||
// Preserve memory outside the area to be inherited if needed
|
||||
const u8 bpp = get_format_block_size_in_bytes(color_format);
|
||||
split_surface_region<false>(command_list, address, Traits::get(rtt), (u16)width, (u16)height, bpp, antialias);
|
||||
}
|
||||
|
||||
if (Traits::rtt_has_format_width_height(rtt, color_format, width, height))
|
||||
{
|
||||
if (pitch_compatible)
|
||||
Traits::notify_surface_persist(rtt);
|
||||
else
|
||||
Traits::invalidate_surface_contents(command_list, Traits::get(rtt), address, pitch);
|
||||
|
||||
Traits::prepare_rtt_for_drawing(command_list, Traits::get(rtt));
|
||||
new_surface = Traits::get(rtt);
|
||||
store = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
old_surface = Traits::get(rtt);
|
||||
old_surface_storage = std::move(rtt);
|
||||
m_render_targets_storage.erase(address);
|
||||
}
|
||||
}
|
||||
|
||||
if (!new_surface)
|
||||
{
|
||||
// Range test
|
||||
const auto aa_factor_v = get_aa_factor_v(antialias);
|
||||
rsx::address_range range = rsx::address_range::start_length(address, u32(pitch * height * aa_factor_v));
|
||||
m_render_targets_memory_range = range.get_min_max(m_render_targets_memory_range);
|
||||
|
||||
// Search invalidated resources for a suitable surface
|
||||
for (auto It = invalidated_resources.begin(); It != invalidated_resources.end(); It++)
|
||||
{
|
||||
auto &rtt = *It;
|
||||
if (Traits::rtt_has_format_width_height(rtt, color_format, width, height, true))
|
||||
{
|
||||
new_surface_storage = std::move(rtt);
|
||||
#ifndef INCOMPLETE_SURFACE_CACHE_IMPL
|
||||
Traits::notify_surface_reused(new_surface_storage);
|
||||
#endif
|
||||
if (old_surface)
|
||||
{
|
||||
// Exchange this surface with the invalidated one
|
||||
Traits::notify_surface_invalidated(old_surface_storage);
|
||||
rtt = std::move(old_surface_storage);
|
||||
}
|
||||
else
|
||||
{
|
||||
// rtt is now empty - erase it
|
||||
invalidated_resources.erase(It);
|
||||
}
|
||||
|
||||
new_surface = Traits::get(new_surface_storage);
|
||||
Traits::invalidate_surface_contents(command_list, new_surface, address, pitch);
|
||||
Traits::prepare_rtt_for_drawing(command_list, new_surface);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for stale storage
|
||||
if (old_surface != nullptr && new_surface == nullptr)
|
||||
{
|
||||
// This was already determined to be invalid and is excluded from testing above
|
||||
Traits::notify_surface_invalidated(old_surface_storage);
|
||||
invalidated_resources.push_back(std::move(old_surface_storage));
|
||||
}
|
||||
|
||||
if (!new_surface)
|
||||
{
|
||||
verify(HERE), store;
|
||||
new_surface_storage = Traits::create_new_surface(address, color_format, width, height, pitch, std::forward<Args>(extra_params)...);
|
||||
new_surface = Traits::get(new_surface_storage);
|
||||
}
|
||||
|
||||
if (!old_surface)
|
||||
{
|
||||
// Remove and preserve if possible any overlapping/replaced depth surface
|
||||
auto aliased_depth_surface = m_depth_stencil_storage.find(address);
|
||||
if (aliased_depth_surface != m_depth_stencil_storage.end())
|
||||
{
|
||||
old_surface = Traits::get(aliased_depth_surface->second);
|
||||
|
||||
Traits::notify_surface_invalidated(aliased_depth_surface->second);
|
||||
invalidated_resources.push_back(std::move(aliased_depth_surface->second));
|
||||
m_depth_stencil_storage.erase(aliased_depth_surface);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef INCOMPLETE_SURFACE_CACHE_IMPL
|
||||
// TODO: This can be done better after refactoring
|
||||
new_surface->set_aa_mode(antialias);
|
||||
|
||||
// Check if old_surface is 'new' and avoid intersection
|
||||
if (old_surface && old_surface->last_use_tag >= write_tag)
|
||||
{
|
||||
new_surface->set_old_contents(old_surface);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
intersect_surface_region<false>(command_list, address, new_surface, old_surface);
|
||||
}
|
||||
|
||||
if (store)
|
||||
{
|
||||
// New surface was found among invalidated surfaces
|
||||
m_render_targets_storage[address] = std::move(new_surface_storage);
|
||||
}
|
||||
|
||||
return new_surface;
|
||||
return bind_surface_address<false>(
|
||||
command_list, address, color_format, antialias,
|
||||
width, height, pitch, get_format_block_size_in_bytes(color_format),
|
||||
std::forward<Args>(extra_params)...);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
|
@ -530,127 +505,11 @@ namespace rsx
|
|||
size_t width, size_t height, size_t pitch,
|
||||
Args&&... extra_params)
|
||||
{
|
||||
surface_storage_type old_surface_storage;
|
||||
surface_storage_type new_surface_storage;
|
||||
surface_type old_surface = nullptr;
|
||||
surface_type new_surface = nullptr;
|
||||
bool store = true;
|
||||
|
||||
auto It = m_depth_stencil_storage.find(address);
|
||||
if (It != m_depth_stencil_storage.end())
|
||||
{
|
||||
surface_storage_type &ds = It->second;
|
||||
const bool pitch_compatible = Traits::surface_is_pitch_compatible(ds, pitch);
|
||||
|
||||
if (pitch_compatible)
|
||||
{
|
||||
const u8 bpp = (depth_format == rsx::surface_depth_format::z16)? 2 : 4;
|
||||
split_surface_region<true>(command_list, address, Traits::get(ds), (u16)width, (u16)height, bpp, antialias);
|
||||
}
|
||||
|
||||
if (Traits::ds_has_format_width_height(ds, depth_format, width, height))
|
||||
{
|
||||
if (pitch_compatible)
|
||||
Traits::notify_surface_persist(ds);
|
||||
else
|
||||
Traits::invalidate_surface_contents(command_list, Traits::get(ds), address, pitch);
|
||||
|
||||
Traits::prepare_ds_for_drawing(command_list, Traits::get(ds));
|
||||
new_surface = Traits::get(ds);
|
||||
store = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
old_surface = Traits::get(ds);
|
||||
old_surface_storage = std::move(ds);
|
||||
m_depth_stencil_storage.erase(address);
|
||||
}
|
||||
}
|
||||
|
||||
if (!new_surface)
|
||||
{
|
||||
// Range test
|
||||
const auto aa_factor_v = get_aa_factor_v(antialias);
|
||||
rsx::address_range range = rsx::address_range::start_length(address, u32(pitch * height * aa_factor_v));
|
||||
m_depth_stencil_memory_range = range.get_min_max(m_depth_stencil_memory_range);
|
||||
|
||||
//Search invalidated resources for a suitable surface
|
||||
for (auto It = invalidated_resources.begin(); It != invalidated_resources.end(); It++)
|
||||
{
|
||||
auto &ds = *It;
|
||||
if (Traits::ds_has_format_width_height(ds, depth_format, width, height, true))
|
||||
{
|
||||
new_surface_storage = std::move(ds);
|
||||
#ifndef INCOMPLETE_SURFACE_CACHE_IMPL
|
||||
Traits::notify_surface_reused(new_surface_storage);
|
||||
#endif
|
||||
if (old_surface)
|
||||
{
|
||||
//Exchange this surface with the invalidated one
|
||||
Traits::notify_surface_invalidated(old_surface_storage);
|
||||
ds = std::move(old_surface_storage);
|
||||
}
|
||||
else
|
||||
invalidated_resources.erase(It);
|
||||
|
||||
new_surface = Traits::get(new_surface_storage);
|
||||
Traits::prepare_ds_for_drawing(command_list, new_surface);
|
||||
Traits::invalidate_surface_contents(command_list, new_surface, address, pitch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (old_surface != nullptr && new_surface == nullptr)
|
||||
{
|
||||
// This was already determined to be invalid and is excluded from testing above
|
||||
Traits::notify_surface_invalidated(old_surface_storage);
|
||||
invalidated_resources.push_back(std::move(old_surface_storage));
|
||||
}
|
||||
|
||||
if (!new_surface)
|
||||
{
|
||||
verify(HERE), store;
|
||||
new_surface_storage = Traits::create_new_surface(address, depth_format, width, height, pitch, std::forward<Args>(extra_params)...);
|
||||
new_surface = Traits::get(new_surface_storage);
|
||||
}
|
||||
|
||||
if (!old_surface)
|
||||
{
|
||||
// Remove and preserve if possible any overlapping/replaced color surface
|
||||
auto aliased_rtt_surface = m_render_targets_storage.find(address);
|
||||
if (aliased_rtt_surface != m_render_targets_storage.end())
|
||||
{
|
||||
old_surface = Traits::get(aliased_rtt_surface->second);
|
||||
|
||||
Traits::notify_surface_invalidated(aliased_rtt_surface->second);
|
||||
invalidated_resources.push_back(std::move(aliased_rtt_surface->second));
|
||||
m_render_targets_storage.erase(aliased_rtt_surface);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef INCOMPLETE_SURFACE_CACHE_IMPL
|
||||
// TODO: Forward this to the management functions
|
||||
new_surface->set_aa_mode(antialias);
|
||||
|
||||
// Check if old_surface is 'new' and avoid intersection
|
||||
if (old_surface && old_surface->last_use_tag >= write_tag)
|
||||
{
|
||||
new_surface->set_old_contents(old_surface);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
intersect_surface_region<true>(command_list, address, new_surface, old_surface);
|
||||
}
|
||||
|
||||
if (store)
|
||||
{
|
||||
// New surface was found among invalidated surfaces
|
||||
m_depth_stencil_storage[address] = std::move(new_surface_storage);
|
||||
}
|
||||
|
||||
return new_surface;
|
||||
return bind_surface_address<true>(
|
||||
command_list, address, depth_format, antialias,
|
||||
width, height, pitch,
|
||||
depth_format == rsx::surface_depth_format::z16? 2 : 4,
|
||||
std::forward<Args>(extra_params)...);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
|
@ -679,7 +538,7 @@ namespace rsx
|
|||
++i, ++count)
|
||||
{
|
||||
auto &rtt = m_bound_render_targets[i];
|
||||
Traits::prepare_rtt_for_sampling(command_list, std::get<1>(rtt));
|
||||
Traits::prepare_surface_for_sampling(command_list, std::get<1>(rtt));
|
||||
rtt = std::make_pair(0, nullptr);
|
||||
}
|
||||
|
||||
|
@ -708,40 +567,20 @@ namespace rsx
|
|||
|
||||
// Same for depth buffer
|
||||
if (std::get<1>(m_bound_depth_stencil) != nullptr)
|
||||
Traits::prepare_ds_for_sampling(command_list, std::get<1>(m_bound_depth_stencil));
|
||||
{
|
||||
Traits::prepare_surface_for_sampling(command_list, std::get<1>(m_bound_depth_stencil));
|
||||
}
|
||||
|
||||
m_bound_depth_stencil = std::make_pair(0, nullptr);
|
||||
|
||||
if (!address_z)
|
||||
return;
|
||||
|
||||
m_bound_depth_stencil = std::make_pair(address_z,
|
||||
bind_address_as_depth_stencil(command_list, address_z, depth_format, antialias,
|
||||
clip_width, clip_height, zeta_pitch, std::forward<Args>(extra_params)...));
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for given address in stored color surface
|
||||
* Return an empty surface_type otherwise.
|
||||
*/
|
||||
surface_type get_texture_from_render_target_if_applicable(u32 address)
|
||||
{
|
||||
auto It = m_render_targets_storage.find(address);
|
||||
if (It != m_render_targets_storage.end())
|
||||
return Traits::get(It->second);
|
||||
return surface_type();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for given address in stored depth stencil surface
|
||||
* Return an empty surface_type otherwise.
|
||||
*/
|
||||
surface_type get_texture_from_depth_stencil_if_applicable(u32 address)
|
||||
{
|
||||
auto It = m_depth_stencil_storage.find(address);
|
||||
if (It != m_depth_stencil_storage.end())
|
||||
return Traits::get(It->second);
|
||||
return surface_type();
|
||||
if (LIKELY(address_z))
|
||||
{
|
||||
m_bound_depth_stencil = std::make_pair(address_z,
|
||||
bind_address_as_depth_stencil(command_list, address_z, depth_format, antialias,
|
||||
clip_width, clip_height, zeta_pitch, std::forward<Args>(extra_params)...));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bound_depth_stencil = std::make_pair(0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
surface_type get_surface_at(u32 address)
|
||||
|
@ -757,138 +596,22 @@ namespace rsx
|
|||
fmt::throw_exception("Unreachable" HERE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bound color surface raw data.
|
||||
*/
|
||||
template <typename... Args>
|
||||
std::array<std::vector<gsl::byte>, 4> get_render_targets_data(
|
||||
surface_color_format color_format, size_t width, size_t height,
|
||||
Args&& ...args
|
||||
)
|
||||
surface_type get_color_surface_at(u32 address)
|
||||
{
|
||||
std::array<download_buffer_object, 4> download_data = {};
|
||||
auto It = m_render_targets_storage.find(address);
|
||||
if (It != m_render_targets_storage.end())
|
||||
return Traits::get(It->second);
|
||||
|
||||
// Issue download commands
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (std::get<0>(m_bound_render_targets[i]) == 0)
|
||||
continue;
|
||||
|
||||
surface_type surface_resource = std::get<1>(m_bound_render_targets[i]);
|
||||
download_data[i] = std::move(
|
||||
Traits::issue_download_command(surface_resource, color_format, width, height, std::forward<Args&&>(args)...)
|
||||
);
|
||||
}
|
||||
|
||||
std::array<std::vector<gsl::byte>, 4> result = {};
|
||||
|
||||
// Sync and copy data
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (std::get<0>(m_bound_render_targets[i]) == 0)
|
||||
continue;
|
||||
|
||||
gsl::span<const gsl::byte> raw_src = Traits::map_downloaded_buffer(download_data[i], std::forward<Args&&>(args)...);
|
||||
|
||||
size_t src_pitch = utility::get_aligned_pitch(color_format, ::narrow<u32>(width));
|
||||
size_t dst_pitch = utility::get_packed_pitch(color_format, ::narrow<u32>(width));
|
||||
|
||||
result[i].resize(dst_pitch * height);
|
||||
|
||||
// Note: MSVC + GSL doesn't support span<byte> -> span<T> for non const span atm
|
||||
// thus manual conversion
|
||||
switch (color_format)
|
||||
{
|
||||
case surface_color_format::a8b8g8r8:
|
||||
case surface_color_format::x8b8g8r8_o8b8g8r8:
|
||||
case surface_color_format::x8b8g8r8_z8b8g8r8:
|
||||
case surface_color_format::a8r8g8b8:
|
||||
case surface_color_format::x8r8g8b8_o8r8g8b8:
|
||||
case surface_color_format::x8r8g8b8_z8r8g8b8:
|
||||
case surface_color_format::x32:
|
||||
{
|
||||
gsl::span<be_t<u32>> dst_span{ (be_t<u32>*)result[i].data(), ::narrow<int>(dst_pitch * height / sizeof(be_t<u32>)) };
|
||||
copy_pitched_src_to_dst(dst_span, as_const_span<const u32>(raw_src), src_pitch, width, height);
|
||||
break;
|
||||
}
|
||||
case surface_color_format::b8:
|
||||
{
|
||||
gsl::span<u8> dst_span{ (u8*)result[i].data(), ::narrow<int>(dst_pitch * height / sizeof(u8)) };
|
||||
copy_pitched_src_to_dst(dst_span, as_const_span<const u8>(raw_src), src_pitch, width, height);
|
||||
break;
|
||||
}
|
||||
case surface_color_format::g8b8:
|
||||
case surface_color_format::r5g6b5:
|
||||
case surface_color_format::x1r5g5b5_o1r5g5b5:
|
||||
case surface_color_format::x1r5g5b5_z1r5g5b5:
|
||||
{
|
||||
gsl::span<be_t<u16>> dst_span{ (be_t<u16>*)result[i].data(), ::narrow<int>(dst_pitch * height / sizeof(be_t<u16>)) };
|
||||
copy_pitched_src_to_dst(dst_span, as_const_span<const u16>(raw_src), src_pitch, width, height);
|
||||
break;
|
||||
}
|
||||
// Note : may require some big endian swap
|
||||
case surface_color_format::w32z32y32x32:
|
||||
{
|
||||
gsl::span<u128> dst_span{ (u128*)result[i].data(), ::narrow<int>(dst_pitch * height / sizeof(u128)) };
|
||||
copy_pitched_src_to_dst(dst_span, as_const_span<const u128>(raw_src), src_pitch, width, height);
|
||||
break;
|
||||
}
|
||||
case surface_color_format::w16z16y16x16:
|
||||
{
|
||||
gsl::span<u64> dst_span{ (u64*)result[i].data(), ::narrow<int>(dst_pitch * height / sizeof(u64)) };
|
||||
copy_pitched_src_to_dst(dst_span, as_const_span<const u64>(raw_src), src_pitch, width, height);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
Traits::unmap_downloaded_buffer(download_data[i], std::forward<Args&&>(args)...);
|
||||
}
|
||||
return result;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bound color surface raw data.
|
||||
*/
|
||||
template <typename... Args>
|
||||
std::array<std::vector<gsl::byte>, 2> get_depth_stencil_data(
|
||||
surface_depth_format depth_format, size_t width, size_t height,
|
||||
Args&& ...args
|
||||
)
|
||||
surface_type get_depth_stencil_surface_at(u32 address)
|
||||
{
|
||||
std::array<std::vector<gsl::byte>, 2> result = {};
|
||||
if (std::get<0>(m_bound_depth_stencil) == 0)
|
||||
return result;
|
||||
size_t row_pitch = align(width * 4, 256);
|
||||
auto It = m_depth_stencil_storage.find(address);
|
||||
if (It != m_depth_stencil_storage.end())
|
||||
return Traits::get(It->second);
|
||||
|
||||
download_buffer_object stencil_data = {};
|
||||
download_buffer_object depth_data = Traits::issue_depth_download_command(std::get<1>(m_bound_depth_stencil), depth_format, width, height, std::forward<Args&&>(args)...);
|
||||
if (depth_format == surface_depth_format::z24s8)
|
||||
stencil_data = std::move(Traits::issue_stencil_download_command(std::get<1>(m_bound_depth_stencil), width, height, std::forward<Args&&>(args)...));
|
||||
|
||||
gsl::span<const gsl::byte> depth_buffer_raw_src = Traits::map_downloaded_buffer(depth_data, std::forward<Args&&>(args)...);
|
||||
if (depth_format == surface_depth_format::z16)
|
||||
{
|
||||
result[0].resize(width * height * 2);
|
||||
gsl::span<u16> dest{ (u16*)result[0].data(), ::narrow<int>(width * height) };
|
||||
copy_pitched_src_to_dst(dest, as_const_span<const u16>(depth_buffer_raw_src), row_pitch, width, height);
|
||||
}
|
||||
if (depth_format == surface_depth_format::z24s8)
|
||||
{
|
||||
result[0].resize(width * height * 4);
|
||||
gsl::span<u32> dest{ (u32*)result[0].data(), ::narrow<int>(width * height) };
|
||||
copy_pitched_src_to_dst(dest, as_const_span<const u32>(depth_buffer_raw_src), row_pitch, width, height);
|
||||
}
|
||||
Traits::unmap_downloaded_buffer(depth_data, std::forward<Args&&>(args)...);
|
||||
|
||||
if (depth_format == surface_depth_format::z16)
|
||||
return result;
|
||||
|
||||
gsl::span<const gsl::byte> stencil_buffer_raw_src = Traits::map_downloaded_buffer(stencil_data, std::forward<Args&&>(args)...);
|
||||
result[1].resize(width * height);
|
||||
gsl::span<u8> dest{ (u8*)result[1].data(), ::narrow<int>(width * height) };
|
||||
copy_pitched_src_to_dst(dest, as_const_span<const u8>(stencil_buffer_raw_src), align(width, 256), width, height);
|
||||
Traits::unmap_downloaded_buffer(stencil_data, std::forward<Args&&>(args)...);
|
||||
return result;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "Utilities/types.h"
|
||||
#include "Utilities/geometry.h"
|
||||
|
@ -214,6 +214,26 @@ namespace rsx
|
|||
}
|
||||
}
|
||||
|
||||
void set_spp(u8 count)
|
||||
{
|
||||
switch (count)
|
||||
{
|
||||
case 1:
|
||||
samples_x = samples_y = spp = 1;
|
||||
break;
|
||||
case 2:
|
||||
samples_x = spp = 2;
|
||||
samples_y = 1;
|
||||
break;
|
||||
case 4:
|
||||
samples_x = samples_y = 2;
|
||||
spp = 4;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unexpected sample count 0x%x", count);
|
||||
}
|
||||
}
|
||||
|
||||
void set_format(rsx::surface_color_format format)
|
||||
{
|
||||
format_info.gcm_color_format = format;
|
||||
|
|
|
@ -1655,7 +1655,7 @@ void GLGSRender::flip(int buffer, bool emu_flip)
|
|||
const u32 absolute_address = rsx::get_address(display_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
|
||||
GLuint image = GL_NONE;
|
||||
|
||||
if (auto render_target_texture = m_rtts.get_texture_from_render_target_if_applicable(absolute_address))
|
||||
if (auto render_target_texture = m_rtts.get_color_surface_at(absolute_address))
|
||||
{
|
||||
if (render_target_texture->last_use_tag == m_rtts.write_tag)
|
||||
{
|
||||
|
|
|
@ -454,23 +454,19 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
|
||||
if (m_gl_texture_cache.get_ro_tex_invalidate_intr())
|
||||
{
|
||||
//Invalidate cached sampler state
|
||||
// Invalidate cached sampler state
|
||||
m_samplers_dirty.store(true);
|
||||
}
|
||||
}
|
||||
|
||||
std::array<std::vector<gsl::byte>, 4> GLGSRender::copy_render_targets_to_memory()
|
||||
{
|
||||
int clip_w = rsx::method_registers.surface_clip_width();
|
||||
int clip_h = rsx::method_registers.surface_clip_height();
|
||||
return m_rtts.get_render_targets_data(rsx::method_registers.surface_color(), clip_w, clip_h);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::array<std::vector<gsl::byte>, 2> GLGSRender::copy_depth_stencil_buffer_to_memory()
|
||||
{
|
||||
int clip_w = rsx::method_registers.surface_clip_width();
|
||||
int clip_h = rsx::method_registers.surface_clip_height();
|
||||
return m_rtts.get_depth_stencil_data(rsx::method_registers.surface_depth_fmt(), clip_w, clip_h);
|
||||
return {};
|
||||
}
|
||||
|
||||
void GLGSRender::read_buffers()
|
||||
|
|
|
@ -76,11 +76,6 @@ namespace gl
|
|||
rsx_pitch = pitch;
|
||||
}
|
||||
|
||||
u16 get_rsx_pitch() const override
|
||||
{
|
||||
return rsx_pitch;
|
||||
}
|
||||
|
||||
bool is_depth_surface() const override
|
||||
{
|
||||
switch (get_internal_format())
|
||||
|
@ -144,7 +139,8 @@ struct gl_render_target_traits
|
|||
std::unique_ptr<gl::render_target> create_new_surface(
|
||||
u32 address,
|
||||
rsx::surface_color_format surface_color_format,
|
||||
size_t width, size_t height, size_t pitch
|
||||
size_t width, size_t height, size_t pitch,
|
||||
rsx::surface_antialiasing antialias
|
||||
)
|
||||
{
|
||||
auto format = rsx::internals::surface_color_format_to_gl(surface_color_format);
|
||||
|
@ -155,6 +151,7 @@ struct gl_render_target_traits
|
|||
result->set_native_pitch((u16)width * format.channel_count * format.channel_size);
|
||||
result->set_surface_dimensions((u16)width, (u16)height, (u16)pitch);
|
||||
result->set_format(surface_color_format);
|
||||
result->set_aa_mode(antialias);
|
||||
|
||||
std::array<GLenum, 4> native_layout = { (GLenum)format.swizzle.a, (GLenum)format.swizzle.r, (GLenum)format.swizzle.g, (GLenum)format.swizzle.b };
|
||||
result->set_native_component_layout(native_layout);
|
||||
|
@ -170,7 +167,8 @@ struct gl_render_target_traits
|
|||
std::unique_ptr<gl::render_target> create_new_surface(
|
||||
u32 address,
|
||||
rsx::surface_depth_format surface_depth_format,
|
||||
size_t width, size_t height, size_t pitch
|
||||
size_t width, size_t height, size_t pitch,
|
||||
rsx::surface_antialiasing antialias
|
||||
)
|
||||
{
|
||||
auto format = rsx::internals::surface_depth_format_to_gl(surface_depth_format);
|
||||
|
@ -186,6 +184,7 @@ struct gl_render_target_traits
|
|||
result->set_surface_dimensions((u16)width, (u16)height, (u16)pitch);
|
||||
result->set_native_component_layout(native_layout);
|
||||
result->set_format(surface_depth_format);
|
||||
result->set_aa_mode(antialias);
|
||||
|
||||
result->memory_usage_flags = rsx::surface_usage_flags::attachment;
|
||||
result->state_flags = rsx::surface_state_flags::erase_bkgnd;
|
||||
|
@ -213,6 +212,7 @@ struct gl_render_target_traits
|
|||
sink->state_flags = rsx::surface_state_flags::erase_bkgnd;
|
||||
sink->format_info = ref->format_info;
|
||||
|
||||
sink->set_spp(ref->get_spp());
|
||||
sink->set_native_pitch(prev.width * ref->get_bpp());
|
||||
sink->set_surface_dimensions(prev.width, prev.height, ref->get_rsx_pitch());
|
||||
sink->set_native_component_layout(ref->get_native_component_layout());
|
||||
|
@ -231,25 +231,23 @@ struct gl_render_target_traits
|
|||
}
|
||||
|
||||
static
|
||||
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() &&
|
||||
surface->get_spp() == sample_count &&
|
||||
surface->get_surface_width(rsx::surface_metrics::pixels) >= width &&
|
||||
surface->get_surface_height(rsx::surface_metrics::pixels) >= height);
|
||||
}
|
||||
|
||||
static void prepare_rtt_for_drawing(gl::command_context&, gl::render_target* rtt)
|
||||
static
|
||||
void prepare_surface_for_drawing(gl::command_context&, gl::render_target* surface)
|
||||
{
|
||||
rtt->memory_usage_flags |= rsx::surface_usage_flags::attachment;
|
||||
surface->memory_usage_flags |= rsx::surface_usage_flags::attachment;
|
||||
}
|
||||
|
||||
static void prepare_ds_for_drawing(gl::command_context&, gl::render_target* ds)
|
||||
{
|
||||
ds->memory_usage_flags |= rsx::surface_usage_flags::attachment;
|
||||
}
|
||||
|
||||
static void prepare_rtt_for_sampling(gl::command_context&, gl::render_target*) {}
|
||||
static void prepare_ds_for_sampling(gl::command_context&, gl::render_target*) {}
|
||||
static
|
||||
void prepare_surface_for_sampling(gl::command_context&, gl::render_target*)
|
||||
{}
|
||||
|
||||
static
|
||||
bool surface_is_pitch_compatible(const std::unique_ptr<gl::render_target> &surface, size_t pitch)
|
||||
|
@ -291,63 +289,47 @@ struct gl_render_target_traits
|
|||
}
|
||||
|
||||
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)
|
||||
bool int_surface_matches_properties(
|
||||
const std::unique_ptr<gl::render_target> &surface,
|
||||
gl::texture::internal_format format,
|
||||
size_t width, size_t height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
bool check_refs = false)
|
||||
{
|
||||
if (check_refs && rtt->has_refs())
|
||||
if (check_refs && surface->has_refs())
|
||||
return false;
|
||||
|
||||
return surface->get_internal_format() == format &&
|
||||
surface->get_spp() == get_format_sample_count(antialias) &&
|
||||
surface->matches_dimensions((u16)width, (u16)height);
|
||||
}
|
||||
|
||||
static
|
||||
bool surface_matches_properties(
|
||||
const std::unique_ptr<gl::render_target> &surface,
|
||||
rsx::surface_color_format format,
|
||||
size_t width, size_t height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
bool check_refs=false)
|
||||
{
|
||||
const auto internal_fmt = rsx::internals::sized_internal_format(format);
|
||||
return rtt->get_internal_format() == internal_fmt && rtt->matches_dimensions((u16)width, (u16)height);
|
||||
return int_surface_matches_properties(surface, internal_fmt, width, height, antialias, check_refs);
|
||||
}
|
||||
|
||||
static
|
||||
bool ds_has_format_width_height(const std::unique_ptr<gl::render_target> &ds, rsx::surface_depth_format format, size_t width, size_t height, bool check_refs=false)
|
||||
bool surface_matches_properties(
|
||||
const std::unique_ptr<gl::render_target> &surface,
|
||||
rsx::surface_depth_format format,
|
||||
size_t width, size_t height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
bool check_refs = false)
|
||||
{
|
||||
if (check_refs && ds->has_refs())
|
||||
return false;
|
||||
|
||||
const auto internal_fmt = rsx::internals::surface_depth_format_to_gl(format).internal_format;
|
||||
return ds->get_internal_format() == internal_fmt && ds->matches_dimensions((u16)width, (u16)height);
|
||||
}
|
||||
|
||||
// Note : pbo breaks fbo here so use classic texture copy
|
||||
static std::vector<u8> issue_download_command(gl::render_target* color_buffer, rsx::surface_color_format color_format, size_t width, size_t height)
|
||||
{
|
||||
auto pixel_format = rsx::internals::surface_color_format_to_gl(color_format);
|
||||
std::vector<u8> result(width * height * pixel_format.channel_count * pixel_format.channel_size);
|
||||
glBindTexture(GL_TEXTURE_2D, color_buffer->id());
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, (GLenum)pixel_format.format, (GLenum)pixel_format.type, result.data());
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::vector<u8> issue_depth_download_command(gl::render_target* depth_stencil_buffer, rsx::surface_depth_format depth_format, size_t width, size_t height)
|
||||
{
|
||||
std::vector<u8> result(width * height * 4);
|
||||
|
||||
auto pixel_format = rsx::internals::surface_depth_format_to_gl(depth_format);
|
||||
glBindTexture(GL_TEXTURE_2D, depth_stencil_buffer->id());
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, (GLenum)pixel_format.format, (GLenum)pixel_format.type, result.data());
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::vector<u8> issue_stencil_download_command(gl::render_target*, size_t width, size_t height)
|
||||
{
|
||||
std::vector<u8> result(width * height * 4);
|
||||
return result;
|
||||
return int_surface_matches_properties(surface, internal_fmt, width, height, antialias, check_refs);
|
||||
}
|
||||
|
||||
static
|
||||
gsl::span<const gsl::byte> map_downloaded_buffer(const std::vector<u8> &buffer)
|
||||
{
|
||||
return{ reinterpret_cast<const gsl::byte*>(buffer.data()), ::narrow<int>(buffer.size()) };
|
||||
}
|
||||
|
||||
static
|
||||
void unmap_downloaded_buffer(const std::vector<u8> &)
|
||||
{
|
||||
}
|
||||
|
||||
static gl::render_target* get(const std::unique_ptr<gl::render_target> &in)
|
||||
gl::render_target* get(const std::unique_ptr<gl::render_target> &in)
|
||||
{
|
||||
return in.get();
|
||||
}
|
||||
|
|
|
@ -3142,7 +3142,7 @@ void VKGSRender::flip(int buffer, bool emu_flip)
|
|||
{
|
||||
const u32 absolute_address = rsx::get_address(display_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
|
||||
|
||||
if (auto render_target_texture = m_rtts.get_texture_from_render_target_if_applicable(absolute_address))
|
||||
if (auto render_target_texture = m_rtts.get_color_surface_at(absolute_address))
|
||||
{
|
||||
if (render_target_texture->last_use_tag == m_rtts.write_tag)
|
||||
{
|
||||
|
|
|
@ -161,6 +161,7 @@ namespace rsx
|
|||
u32 address,
|
||||
surface_color_format format,
|
||||
size_t width, size_t height, size_t pitch,
|
||||
rsx::surface_antialiasing antialias,
|
||||
vk::render_device &device, vk::command_buffer& cmd)
|
||||
{
|
||||
auto fmt = vk::get_compatible_surface_format(format);
|
||||
|
@ -181,6 +182,7 @@ namespace rsx
|
|||
change_image_layout(cmd, rtt.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT));
|
||||
|
||||
rtt->set_format(format);
|
||||
rtt->set_aa_mode(antialias);
|
||||
rtt->memory_usage_flags = rsx::surface_usage_flags::attachment;
|
||||
rtt->state_flags = rsx::surface_state_flags::erase_bkgnd;
|
||||
rtt->native_component_map = fmt.second;
|
||||
|
@ -198,6 +200,7 @@ namespace rsx
|
|||
u32 address,
|
||||
surface_depth_format format,
|
||||
size_t width, size_t height, size_t pitch,
|
||||
rsx::surface_antialiasing antialias,
|
||||
vk::render_device &device, vk::command_buffer& cmd)
|
||||
{
|
||||
VkFormat requested_format = vk::get_compatible_depth_surface_format(device.get_formats_support(), format);
|
||||
|
@ -222,6 +225,7 @@ namespace rsx
|
|||
|
||||
|
||||
ds->set_format(format);
|
||||
ds->set_aa_mode(antialias);
|
||||
ds->memory_usage_flags= rsx::surface_usage_flags::attachment;
|
||||
ds->state_flags = rsx::surface_state_flags::erase_bkgnd;
|
||||
ds->native_component_map = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R };
|
||||
|
@ -264,6 +268,7 @@ namespace rsx
|
|||
ref->info.flags);
|
||||
|
||||
sink->add_ref();
|
||||
sink->set_spp(ref->get_spp());
|
||||
sink->format_info = ref->format_info;
|
||||
sink->memory_usage_flags = rsx::surface_usage_flags::storage;
|
||||
sink->state_flags = rsx::surface_state_flags::erase_bkgnd;
|
||||
|
@ -284,33 +289,30 @@ namespace rsx
|
|||
sink->last_use_tag = ref->last_use_tag;
|
||||
}
|
||||
|
||||
static bool is_compatible_surface(const vk::render_target* surface, const vk::render_target* ref, u16 width, u16 height, u8 /*sample_count*/)
|
||||
static bool is_compatible_surface(const vk::render_target* surface, const vk::render_target* ref, u16 width, u16 height, u8 sample_count)
|
||||
{
|
||||
return (surface->format() == ref->format() &&
|
||||
surface->get_spp() == sample_count &&
|
||||
surface->get_surface_width() >= width &&
|
||||
surface->get_surface_height() >= height);
|
||||
}
|
||||
|
||||
static void prepare_rtt_for_drawing(vk::command_buffer& cmd, vk::render_target *surface)
|
||||
static void prepare_surface_for_drawing(vk::command_buffer& cmd, vk::render_target *surface)
|
||||
{
|
||||
surface->change_layout(cmd, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
if (surface->aspect() == VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
{
|
||||
surface->change_layout(cmd, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
surface->change_layout(cmd, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
surface->frame_tag = 0;
|
||||
surface->memory_usage_flags |= rsx::surface_usage_flags::attachment;
|
||||
}
|
||||
|
||||
static void prepare_rtt_for_sampling(vk::command_buffer& cmd, vk::render_target *surface)
|
||||
{
|
||||
surface->change_layout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
static void prepare_ds_for_drawing(vk::command_buffer& cmd, vk::render_target *surface)
|
||||
{
|
||||
surface->change_layout(cmd, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
surface->frame_tag = 0;
|
||||
surface->memory_usage_flags |= rsx::surface_usage_flags::attachment;
|
||||
}
|
||||
|
||||
static void prepare_ds_for_sampling(vk::command_buffer& cmd, vk::render_target *surface)
|
||||
static void prepare_surface_for_sampling(vk::command_buffer& cmd, vk::render_target *surface)
|
||||
{
|
||||
surface->change_layout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
@ -352,63 +354,45 @@ namespace rsx
|
|||
surface->add_ref();
|
||||
}
|
||||
|
||||
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)
|
||||
static bool int_surface_matches_properties(
|
||||
const std::unique_ptr<vk::render_target> &surface,
|
||||
VkFormat format,
|
||||
size_t width, size_t height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
bool check_refs)
|
||||
{
|
||||
if (check_refs && rtt->has_refs()) // Surface may still have read refs from data 'copy'
|
||||
return false;
|
||||
|
||||
VkFormat fmt = vk::get_compatible_surface_format(format).first;
|
||||
|
||||
if (rtt->info.format == fmt &&
|
||||
rtt->matches_dimensions((u16)width, (u16)height))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ds_has_format_width_height(const std::unique_ptr<vk::render_target> &ds, surface_depth_format format, size_t width, size_t height, bool check_refs=false)
|
||||
{
|
||||
if (check_refs && ds->has_refs()) //Surface may still have read refs from data 'copy'
|
||||
return false;
|
||||
|
||||
if (ds->matches_dimensions((u16)width, (u16)height))
|
||||
if (check_refs && surface->has_refs())
|
||||
{
|
||||
//Check format
|
||||
switch (ds->info.format)
|
||||
{
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
return format == surface_depth_format::z16;
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
return format == surface_depth_format::z24s8;
|
||||
}
|
||||
// Surface may still have read refs from data 'copy'
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return (surface->info.format == format &&
|
||||
surface->get_spp() == get_format_sample_count(antialias) &&
|
||||
surface->matches_dimensions((u16)width, (u16)height));
|
||||
}
|
||||
|
||||
static download_buffer_object issue_download_command(surface_type, surface_color_format, size_t /*width*/, size_t /*height*/, ...)
|
||||
static bool surface_matches_properties(
|
||||
const std::unique_ptr<vk::render_target> &surface,
|
||||
surface_color_format format,
|
||||
size_t width, size_t height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
bool check_refs = false)
|
||||
{
|
||||
return nullptr;
|
||||
VkFormat vk_format = vk::get_compatible_surface_format(format).first;
|
||||
return int_surface_matches_properties(surface, vk_format, width, height, antialias, check_refs);
|
||||
}
|
||||
|
||||
static download_buffer_object issue_depth_download_command(surface_type, surface_depth_format, size_t /*width*/, size_t /*height*/, ...)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static download_buffer_object issue_stencil_download_command(surface_type, surface_depth_format, size_t /*width*/, size_t /*height*/, ...)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gsl::span<const gsl::byte> map_downloaded_buffer(download_buffer_object, ...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
static void unmap_downloaded_buffer(download_buffer_object, ...)
|
||||
static bool surface_matches_properties(
|
||||
const std::unique_ptr<vk::render_target> &surface,
|
||||
surface_depth_format format,
|
||||
size_t width, size_t height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
bool check_refs = false)
|
||||
{
|
||||
auto device = vk::get_current_renderer();
|
||||
VkFormat vk_format = vk::get_compatible_depth_surface_format(device->get_formats_support(), format);
|
||||
return int_surface_matches_properties(surface, vk_format, width, height, antialias, check_refs);
|
||||
}
|
||||
|
||||
static vk::render_target *get(const std::unique_ptr<vk::render_target> &tex)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue