This commit is contained in:
kd-11 2026-07-10 00:04:24 +02:00 committed by GitHub
commit 4eabcf1b9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 1202 additions and 810 deletions

View File

@ -1703,6 +1703,48 @@ namespace rsx
}
}
rsx::surface_color_format get_compatible_surface_color_format(u32 gcm_format)
{
switch (gcm_format)
{
case CELL_GCM_TEXTURE_R5G6B5:
return rsx::surface_color_format::r5g6b5;
case CELL_GCM_TEXTURE_A8R8G8B8:
return rsx::surface_color_format::a8r8g8b8;
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
return rsx::surface_color_format::w16z16y16x16;
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
return rsx::surface_color_format::w32z32y32x32;
case CELL_GCM_TEXTURE_A1R5G5B5:
return rsx::surface_color_format::x1r5g5b5_o1r5g5b5;
case CELL_GCM_TEXTURE_B8:
return rsx::surface_color_format::b8;
case CELL_GCM_TEXTURE_G8B8:
return rsx::surface_color_format::g8b8;
case CELL_GCM_TEXTURE_X32_FLOAT:
return rsx::surface_color_format::x32;
default:
fmt::throw_exception("Unhandled surface format 0x%x", gcm_format);
}
}
rsx::surface_depth_format2 get_compatible_surface_depth_format(u32 gcm_format)
{
switch (gcm_format)
{
case RSX_FORMAT_CLASS_DEPTH16_UNORM:
return rsx::surface_depth_format2::z16_uint;
case RSX_FORMAT_CLASS_DEPTH24_UNORM_X8_PACK32:
return rsx::surface_depth_format2::z24s8_uint;
case RSX_FORMAT_CLASS_DEPTH16_FLOAT:
return rsx::surface_depth_format2::z16_float;
case RSX_FORMAT_CLASS_DEPTH24_FLOAT_X8_PACK32:
return rsx::surface_depth_format2::z24s8_float;
default:
fmt::throw_exception("Invalid depth format 0x%x", gcm_format);
}
}
u32 get_max_depth_value(rsx::surface_depth_format2 format)
{
return get_format_block_size_in_bytes(format) == 2 ? 0xFFFF : 0xFFFFFF;

View File

@ -284,6 +284,21 @@ namespace rsx
usz alignment;
};
struct image_section_attributes_t
{
u32 address;
u32 gcm_format;
u32 pitch;
u16 width;
u16 height;
u16 depth;
u16 mipmaps;
u16 slice_h;
u8 bpp;
bool swizzled;
bool edge_clamped;
};
/**
* Get size to store texture in a linear fashion.
* Storage is assumed to use a rowPitchAlignment boundary for every row of texture.
@ -350,6 +365,9 @@ namespace rsx
std::pair<u32, bool> get_compatible_gcm_format(rsx::surface_color_format format);
std::pair<u32, bool> get_compatible_gcm_format(rsx::surface_depth_format2 format);
rsx::surface_color_format get_compatible_surface_color_format(u32 gcm_format);
rsx::surface_depth_format2 get_compatible_surface_depth_format(u32 gcm_format);
format_class classify_format(rsx::surface_depth_format2 format);
format_class classify_format(u32 gcm_format);

View File

@ -532,7 +532,7 @@ namespace rsx
if (!new_surface)
{
ensure(store);
new_surface_storage = Traits::create_new_surface(address, format, width, height, pitch, antialias, scaling_config, std::forward<Args>(extra_params)...);
new_surface_storage = Traits::create_new_surface(command_list, address, format, width, height, pitch, antialias, scaling_config, std::forward<Args>(extra_params)...);
new_surface = Traits::get(new_surface_storage);
Traits::prepare_surface_for_drawing(command_list, new_surface);
allocate_rsx_memory(new_surface);
@ -1027,6 +1027,83 @@ namespace rsx
}
}
// Prepare a render target surface for drawing without binding it to the current RTV/DSV set.
// Useful for transfer operations to ensure watertight writes.
template <typename ...Args>
void prepare_transfer_target(
command_list_type command_list,
surface_type surface,
rsx::surface_access access,
Args&&... extra_params)
{
// We need to reintersect the surface against the surface hierarchy tree to avoid data loss
if (!surface->is_depth_surface()) [[ likely ]]
{
bind_address_as_render_targets(
command_list,
surface->base_addr,
surface->format_info.gcm_color_format,
surface->get_aa_mode(),
surface->get_surface_width(),
surface->get_surface_height(),
surface->get_rsx_pitch(),
surface->get_resolution_scaling_config(),
std::forward<Args>(extra_params)...);
}
else
{
bind_address_as_depth_stencil(
command_list,
surface->base_addr,
surface->format_info.gcm_depth_format,
surface->get_aa_mode(),
surface->get_surface_width(),
surface->get_surface_height(),
surface->get_rsx_pitch(),
surface->get_resolution_scaling_config(),
std::forward<Args>(extra_params)...);
}
ensure(access.is_transfer());
surface->memory_barrier(command_list, access);
}
// Create surface on-demand from an RSX image description
template <typename ...Args>
surface_type create_surface_from_rsx_section(
command_list_type command_list,
const rsx::image_section_attributes_t& attributes,
const rsx::surface_scaling_config_t& scaling_config,
Args&&... extra_params)
{
cache_tag = rsx::get_shared_tag();
if (rsx::classify_format(attributes.gcm_format) == RSX_FORMAT_CLASS_COLOR)
{
return bind_address_as_render_targets(
command_list,
attributes.address,
rsx::get_compatible_surface_color_format(attributes.gcm_format),
rsx::surface_antialiasing::center_1_sample,
attributes.width,
attributes.height,
attributes.pitch,
scaling_config,
std::forward<Args>(extra_params)...);
}
return bind_address_as_depth_stencil(
command_list,
attributes.address,
rsx::get_compatible_surface_depth_format(attributes.gcm_format),
rsx::surface_antialiasing::center_1_sample,
attributes.width,
attributes.height,
attributes.pitch,
{},
std::forward<Args>(extra_params)...);
}
u8 get_color_surface_count() const
{
return static_cast<u8>(m_bound_render_target_ids.size());

View File

@ -12,10 +12,11 @@ namespace rsx
{
enum surface_state_flags : u32
{
ready = 0,
erase_bkgnd = 1,
require_resolve = 2,
require_unresolve = 4
ready = 0x00,
erase_bkgnd = 0x01,
require_resolve = 0x02,
require_unresolve = 0x04,
force_data_load = 0x08
};
enum class surface_sample_layout : u32
@ -146,6 +147,9 @@ namespace rsx
u8 samples_x = 1;
u8 samples_y = 1;
// AA mode
rsx::surface_antialiasing aa_mode = rsx::surface_antialiasing::center_1_sample;
// Scaling configuration
surface_scaling_config_t resolution_scaling_config;
@ -257,6 +261,8 @@ namespace rsx
void set_aa_mode(rsx::surface_antialiasing aa)
{
aa_mode = aa;
switch (aa)
{
case rsx::surface_antialiasing::center_1_sample:
@ -276,6 +282,11 @@ namespace rsx
}
}
rsx::surface_antialiasing get_aa_mode() const
{
return aa_mode;
}
void set_spp(u8 count)
{
switch (count)

View File

@ -1,12 +1,19 @@
#include "stdafx.h"
#include "texture_cache_utils.h"
#include "Emu/RSX/RSXThread.h"
#include "Utilities/address_range.h"
#include "util/fnv_hash.hpp"
#include "texture_cache_utils.h"
#include "texture_cache_helpers.h"
#include "texture_cache_blit_helpers.h"
namespace rsx
{
constexpr u32 min_lockable_data_size = 4096; // Increasing this value has worse results even on systems with pages > 4k
namespace helpers = rsx::texture_cache_helpers;
void buffered_section::init_lockable_range(const address_range32& range)
{
locked_range = range.to_page_range();
@ -215,4 +222,292 @@ namespace rsx
return (fast_hash_internal() == mem_hash);
}
namespace blit_engine_helpers
{
// Applies reverse-scan subpixel correction and computes the mirror/flip adjustments for the source.
void apply_pixel_transforms(
rsx::blit_src_info& src,
const rsx::blit_dst_info& dst,
typeless_xfer& typeless_info,
u32& src_address,
u16& src_w,
u16& src_h,
u8 src_bpp)
{
if (true) // This block is a debug/sanity check and should be optionally disabled with a config option
{
// Do subpixel correction in the special case of reverse scanning
// When reverse scanning, pixel0 is at offset = (dimension - 1)
if (dst.scale_y < 0.f && src.offset_y)
{
if (src.offset_y = (src.height - src.offset_y);
src.offset_y == 1)
{
src.offset_y = 0;
}
}
if (dst.scale_x < 0.f && src.offset_x)
{
if (src.offset_x = (src.width - src.offset_x);
src.offset_x == 1)
{
src.offset_x = 0;
}
}
if ((src_h + src.offset_y) > src.height) [[unlikely]]
{
// TODO: Special case that needs wrapping around (custom blit)
rsx_log.error("Transfer cropped in Y, src_h=%d, offset_y=%d, block_h=%d", src_h, src.offset_y, src.height);
src_h = src.height - src.offset_y;
}
if ((src_w + src.offset_x) > src.width) [[unlikely]]
{
// TODO: Special case that needs wrapping around (custom blit)
rsx_log.error("Transfer cropped in X, src_w=%d, offset_x=%d, block_w=%d", src_w, src.offset_x, src.width);
src_w = src.width - src.offset_x;
}
}
if (dst.scale_y < 0.f)
{
typeless_info.flip_vertical = true;
src_address -= (src.pitch * (src_h - 1));
}
if (dst.scale_x < 0.f)
{
typeless_info.flip_horizontal = true;
src_address += (src.width - src_w) * src_bpp;
}
}
// Given a surface's actual bpp, decide whether the blit side must be typeless and pick its format.
void configure_typeless_format(
/*out*/ bool& is_typeless,
/*out*/ f32& scaling_hint,
/*out*/ u32& gcm_format,
u8 surface_bpp,
u8 blit_bpp,
bool is_argb8,
bool surface_is_depth,
bool is_format_convert)
{
const bool typeless = (surface_bpp != blit_bpp || is_format_convert);
if (!typeless) [[likely]]
{
// Use format as-is
gcm_format = helpers::get_sized_blit_format(is_argb8, surface_is_depth, false);
}
else
{
// Enable type scaling
is_typeless = true;
scaling_hint = static_cast<f32>(surface_bpp) / blit_bpp;
gcm_format = helpers::get_sized_blit_format(is_argb8, false, is_format_convert);
}
}
// Whether a cached surface's format is an acceptable source for a blit.
// Only accept 16-bit data for 16-bit transfers and 32-bit for 32-bit transfers.
// NOTE: some formats are copy-compatible but not scaling-compatible (hence the is_copy_op / dst_is_render_target checks).
bool is_blit_source_format_compatible(u32 gcm_format, bool src_is_argb8, bool is_copy_op, bool dst_is_render_target)
{
switch (gcm_format)
{
case CELL_GCM_TEXTURE_X32_FLOAT:
case CELL_GCM_TEXTURE_Y16_X16:
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
// Should be copy compatible but not scaling compatible
return src_is_argb8 && (is_copy_op || dst_is_render_target);
case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
// Should be copy compatible but not scaling compatible
return src_is_argb8 && (is_copy_op || !dst_is_render_target);
case CELL_GCM_TEXTURE_A8R8G8B8:
case CELL_GCM_TEXTURE_D8R8G8B8:
// Perfect match
return src_is_argb8;
case CELL_GCM_TEXTURE_X16:
case CELL_GCM_TEXTURE_G8B8:
case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_D1R5G5B5:
case CELL_GCM_TEXTURE_R5G5B5A1:
// Copy compatible
return !src_is_argb8 && (is_copy_op || dst_is_render_target);
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
// Copy compatible
return !src_is_argb8 && (is_copy_op || !dst_is_render_target);
case CELL_GCM_TEXTURE_R5G6B5:
// Perfect match
return !src_is_argb8;
default:
return false;
}
}
// Decides whether a transfer into main memory should run on the GPU or fall back to a CPU memcpy.
// Pure heuristic: the caller applies the returned effects (early-out, rtt discard, collision handling).
transfer_configuration configure_transfer_mode(
const rsx::blit_src_info& src,
const rsx::blit_dst_info& dst,
bool dst_is_render_target,
bool is_copy_op,
bool is_format_convert,
bool dst_is_tiled,
bool src_is_tiled,
u16 src_w,
u16 src_h,
u16 dst_w,
u16 dst_h,
u32 dst_address)
{
transfer_configuration config{};
// Determine whether to perform this transfer on CPU or GPU (src data may not be graphical)
const bool is_trivial_copy = is_copy_op && !is_format_convert && !dst.swizzled && !dst_is_tiled && !src_is_tiled;
const bool is_block_transfer = (dst_w == src_w && dst_h == src_h && (src.pitch == dst.pitch || src_h == 1));
const bool is_mirror_op = (dst.scale_x < 0.f || dst.scale_y < 0.f);
// Always use GPU blit if src or dst is in the surface store
if (dst_is_render_target)
{
if (is_trivial_copy && src_h == 1)
{
dst_is_render_target = false;
config.discard_dst_render_target = true;
}
else
{
return config;
}
}
if (is_trivial_copy)
{
// Check if trivial memcpy can perform the same task
// Used to copy programs and arbitrary data to the GPU in some cases
// NOTE: This case overrides the GPU texture scaling option
if (is_block_transfer && !is_mirror_op)
{
config.fall_back_to_cpu = true;
return config;
}
}
if (!g_cfg.video.use_gpu_texture_scaling && !dst_is_tiled && !src_is_tiled)
{
if (dst.swizzled)
{
// Swizzle operation requested. Use fallback
config.fall_back_to_cpu = true;
return config;
}
if (is_trivial_copy && get_location(dst_address) != CELL_GCM_LOCATION_LOCAL)
{
// Trivial copy and the destination is in XDR memory
config.fall_back_to_cpu = true;
return config;
}
}
return config;
}
// Verifies that the memory range defined by [base_address, write_end] actually exists in VM
// The heurestic-defined block_end input is speculative. e.g We may be rendering to one corner of a larger image.
// Returns true if we can use the entire range, false if we can only use the [base_address, write_end] area
bool validate_memory_range(u32 base_address, u32 write_end, u32 block_end)
{
if (block_end <= write_end)
{
return true;
}
// Confirm if the pages actually exist in vm
if (get_location(base_address) == CELL_GCM_LOCATION_LOCAL)
{
const auto vram_end = rsx::get_current_renderer()->local_mem_size + rsx::constants::local_mem_base;
return block_end <= vram_end;
}
// Main memory block validation
return vm::check_addr(write_end, vm::page_readable, (block_end - write_end));
}
// Reverse projects output clip rect back onto the source input.
// This cuts out a post-transfer clip operation at the cost of possible edge bleed.
void reproject_clip_offsets(
rsx::blit_dst_info& dst_info,
areai& src_area,
u16 max_dst_width,
u16 max_dst_height,
f32 scale_x,
f32 scale_y,
const typeless_xfer& typeless_info)
{
// Validate clipping region
if ((dst_info.offset_x + dst_info.clip_x + dst_info.clip_width) > max_dst_width) dst_info.clip_x = 0;
if ((dst_info.offset_y + dst_info.clip_y + dst_info.clip_height) > max_dst_height) dst_info.clip_y = 0;
// Reproject clip offsets onto source to simplify blit
if (dst_info.clip_x || dst_info.clip_y)
{
const u16 scaled_clip_offset_x = static_cast<u16>(dst_info.clip_x / (scale_x * typeless_info.src_scaling_hint));
const u16 scaled_clip_offset_y = static_cast<u16>(dst_info.clip_y / scale_y);
src_area.x1 += scaled_clip_offset_x;
src_area.x2 += scaled_clip_offset_x;
src_area.y1 += scaled_clip_offset_y;
src_area.y2 += scaled_clip_offset_y;
}
}
// Reconcile cross-aspect transfers. Transfers cannot go across aspects due to API limitations.
void reconcile_depth_color_typeless(
typeless_xfer& typeless_info,
bool src_is_argb8,
bool dst_is_argb8)
{
if (typeless_info.src_gcm_format == typeless_info.dst_gcm_format) [[ likely ]]
{
return;
}
const auto src_is_depth = texture_cache_helpers::is_gcm_depth_format(typeless_info.src_gcm_format);
const auto dst_is_depth = helpers::is_gcm_depth_format(typeless_info.dst_gcm_format);
if (src_is_depth == dst_is_depth)
{
return;
}
// Make the depth side typeless because the other side is guaranteed to be color
if (src_is_depth)
{
// SRC is depth, transfer must be done typelessly
if (!typeless_info.src_is_typeless)
{
typeless_info.src_is_typeless = true;
typeless_info.src_gcm_format = helpers::get_sized_blit_format(src_is_argb8, false, false);
}
return;
}
// DST is depth, transfer must be done typelessly
if (!typeless_info.dst_is_typeless)
{
typeless_info.dst_is_typeless = true;
typeless_info.dst_gcm_format = helpers::get_sized_blit_format(dst_is_argb8, false, false);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,80 @@
#pragma once
#include "texture_cache_utils.h"
namespace rsx
{
namespace blit_engine_helpers
{
// Result of the CPU-vs-GPU transfer heuristic for a main-memory destination.
struct transfer_configuration
{
bool fall_back_to_cpu = false; // Abort the GPU path and let the caller memcpy instead
bool discard_dst_render_target = false; // dst was a render target but should be treated as plain memory
};
// Applies reverse-scan subpixel correction and computes the mirror/flip adjustments for the source.
void apply_pixel_transforms(
rsx::blit_src_info& src,
const rsx::blit_dst_info& dst,
typeless_xfer& typeless_info,
u32& src_address,
u16& src_w,
u16& src_h,
u8 src_bpp);
// Given a surface's actual bpp, decide whether the blit side must be typeless and pick its format.
void configure_typeless_format(
/*out*/ bool& is_typeless,
/*out*/ f32& scaling_hint,
/*out*/ u32& gcm_format,
u8 surface_bpp,
u8 blit_bpp,
bool is_argb8,
bool surface_is_depth,
bool is_format_convert);
// Whether a cached surface's format is an acceptable source for a blit.
// Only accept 16-bit data for 16-bit transfers and 32-bit for 32-bit transfers.
// NOTE: some formats are copy-compatible but not scaling-compatible (hence the is_copy_op / dst_is_render_target checks).
bool is_blit_source_format_compatible(u32 gcm_format, bool src_is_argb8, bool is_copy_op, bool dst_is_render_target);
// Decides whether a transfer into main memory should run on the GPU or fall back to a CPU memcpy.
// Pure heuristic: the caller applies the returned effects (early-out, rtt discard, collision handling).
transfer_configuration configure_transfer_mode(
const rsx::blit_src_info& src,
const rsx::blit_dst_info& dst,
bool dst_is_render_target,
bool is_copy_op,
bool is_format_convert,
bool dst_is_tiled,
bool src_is_tiled,
u16 src_w,
u16 src_h,
u16 dst_w,
u16 dst_h,
u32 dst_address);
// Verifies that the memory range defined by [base_address, write_end] actually exists in VM
// The heurestic-defined block_end input is speculative. e.g We may be rendering to one corner of a larger image.
// Returns true if we can use the entire range, false if we can only use the [base_address, write_end] area
bool validate_memory_range(u32 base_address, u32 write_end, u32 block_end);
// Reverse projects output clip rect back onto the source input.
// This cuts out a post-transfer clip operation at the cost of possible edge bleed.
void reproject_clip_offsets(
rsx::blit_dst_info& dst_info,
areai& src_area,
u16 max_dst_width,
u16 max_dst_height,
f32 scale_x,
f32 scale_y,
const typeless_xfer& typeless_info);
// Reconcile cross-aspect transfers. Transfers cannot go across aspects due to API limitations.
void reconcile_depth_color_typeless(
typeless_xfer& typeless_info,
bool src_is_argb8,
bool dst_is_argb8);
}
}

View File

@ -46,21 +46,6 @@ namespace rsx
blit_image_static, // Variant of the copy command that does scaling instead of copying
};
struct image_section_attributes_t
{
u32 address;
u32 gcm_format;
u32 pitch;
u16 width;
u16 height;
u16 depth;
u16 mipmaps;
u16 slice_h;
u8 bpp;
bool swizzled;
bool edge_clamped;
};
struct blit_op_result
{
bool succeeded = false;

View File

@ -325,10 +325,6 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /*
if (!m_rtts.orphaned_surfaces.empty())
{
gl::texture::format format;
gl::texture::type type;
bool swap_bytes;
for (auto& [base_addr, surface] : m_rtts.orphaned_surfaces)
{
bool lock = surface->is_depth_surface() ? !!g_cfg.video.write_depth_buffer :
@ -354,31 +350,15 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /*
continue;
}
if (surface->is_depth_surface())
{
const auto depth_format_gl = rsx::internals::surface_depth_format_to_gl(surface->get_surface_depth_format());
format = depth_format_gl.format;
type = depth_format_gl.type;
swap_bytes = (type != gl::texture::type::uint_24_8);
}
else
{
const auto color_format_gl = rsx::internals::surface_color_format_to_gl(surface->get_surface_color_format());
format = color_format_gl.format;
type = color_format_gl.type;
swap_bytes = color_format_gl.swap_bytes;
}
m_gl_texture_cache.lock_memory_region(
cmd, surface, surface->get_memory_range(), false,
surface->get_surface_width<rsx::surface_metrics::pixels>(), surface->get_surface_height<rsx::surface_metrics::pixels>(), surface->get_rsx_pitch(),
format, type, swap_bytes);
surface);
}
m_rtts.orphaned_surfaces.clear();
}
const auto color_format = rsx::internals::surface_color_format_to_gl(m_framebuffer_layout.color_format);
for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i)
{
if (!m_surface_info[i].address || !m_surface_info[i].pitch) continue;
@ -390,7 +370,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /*
m_gl_texture_cache.lock_memory_region(
cmd, m_rtts.m_bound_render_targets[i].second, surface_range, true,
m_surface_info[i].width, m_surface_info[i].height, m_surface_info[i].pitch,
color_format.format, color_format.type, color_format.swap_bytes);
m_rtts.m_bound_render_targets[i].second);
}
else
{
@ -403,11 +383,10 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /*
const auto surface_range = m_depth_surface_info.get_memory_range();
if (g_cfg.video.write_depth_buffer)
{
const auto depth_format_gl = rsx::internals::surface_depth_format_to_gl(m_framebuffer_layout.depth_format);
m_gl_texture_cache.lock_memory_region(
cmd, m_rtts.m_bound_depth_stencil.second, surface_range, true,
m_depth_surface_info.width, m_depth_surface_info.height, m_depth_surface_info.pitch,
depth_format_gl.format, depth_format_gl.type, depth_format_gl.type != gl::texture::type::uint_24_8);
m_rtts.m_bound_depth_stencil.second);
}
else
{
@ -472,15 +451,17 @@ void gl::render_target::load_memory(gl::command_context& cmd)
}
}
state_flags &= ~rsx::surface_state_flags::erase_bkgnd;
state_flags &= ~(rsx::surface_state_flags::erase_bkgnd | rsx::surface_state_flags::force_data_load);
}
void gl::render_target::initialize_memory(gl::command_context& cmd, rsx::surface_access access)
{
const bool memory_load = is_depth_surface() ?
const bool read_buffers_config = is_depth_surface() ?
!!g_cfg.video.read_depth_buffer :
!!g_cfg.video.read_color_buffers;
const bool memory_load = (state_flags & rsx::surface_state_flags::force_data_load) || read_buffers_config;
if (!memory_load)
{
clear_memory(cmd);

View File

@ -135,12 +135,12 @@ struct gl_render_target_traits
static
std::unique_ptr<gl::render_target> create_new_surface(
gl::command_context&,
u32 address,
rsx::surface_color_format surface_color_format,
usz width, usz height, usz pitch,
rsx::surface_antialiasing antialias,
const rsx::surface_scaling_config_t& resolution_scaling_config
)
const rsx::surface_scaling_config_t& resolution_scaling_config)
{
auto format = rsx::internals::surface_color_format_to_gl(surface_color_format);
const auto [width_, height_] = rsx::apply_resolution_scale<true>(resolution_scaling_config, static_cast<u16>(width), static_cast<u16>(height));
@ -181,12 +181,12 @@ struct gl_render_target_traits
static
std::unique_ptr<gl::render_target> create_new_surface(
u32 address,
rsx::surface_depth_format2 surface_depth_format,
usz width, usz height, usz pitch,
rsx::surface_antialiasing antialias,
const rsx::surface_scaling_config_t& resolution_scaling_config
)
gl::command_context&,
u32 address,
rsx::surface_depth_format2 surface_depth_format,
usz width, usz height, usz pitch,
rsx::surface_antialiasing antialias,
const rsx::surface_scaling_config_t& resolution_scaling_config)
{
auto format = rsx::internals::surface_depth_format_to_gl(surface_depth_format);
const auto [width_, height_] = rsx::apply_resolution_scale<true>(resolution_scaling_config, static_cast<u16>(width), static_cast<u16>(height));
@ -252,7 +252,7 @@ struct gl_render_target_traits
sink->resolution_scaling_config = scaling_config;
sink->set_name(fmt::format("SINK_%u@0x%x", sink->id(), address));
sink->set_spp(ref->get_spp());
sink->set_aa_mode(ref->get_aa_mode());
sink->set_native_pitch(static_cast<u32>(prev.width) * ref->get_bpp() * ref->samples_x);
sink->set_rsx_pitch(ref->get_rsx_pitch());
sink->set_surface_dimensions(prev.width, prev.height, ref->get_rsx_pitch());

View File

@ -120,6 +120,30 @@ namespace gl
baseclass::on_section_resources_created();
}
void create(u16 w, u16 h, u16 depth, u16 mipmaps, gl::texture* image, u32 rsx_pitch, bool managed, const gl::render_target* surface)
{
gl::texture::format format;
gl::texture::type type;
bool swap_bytes;
if (surface->is_depth_surface())
{
const auto depth_format_gl = rsx::internals::surface_depth_format_to_gl(surface->get_surface_depth_format());
format = depth_format_gl.format;
type = depth_format_gl.type;
swap_bytes = (type != gl::texture::type::uint_24_8);
}
else
{
const auto color_format_gl = rsx::internals::surface_color_format_to_gl(surface->get_surface_color_format());
format = color_format_gl.format;
type = color_format_gl.type;
swap_bytes = color_format_gl.swap_bytes;
}
create(w, h, depth, mipmaps, image, rsx_pitch, managed, format, type, swap_bytes);
}
void set_dimensions(u32 width, u32 height, u32 /*depth*/, u32 pitch)
{
this->width = width;

View File

@ -2480,8 +2480,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
m_framebuffer_layout.target, m_framebuffer_layout.aa_mode, m_framebuffer_layout.raster_type,
m_framebuffer_layout.color_addresses, m_framebuffer_layout.zeta_address,
m_framebuffer_layout.actual_color_pitch, m_framebuffer_layout.actual_zeta_pitch,
resolution_scaling_config,
(*m_device), *m_current_command_buffer);
resolution_scaling_config);
// Reset framebuffer information
const auto color_bpp = get_format_block_size_in_bytes(m_framebuffer_layout.color_format);
@ -2572,9 +2571,6 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
if (!m_rtts.orphaned_surfaces.empty())
{
u32 gcm_format;
bool swap_bytes;
for (auto& [base_addr, surface] : m_rtts.orphaned_surfaces)
{
bool lock = surface->is_depth_surface() ? !!g_cfg.video.write_depth_buffer :
@ -2600,28 +2596,15 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
continue;
}
if (surface->is_depth_surface())
{
gcm_format = (surface->get_surface_depth_format() != rsx::surface_depth_format::z16) ? CELL_GCM_TEXTURE_DEPTH16 : CELL_GCM_TEXTURE_DEPTH24_D8;
swap_bytes = true;
}
else
{
auto info = get_compatible_gcm_format(surface->get_surface_color_format());
gcm_format = info.first;
swap_bytes = info.second;
}
m_texture_cache.lock_memory_region(
*m_current_command_buffer, surface, surface->get_memory_range(), false,
surface->get_surface_width<rsx::surface_metrics::pixels>(), surface->get_surface_height<rsx::surface_metrics::pixels>(), surface->get_rsx_pitch(),
gcm_format, swap_bytes);
surface);
}
m_rtts.orphaned_surfaces.clear();
}
const auto color_fmt_info = get_compatible_gcm_format(m_framebuffer_layout.color_format);
for (u8 index : m_draw_buffers)
{
if (!m_surface_info[index].address || !m_surface_info[index].pitch) continue;
@ -2632,7 +2615,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
m_texture_cache.lock_memory_region(
*m_current_command_buffer, m_rtts.m_bound_render_targets[index].second, surface_range, true,
m_surface_info[index].width, m_surface_info[index].height, m_framebuffer_layout.actual_color_pitch[index],
color_fmt_info.first, color_fmt_info.second);
m_rtts.m_bound_render_targets[index].second);
}
else
{
@ -2645,10 +2628,10 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
const utils::address_range32 surface_range = m_depth_surface_info.get_memory_range();
if (g_cfg.video.write_depth_buffer)
{
const u32 gcm_format = (m_depth_surface_info.depth_format == rsx::surface_depth_format::z16) ? CELL_GCM_TEXTURE_DEPTH16 : CELL_GCM_TEXTURE_DEPTH24_D8;
m_texture_cache.lock_memory_region(
*m_current_command_buffer, m_rtts.m_bound_depth_stencil.second, surface_range, true,
m_depth_surface_info.width, m_depth_surface_info.height, m_framebuffer_layout.actual_zeta_pitch, gcm_format, true);
m_depth_surface_info.width, m_depth_surface_info.height, m_framebuffer_layout.actual_zeta_pitch,
m_rtts.m_bound_depth_stencil.second);
}
else
{

View File

@ -794,13 +794,16 @@ namespace vk
}
}
state_flags &= ~rsx::surface_state_flags::erase_bkgnd;
state_flags &= ~(rsx::surface_state_flags::erase_bkgnd | rsx::surface_state_flags::force_data_load);
}
void render_target::initialize_memory(vk::command_buffer& cmd, rsx::surface_access access)
{
const bool is_depth = is_depth_surface();
const bool should_read_buffers = is_depth ? !!g_cfg.video.read_depth_buffer : !!g_cfg.video.read_color_buffers;
const bool read_buffers_config = is_depth_surface() ?
!!g_cfg.video.read_depth_buffer :
!!g_cfg.video.read_color_buffers;
const bool should_read_buffers = (state_flags & rsx::surface_state_flags::force_data_load) || read_buffers_config;
if (!should_read_buffers)
{
@ -938,7 +941,8 @@ namespace vk
}
const bool is_depth = is_depth_surface();
const bool should_read_buffers = is_depth ? !!g_cfg.video.read_depth_buffer : !!g_cfg.video.read_color_buffers;
const bool read_buffers_config = is_depth ? !!g_cfg.video.read_depth_buffer : !!g_cfg.video.read_color_buffers;
const bool should_read_buffers = (state_flags & rsx::surface_state_flags::force_data_load) || read_buffers_config;
if (should_read_buffers)
{

View File

@ -196,12 +196,12 @@ namespace vk
}
static std::unique_ptr<vk::render_target> create_new_surface(
const vk::command_buffer& cmd,
u32 address,
rsx::surface_color_format format,
usz width, usz height, usz pitch,
rsx::surface_antialiasing antialias,
const rsx::surface_scaling_config_t& resolution_scaling_config,
vk::render_device& device, vk::command_buffer& cmd)
const rsx::surface_scaling_config_t& resolution_scaling_config)
{
const auto fmt = vk::get_compatible_surface_format(format);
VkFormat requested_format = fmt.first;
@ -234,7 +234,8 @@ namespace vk
std::unique_ptr<vk::render_target> rtt;
const auto [width_, height_] = rsx::apply_resolution_scale<true>(resolution_scaling_config, static_cast<u16>(width), static_cast<u16>(height));
rtt = std::make_unique<vk::render_target>(device, device.get_memory_mapping().device_local,
auto pdev = vk::get_current_renderer();
rtt = std::make_unique<vk::render_target>(*pdev, pdev->get_memory_mapping().device_local,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VK_IMAGE_TYPE_2D,
requested_format,
@ -268,14 +269,15 @@ namespace vk
}
static std::unique_ptr<vk::render_target> create_new_surface(
const vk::command_buffer& cmd,
u32 address,
rsx::surface_depth_format2 format,
usz width, usz height, usz pitch,
rsx::surface_antialiasing antialias,
const rsx::surface_scaling_config_t& resolution_scaling_config,
vk::render_device& device, vk::command_buffer& cmd)
const rsx::surface_scaling_config_t& resolution_scaling_config)
{
const VkFormat requested_format = vk::get_compatible_depth_surface_format(device.get_formats_support(), format);
auto pdev = vk::get_current_renderer();
const VkFormat requested_format = vk::get_compatible_depth_surface_format(pdev->get_formats_support(), format);
u8 samples;
rsx::surface_sample_layout sample_layout;
@ -301,7 +303,7 @@ namespace vk
std::unique_ptr<vk::render_target> ds;
const auto [width_, height_] = rsx::apply_resolution_scale<true>(resolution_scaling_config, static_cast<u16>(width), static_cast<u16>(height));
ds = std::make_unique<vk::render_target>(device, device.get_memory_mapping().device_local,
ds = std::make_unique<vk::render_target>(*pdev, pdev->get_memory_mapping().device_local,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VK_IMAGE_TYPE_2D,
requested_format,
@ -366,7 +368,7 @@ namespace vk
sink->sample_layout = ref->sample_layout;
sink->resolution_scaling_config = scaling_config;
sink->set_spp(ref->get_spp());
sink->set_aa_mode(ref->get_aa_mode());
sink->format_info = ref->format_info;
sink->memory_usage_flags = rsx::surface_usage_flags::storage;
sink->state_flags = rsx::surface_state_flags::erase_bkgnd;

View File

@ -37,7 +37,7 @@ namespace vk
std::unique_ptr<vk::viewable_image> managed_texture = nullptr;
//DMA relevant data
// DMA relevant data
std::unique_ptr<vk::event> dma_fence;
vk::render_device* m_device = nullptr;
vk::viewable_image* vram_texture = nullptr;
@ -99,6 +99,26 @@ namespace vk
baseclass::on_section_resources_created();
}
void create(u16 w, u16 h, u16 depth, u16 mipmaps, vk::image* image, u32 rsx_pitch, bool managed, const vk::render_target* surface)
{
u32 gcm_format;
bool swap_bytes;
if (surface->is_depth_surface())
{
gcm_format = (surface->get_surface_depth_format() != rsx::surface_depth_format::z16) ? CELL_GCM_TEXTURE_DEPTH16 : CELL_GCM_TEXTURE_DEPTH24_D8;
swap_bytes = true;
}
else
{
auto info = get_compatible_gcm_format(surface->get_surface_color_format());
gcm_format = info.first;
swap_bytes = info.second;
}
create(w, h, depth, mipmaps, image, rsx_pitch, managed, gcm_format, swap_bytes);
}
void release_dma_resources()
{
if (dma_fence)

View File

@ -680,6 +680,7 @@
<ClInclude Include="Emu\RSX\Common\bitfield.hpp" />
<ClInclude Include="Emu\RSX\Common\buffer_stream.hpp" />
<ClInclude Include="Emu\RSX\Common\reverse_ptr.hpp" />
<ClInclude Include="Emu\RSX\Common\texture_cache_blit_helpers.h" />
<ClInclude Include="Emu\RSX\Common\tiled_dma_copy.hpp" />
<ClInclude Include="Emu\RSX\Common\expected.hpp" />
<ClInclude Include="Emu\RSX\Common\io_buffer.h" />

View File

@ -2950,6 +2950,9 @@
<ClInclude Include="Emu\Cell\Modules\libsvc1d.h">
<Filter>Emu\Cell\Modules</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\Common\texture_cache_blit_helpers.h">
<Filter>Emu\GPU\RSX\Common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">