mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-26 04:32:35 +01:00
rsx: Refactor and fix framebuffer layout checks
- Refactors shared code back into rsx core - Adds extra check to avoid contest confusion
This commit is contained in:
parent
0267221586
commit
d0165290b6
@ -173,6 +173,12 @@ namespace
|
|||||||
|
|
||||||
void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool skip_reading)
|
void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool skip_reading)
|
||||||
{
|
{
|
||||||
|
if (m_framebuffer_state_contested && (m_framebuffer_contest_type != context))
|
||||||
|
{
|
||||||
|
// Clear commands affect contested memory
|
||||||
|
m_rtts_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (draw_fbo && !m_rtts_dirty)
|
if (draw_fbo && !m_rtts_dirty)
|
||||||
{
|
{
|
||||||
set_viewport();
|
set_viewport();
|
||||||
@ -180,221 +186,41 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_rtts_dirty = false;
|
m_rtts_dirty = false;
|
||||||
zcull_surface_active = false;
|
|
||||||
|
|
||||||
const u16 clip_horizontal = rsx::method_registers.surface_clip_width();
|
|
||||||
const u16 clip_vertical = rsx::method_registers.surface_clip_height();
|
|
||||||
const u16 clip_x = rsx::method_registers.surface_clip_origin_x();
|
|
||||||
const u16 clip_y = rsx::method_registers.surface_clip_origin_y();
|
|
||||||
|
|
||||||
framebuffer_status_valid = false;
|
framebuffer_status_valid = false;
|
||||||
m_framebuffer_state_contested = false;
|
m_framebuffer_state_contested = false;
|
||||||
|
|
||||||
if (clip_horizontal == 0 || clip_vertical == 0)
|
const auto layout = get_framebuffer_layout(context);
|
||||||
|
if (!framebuffer_status_valid)
|
||||||
{
|
{
|
||||||
LOG_ERROR(RSX, "Invalid framebuffer setup, w=%d, h=%d", clip_horizontal, clip_vertical);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto surface_addresses = get_color_surface_addresses();
|
if (draw_fbo && layout.ignore_change)
|
||||||
auto depth_address = get_zeta_surface_address();
|
|
||||||
|
|
||||||
const auto pitchs = get_pitchs();
|
|
||||||
const auto zeta_pitch = rsx::method_registers.surface_z_pitch();
|
|
||||||
const auto surface_format = rsx::method_registers.surface_color();
|
|
||||||
const auto depth_format = rsx::method_registers.surface_depth_fmt();
|
|
||||||
const auto target = rsx::method_registers.surface_color_target();
|
|
||||||
|
|
||||||
const auto aa_mode = rsx::method_registers.surface_antialias();
|
|
||||||
const u32 aa_factor_u = (aa_mode == rsx::surface_antialiasing::center_1_sample) ? 1 : 2;
|
|
||||||
const u32 aa_factor_v = (aa_mode == rsx::surface_antialiasing::center_1_sample || aa_mode == rsx::surface_antialiasing::diagonal_centered_2_samples) ? 1 : 2;
|
|
||||||
|
|
||||||
//NOTE: Its is possible that some renders are done on a swizzled context. Pitch is meaningless in that case
|
|
||||||
//Seen in Nier (color) and GT HD concept (z buffer)
|
|
||||||
//Restriction is that the dimensions are powers of 2. Also, dimensions are passed via log2w and log2h entries
|
|
||||||
const auto required_zeta_pitch = std::max<u32>((u32)(depth_format == rsx::surface_depth_format::z16 ? clip_horizontal * 2 : clip_horizontal * 4) * aa_factor_u, 64u);
|
|
||||||
const auto required_color_pitch = std::max<u32>((u32)rsx::utility::get_packed_pitch(surface_format, clip_horizontal) * aa_factor_u, 64u);
|
|
||||||
const bool stencil_test_enabled = depth_format == rsx::surface_depth_format::z24s8 && rsx::method_registers.stencil_test_enabled();
|
|
||||||
const auto lg2w = rsx::method_registers.surface_log2_width();
|
|
||||||
const auto lg2h = rsx::method_registers.surface_log2_height();
|
|
||||||
const auto clipw_log2 = (u32)floor(log2(clip_horizontal));
|
|
||||||
const auto cliph_log2 = (u32)floor(log2(clip_vertical));
|
|
||||||
|
|
||||||
if (depth_address)
|
|
||||||
{
|
{
|
||||||
if (!rsx::method_registers.depth_test_enabled() &&
|
// Nothing has changed, we're still using the same framebuffer
|
||||||
!stencil_test_enabled &&
|
// Update flags to match current
|
||||||
target != rsx::surface_target::none)
|
for (u32 index = 0; index < 4; index++)
|
||||||
{
|
{
|
||||||
//Disable depth buffer if depth testing is not enabled, unless a clear command is targeting the depth buffer
|
if (auto surface = std::get<1>(m_rtts.m_bound_render_targets[index]))
|
||||||
const bool is_depth_clear = !!(context & rsx::framebuffer_creation_context::context_clear_depth);
|
|
||||||
if (!is_depth_clear)
|
|
||||||
{
|
{
|
||||||
depth_address = 0;
|
surface->write_aa_mode = layout.aa_mode;
|
||||||
m_framebuffer_state_contested = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth_address && zeta_pitch < required_zeta_pitch)
|
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil))
|
||||||
{
|
{
|
||||||
if (lg2w < clipw_log2 || lg2h < cliph_log2)
|
ds->write_aa_mode = layout.aa_mode;
|
||||||
{
|
|
||||||
//Cannot fit
|
|
||||||
depth_address = 0;
|
|
||||||
|
|
||||||
if (lg2w > 0 || lg2h > 0)
|
|
||||||
{
|
|
||||||
//Something was actually declared for the swizzle context dimensions
|
|
||||||
LOG_WARNING(RSX, "Invalid swizzled context depth surface dims, LG2W=%d, LG2H=%d, clip_w=%d, clip_h=%d", lg2w, lg2h, clip_horizontal, clip_vertical);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_TRACE(RSX, "Swizzled context depth surface, LG2W=%d, LG2H=%d, clip_w=%d, clip_h=%d", lg2w, lg2h, clip_horizontal, clip_vertical);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &index : rsx::utility::get_rtt_indexes(target))
|
|
||||||
{
|
|
||||||
if (pitchs[index] < required_color_pitch)
|
|
||||||
{
|
|
||||||
if (lg2w < clipw_log2 || lg2h < cliph_log2)
|
|
||||||
{
|
|
||||||
surface_addresses[index] = 0;
|
|
||||||
|
|
||||||
if (lg2w > 0 || lg2h > 0)
|
|
||||||
{
|
|
||||||
//Something was actually declared for the swizzle context dimensions
|
|
||||||
LOG_WARNING(RSX, "Invalid swizzled context color surface dims, LG2W=%d, LG2H=%d, clip_w=%d, clip_h=%d", lg2w, lg2h, clip_horizontal, clip_vertical);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_TRACE(RSX, "Swizzled context color surface, LG2W=%d, LG2H=%d, clip_w=%d, clip_h=%d", lg2w, lg2h, clip_horizontal, clip_vertical);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface_addresses[index] == depth_address)
|
|
||||||
{
|
|
||||||
LOG_TRACE(RSX, "Framebuffer at 0x%X has aliasing color/depth targets, zeta_pitch = %d, color_pitch=%d", depth_address, zeta_pitch, pitchs[index]);
|
|
||||||
//TODO: Research clearing both depth AND color
|
|
||||||
//TODO: If context is creation_draw, deal with possibility of a lost buffer clear
|
|
||||||
if (context == rsx::framebuffer_creation_context::context_clear_depth ||
|
|
||||||
rsx::method_registers.depth_test_enabled() || stencil_test_enabled ||
|
|
||||||
(!rsx::method_registers.color_write_enabled() && rsx::method_registers.depth_write_enabled()))
|
|
||||||
{
|
|
||||||
// Use address for depth data
|
|
||||||
surface_addresses[index] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Use address for color data
|
|
||||||
depth_address = 0;
|
|
||||||
m_framebuffer_state_contested = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (surface_addresses[index])
|
|
||||||
framebuffer_status_valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!framebuffer_status_valid && !depth_address)
|
|
||||||
{
|
|
||||||
LOG_WARNING(RSX, "Framebuffer setup failed. Draw calls may have been lost");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Window (raster) offsets
|
m_rtts.prepare_render_target(nullptr, layout.color_format, layout.depth_format, layout.width, layout.height,
|
||||||
const auto window_offset_x = rsx::method_registers.window_offset_x();
|
layout.target, layout.color_addresses, layout.zeta_address);
|
||||||
const auto window_offset_y = rsx::method_registers.window_offset_y();
|
|
||||||
const auto window_clip_width = rsx::method_registers.window_clip_horizontal();
|
|
||||||
const auto window_clip_height = rsx::method_registers.window_clip_vertical();
|
|
||||||
|
|
||||||
const auto bpp = get_format_block_size_in_bytes(surface_format);
|
|
||||||
|
|
||||||
if (window_offset_x || window_offset_y)
|
|
||||||
{
|
|
||||||
//Window offset is what affects the raster position!
|
|
||||||
//Tested with Turbo: Super stunt squad that only changes the window offset to declare new framebuffers
|
|
||||||
//Sampling behavior clearly indicates the addresses are expected to have changed
|
|
||||||
if (auto clip_type = rsx::method_registers.window_clip_type())
|
|
||||||
LOG_ERROR(RSX, "Unknown window clip type 0x%X" HERE, clip_type);
|
|
||||||
|
|
||||||
for (const auto &index : rsx::utility::get_rtt_indexes(target))
|
|
||||||
{
|
|
||||||
if (surface_addresses[index])
|
|
||||||
{
|
|
||||||
const u32 window_offset_bytes = (std::max<u32>(pitchs[index], required_color_pitch) * window_offset_y) + ((aa_factor_u * bpp) * window_offset_x);
|
|
||||||
surface_addresses[index] += window_offset_bytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth_address)
|
|
||||||
{
|
|
||||||
const auto depth_bpp = depth_format == rsx::surface_depth_format::z16 ? 2 : 4;
|
|
||||||
depth_address += (std::max<u32>(zeta_pitch, required_zeta_pitch) * window_offset_y) + ((aa_factor_u * depth_bpp) * window_offset_x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((window_clip_width && window_clip_width < clip_horizontal) ||
|
|
||||||
(window_clip_height && window_clip_height < clip_vertical))
|
|
||||||
{
|
|
||||||
LOG_ERROR(RSX, "Unexpected window clip dimensions: window_clip=%dx%d, surface_clip=%dx%d",
|
|
||||||
window_clip_width, window_clip_height, clip_horizontal, clip_vertical);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (draw_fbo)
|
|
||||||
{
|
|
||||||
bool really_changed = false;
|
|
||||||
auto sz = draw_fbo.get_extents();
|
|
||||||
|
|
||||||
if (sz.width == clip_horizontal && sz.height == clip_vertical)
|
|
||||||
{
|
|
||||||
for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i)
|
|
||||||
{
|
|
||||||
if (m_surface_info[i].address != surface_addresses[i])
|
|
||||||
{
|
|
||||||
really_changed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!really_changed)
|
|
||||||
{
|
|
||||||
if (depth_address == m_depth_surface_info.address)
|
|
||||||
{
|
|
||||||
// Nothing has changed, we're still using the same framebuffer
|
|
||||||
// Update flags to match current
|
|
||||||
|
|
||||||
const auto aa_mode = rsx::method_registers.surface_antialias();
|
|
||||||
|
|
||||||
for (u32 index = 0; index < 4; index++)
|
|
||||||
{
|
|
||||||
if (auto surface = std::get<1>(m_rtts.m_bound_render_targets[index]))
|
|
||||||
{
|
|
||||||
surface->write_aa_mode = aa_mode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil))
|
|
||||||
{
|
|
||||||
ds->write_aa_mode = aa_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_rtts.prepare_render_target(nullptr, surface_format, depth_format, clip_horizontal, clip_vertical,
|
|
||||||
target, surface_addresses, depth_address);
|
|
||||||
|
|
||||||
draw_fbo.recreate();
|
draw_fbo.recreate();
|
||||||
draw_fbo.bind();
|
draw_fbo.bind();
|
||||||
draw_fbo.set_extents({ (int)clip_horizontal, (int)clip_vertical });
|
draw_fbo.set_extents({ (int)layout.width, (int)layout.height });
|
||||||
|
|
||||||
bool old_format_found = false;
|
bool old_format_found = false;
|
||||||
gl::texture::format old_format;
|
gl::texture::format old_format;
|
||||||
@ -421,13 +247,13 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||||||
auto rtt = std::get<1>(m_rtts.m_bound_render_targets[i]);
|
auto rtt = std::get<1>(m_rtts.m_bound_render_targets[i]);
|
||||||
draw_fbo.color[i] = *rtt;
|
draw_fbo.color[i] = *rtt;
|
||||||
|
|
||||||
rtt->set_rsx_pitch(pitchs[i]);
|
rtt->set_rsx_pitch(layout.color_pitch[i]);
|
||||||
m_surface_info[i] = { surface_addresses[i], std::max(pitchs[i], required_color_pitch), false, surface_format, depth_format, clip_horizontal, clip_vertical };
|
m_surface_info[i] = { layout.color_addresses[i], layout.actual_color_pitch[i], false, layout.color_format, layout.depth_format, layout.width, layout.height };
|
||||||
|
|
||||||
rtt->tile = find_tile(color_offsets[i], color_locations[i]);
|
rtt->tile = find_tile(color_offsets[i], color_locations[i]);
|
||||||
rtt->write_aa_mode = aa_mode;
|
rtt->write_aa_mode = layout.aa_mode;
|
||||||
m_gl_texture_cache.notify_surface_changed(surface_addresses[i]);
|
m_gl_texture_cache.notify_surface_changed(m_surface_info[i].address);
|
||||||
m_gl_texture_cache.tag_framebuffer(surface_addresses[i]);
|
m_gl_texture_cache.tag_framebuffer(m_surface_info[i].address);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_surface_info[i] = {};
|
m_surface_info[i] = {};
|
||||||
@ -445,18 +271,17 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto ds = std::get<1>(m_rtts.m_bound_depth_stencil);
|
auto ds = std::get<1>(m_rtts.m_bound_depth_stencil);
|
||||||
if (depth_format == rsx::surface_depth_format::z24s8)
|
if (layout.depth_format == rsx::surface_depth_format::z24s8)
|
||||||
draw_fbo.depth_stencil = *ds;
|
draw_fbo.depth_stencil = *ds;
|
||||||
else
|
else
|
||||||
draw_fbo.depth = *ds;
|
draw_fbo.depth = *ds;
|
||||||
|
|
||||||
std::get<1>(m_rtts.m_bound_depth_stencil)->set_rsx_pitch(rsx::method_registers.surface_z_pitch());
|
std::get<1>(m_rtts.m_bound_depth_stencil)->set_rsx_pitch(rsx::method_registers.surface_z_pitch());
|
||||||
m_depth_surface_info = { depth_address, std::max(zeta_pitch, required_zeta_pitch), true, surface_format, depth_format, clip_horizontal, clip_vertical };
|
m_depth_surface_info = { layout.zeta_address, layout.actual_zeta_pitch, true, layout.color_format, layout.depth_format, layout.width, layout.height };
|
||||||
|
|
||||||
ds->write_aa_mode = aa_mode;
|
ds->write_aa_mode = layout.aa_mode;
|
||||||
m_gl_texture_cache.notify_surface_changed(depth_address);
|
m_gl_texture_cache.notify_surface_changed(layout.zeta_address);
|
||||||
|
m_gl_texture_cache.tag_framebuffer(layout.zeta_address);
|
||||||
m_gl_texture_cache.tag_framebuffer(depth_address);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_depth_surface_info = {};
|
m_depth_surface_info = {};
|
||||||
@ -502,13 +327,13 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||||||
//Mark buffer regions as NO_ACCESS on Cell visible side
|
//Mark buffer regions as NO_ACCESS on Cell visible side
|
||||||
if (g_cfg.video.write_color_buffers)
|
if (g_cfg.video.write_color_buffers)
|
||||||
{
|
{
|
||||||
auto color_format = rsx::internals::surface_color_format_to_gl(surface_format);
|
auto color_format = rsx::internals::surface_color_format_to_gl(layout.color_format);
|
||||||
|
|
||||||
for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i)
|
for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i)
|
||||||
{
|
{
|
||||||
if (!m_surface_info[i].address || !m_surface_info[i].pitch) continue;
|
if (!m_surface_info[i].address || !m_surface_info[i].pitch) continue;
|
||||||
|
|
||||||
const u32 range = m_surface_info[i].pitch * m_surface_info[i].height * aa_factor_v;
|
const u32 range = m_surface_info[i].pitch * m_surface_info[i].height * layout.aa_factors[1];
|
||||||
m_gl_texture_cache.lock_memory_region(std::get<1>(m_rtts.m_bound_render_targets[i]), m_surface_info[i].address, range, m_surface_info[i].width, m_surface_info[i].height, m_surface_info[i].pitch,
|
m_gl_texture_cache.lock_memory_region(std::get<1>(m_rtts.m_bound_render_targets[i]), m_surface_info[i].address, range, 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);
|
color_format.format, color_format.type, color_format.swap_bytes);
|
||||||
}
|
}
|
||||||
@ -518,8 +343,8 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||||||
{
|
{
|
||||||
if (m_depth_surface_info.address && m_depth_surface_info.pitch)
|
if (m_depth_surface_info.address && m_depth_surface_info.pitch)
|
||||||
{
|
{
|
||||||
const auto depth_format_gl = rsx::internals::surface_depth_format_to_gl(depth_format);
|
const auto depth_format_gl = rsx::internals::surface_depth_format_to_gl(layout.depth_format);
|
||||||
const u32 range = m_depth_surface_info.pitch * m_depth_surface_info.height * aa_factor_v;
|
const u32 range = m_depth_surface_info.pitch * m_depth_surface_info.height * layout.aa_factors[1];
|
||||||
m_gl_texture_cache.lock_memory_region(std::get<1>(m_rtts.m_bound_depth_stencil), m_depth_surface_info.address, range, m_depth_surface_info.width, m_depth_surface_info.height, m_depth_surface_info.pitch,
|
m_gl_texture_cache.lock_memory_region(std::get<1>(m_rtts.m_bound_depth_stencil), m_depth_surface_info.address, range, m_depth_surface_info.width, m_depth_surface_info.height, m_depth_surface_info.pitch,
|
||||||
depth_format_gl.format, depth_format_gl.type, true);
|
depth_format_gl.format, depth_format_gl.type, true);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "Common/BufferUtils.h"
|
#include "Common/BufferUtils.h"
|
||||||
#include "Common/texture_cache.h"
|
#include "Common/texture_cache.h"
|
||||||
|
#include "Common/surface_store.h"
|
||||||
#include "Capture/rsx_capture.h"
|
#include "Capture/rsx_capture.h"
|
||||||
#include "rsx_methods.h"
|
#include "rsx_methods.h"
|
||||||
#include "rsx_utils.h"
|
#include "rsx_utils.h"
|
||||||
@ -1443,6 +1444,240 @@ namespace rsx
|
|||||||
return rsx::get_address(offset_zeta, m_context_dma_z);
|
return rsx::get_address(offset_zeta, m_context_dma_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
framebuffer_layout thread::get_framebuffer_layout(rsx::framebuffer_creation_context context)
|
||||||
|
{
|
||||||
|
framebuffer_layout layout;
|
||||||
|
memset(&layout, 0, sizeof(layout));
|
||||||
|
|
||||||
|
layout.ignore_change = true;
|
||||||
|
layout.width = rsx::method_registers.surface_clip_width();
|
||||||
|
layout.height = rsx::method_registers.surface_clip_height();
|
||||||
|
|
||||||
|
framebuffer_status_valid = false;
|
||||||
|
m_framebuffer_state_contested = false;
|
||||||
|
m_framebuffer_contest_type = context;
|
||||||
|
|
||||||
|
if (layout.width == 0 || layout.height == 0)
|
||||||
|
{
|
||||||
|
LOG_TRACE(RSX, "Invalid framebuffer setup, w=%d, h=%d", layout.width, layout.height);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u16 clip_x = rsx::method_registers.surface_clip_origin_x();
|
||||||
|
const u16 clip_y = rsx::method_registers.surface_clip_origin_y();
|
||||||
|
|
||||||
|
layout.color_addresses = get_color_surface_addresses();
|
||||||
|
layout.zeta_address = get_zeta_surface_address();
|
||||||
|
layout.zeta_pitch = rsx::method_registers.surface_z_pitch();
|
||||||
|
layout.color_pitch =
|
||||||
|
{
|
||||||
|
rsx::method_registers.surface_a_pitch(),
|
||||||
|
rsx::method_registers.surface_b_pitch(),
|
||||||
|
rsx::method_registers.surface_c_pitch(),
|
||||||
|
rsx::method_registers.surface_d_pitch(),
|
||||||
|
};
|
||||||
|
|
||||||
|
layout.color_format = rsx::method_registers.surface_color();
|
||||||
|
layout.depth_format = rsx::method_registers.surface_depth_fmt();
|
||||||
|
layout.target = rsx::method_registers.surface_color_target();
|
||||||
|
|
||||||
|
const auto aa_mode = rsx::method_registers.surface_antialias();
|
||||||
|
const u32 aa_factor_u = (aa_mode == rsx::surface_antialiasing::center_1_sample) ? 1 : 2;
|
||||||
|
const u32 aa_factor_v = (aa_mode == rsx::surface_antialiasing::center_1_sample || aa_mode == rsx::surface_antialiasing::diagonal_centered_2_samples) ? 1 : 2;
|
||||||
|
|
||||||
|
// NOTE: Its is possible that some renders are done on a swizzled context. Pitch is meaningless in that case
|
||||||
|
// Seen in Nier (color) and GT HD concept (z buffer)
|
||||||
|
// Restriction is that the dimensions are powers of 2. Also, dimensions are passed via log2w and log2h entries
|
||||||
|
const auto required_zeta_pitch = std::max<u32>((u32)(layout.depth_format == rsx::surface_depth_format::z16 ? layout.width * 2 : layout.width * 4) * aa_factor_u, 64u);
|
||||||
|
const auto required_color_pitch = std::max<u32>((u32)rsx::utility::get_packed_pitch(layout.color_format, layout.width) * aa_factor_u, 64u);
|
||||||
|
const bool color_write_enabled = (context & rsx::framebuffer_creation_context::context_clear_color) ? true : rsx::method_registers.color_write_enabled();
|
||||||
|
const bool depth_write_enabled = (context & rsx::framebuffer_creation_context::context_clear_depth) ? true : rsx::method_registers.depth_write_enabled();
|
||||||
|
const auto lg2w = rsx::method_registers.surface_log2_width();
|
||||||
|
const auto lg2h = rsx::method_registers.surface_log2_height();
|
||||||
|
const auto clipw_log2 = (u32)floor(log2(layout.width));
|
||||||
|
const auto cliph_log2 = (u32)floor(log2(layout.height));
|
||||||
|
|
||||||
|
const bool stencil_test_enabled = layout.depth_format == rsx::surface_depth_format::z24s8 && rsx::method_registers.stencil_test_enabled();
|
||||||
|
const bool depth_test_enabled = rsx::method_registers.depth_test_enabled();
|
||||||
|
const bool ignore_depth = (context == rsx::framebuffer_creation_context::context_clear_color);
|
||||||
|
const bool ignore_color = (context == rsx::framebuffer_creation_context::context_clear_depth);
|
||||||
|
|
||||||
|
if (layout.zeta_address)
|
||||||
|
{
|
||||||
|
if (!depth_test_enabled &&
|
||||||
|
!stencil_test_enabled &&
|
||||||
|
layout.target != rsx::surface_target::none)
|
||||||
|
{
|
||||||
|
// Disable depth buffer if depth testing is not enabled, unless a clear command is targeting the depth buffer
|
||||||
|
const bool is_depth_clear = !!(context & rsx::framebuffer_creation_context::context_clear_depth);
|
||||||
|
if (!is_depth_clear)
|
||||||
|
{
|
||||||
|
layout.zeta_address = 0;
|
||||||
|
m_framebuffer_state_contested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layout.zeta_address && layout.zeta_pitch < required_zeta_pitch)
|
||||||
|
{
|
||||||
|
if (lg2w < clipw_log2 || lg2h < cliph_log2)
|
||||||
|
{
|
||||||
|
// Cannot fit
|
||||||
|
layout.zeta_address = 0;
|
||||||
|
|
||||||
|
if (lg2w > 0 || lg2h > 0)
|
||||||
|
{
|
||||||
|
// Something was actually declared for the swizzle context dimensions
|
||||||
|
LOG_WARNING(RSX, "Invalid swizzled context depth surface dims, LG2W=%d, LG2H=%d, clip_w=%d, clip_h=%d", lg2w, lg2h, layout.width, layout.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_TRACE(RSX, "Swizzled context depth surface, LG2W=%d, LG2H=%d, clip_w=%d, clip_h=%d", lg2w, lg2h, layout.width, layout.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layout.zeta_address)
|
||||||
|
{
|
||||||
|
// Still exists? Unlikely to get discarded
|
||||||
|
layout.actual_zeta_pitch = std::max(layout.zeta_pitch, required_zeta_pitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &index : rsx::utility::get_rtt_indexes(layout.target))
|
||||||
|
{
|
||||||
|
if (layout.color_pitch[index] < required_color_pitch)
|
||||||
|
{
|
||||||
|
if (lg2w < clipw_log2 || lg2h < cliph_log2)
|
||||||
|
{
|
||||||
|
layout.color_addresses[index] = 0;
|
||||||
|
|
||||||
|
if (lg2w > 0 || lg2h > 0)
|
||||||
|
{
|
||||||
|
// Something was actually declared for the swizzle context dimensions
|
||||||
|
LOG_WARNING(RSX, "Invalid swizzled context color surface dims, LG2W=%d, LG2H=%d, clip_w=%d, clip_h=%d", lg2w, lg2h, layout.width, layout.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_TRACE(RSX, "Swizzled context color surface, LG2W=%d, LG2H=%d, clip_w=%d, clip_h=%d", lg2w, lg2h, layout.width, layout.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layout.zeta_address && (layout.color_addresses[index] == layout.zeta_address))
|
||||||
|
{
|
||||||
|
LOG_TRACE(RSX, "Framebuffer at 0x%X has aliasing color/depth targets, color_index=%d, zeta_pitch = %d, color_pitch=%d, context=%d",
|
||||||
|
layout.zeta_address, index, layout.zeta_pitch, layout.color_pitch[index], (u32)context);
|
||||||
|
|
||||||
|
// TODO: Research clearing both depth AND color
|
||||||
|
// TODO: If context is creation_draw, deal with possibility of a lost buffer clear
|
||||||
|
if (!ignore_depth &&
|
||||||
|
(ignore_color || depth_test_enabled || stencil_test_enabled ||
|
||||||
|
(!color_write_enabled && depth_write_enabled)))
|
||||||
|
{
|
||||||
|
// Use address for depth data
|
||||||
|
layout.color_addresses[index] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use address for color data
|
||||||
|
layout.zeta_address = 0;
|
||||||
|
m_framebuffer_state_contested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layout.color_addresses[index])
|
||||||
|
{
|
||||||
|
layout.actual_color_pitch[index] = std::max(layout.color_pitch[index], required_color_pitch);
|
||||||
|
framebuffer_status_valid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!framebuffer_status_valid && !layout.zeta_address)
|
||||||
|
{
|
||||||
|
LOG_WARNING(RSX, "Framebuffer setup failed. Draw calls may have been lost");
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// At least one attachment exists
|
||||||
|
framebuffer_status_valid = true;
|
||||||
|
|
||||||
|
// Window (raster) offsets
|
||||||
|
const auto window_offset_x = rsx::method_registers.window_offset_x();
|
||||||
|
const auto window_offset_y = rsx::method_registers.window_offset_y();
|
||||||
|
const auto window_clip_width = rsx::method_registers.window_clip_horizontal();
|
||||||
|
const auto window_clip_height = rsx::method_registers.window_clip_vertical();
|
||||||
|
|
||||||
|
const auto bpp = get_format_block_size_in_bytes(layout.color_format);
|
||||||
|
|
||||||
|
if (window_offset_x || window_offset_y)
|
||||||
|
{
|
||||||
|
// Window offset is what affects the raster position!
|
||||||
|
// Tested with Turbo: Super stunt squad that only changes the window offset to declare new framebuffers
|
||||||
|
// Sampling behavior clearly indicates the addresses are expected to have changed
|
||||||
|
if (auto clip_type = rsx::method_registers.window_clip_type())
|
||||||
|
LOG_ERROR(RSX, "Unknown window clip type 0x%X" HERE, clip_type);
|
||||||
|
|
||||||
|
for (const auto &index : rsx::utility::get_rtt_indexes(layout.target))
|
||||||
|
{
|
||||||
|
if (layout.color_addresses[index])
|
||||||
|
{
|
||||||
|
const u32 window_offset_bytes = (std::max<u32>(layout.color_pitch[index], required_color_pitch) * window_offset_y) + ((aa_factor_u * bpp) * window_offset_x);
|
||||||
|
layout.color_addresses[index] += window_offset_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layout.zeta_address)
|
||||||
|
{
|
||||||
|
const auto depth_bpp = (layout.depth_format == rsx::surface_depth_format::z16) ? 2 : 4;
|
||||||
|
layout.zeta_address += (std::max<u32>(layout.zeta_pitch, required_zeta_pitch) * window_offset_y) + ((aa_factor_u * depth_bpp) * window_offset_x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((window_clip_width && window_clip_width < layout.width) ||
|
||||||
|
(window_clip_height && window_clip_height < layout.height))
|
||||||
|
{
|
||||||
|
LOG_ERROR(RSX, "Unexpected window clip dimensions: window_clip=%dx%d, surface_clip=%dx%d",
|
||||||
|
window_clip_width, window_clip_height, layout.width, layout.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
layout.aa_mode = aa_mode;
|
||||||
|
layout.aa_factors[0] = aa_factor_u;
|
||||||
|
layout.aa_factors[1] = aa_factor_v;
|
||||||
|
|
||||||
|
bool really_changed = false;
|
||||||
|
|
||||||
|
for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i)
|
||||||
|
{
|
||||||
|
if (m_surface_info[i].address != layout.color_addresses[i])
|
||||||
|
{
|
||||||
|
really_changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layout.color_addresses[i])
|
||||||
|
{
|
||||||
|
if (m_surface_info[i].width != layout.width ||
|
||||||
|
m_surface_info[i].height != layout.height)
|
||||||
|
{
|
||||||
|
really_changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!really_changed)
|
||||||
|
{
|
||||||
|
if (layout.zeta_address == m_depth_surface_info.address)
|
||||||
|
{
|
||||||
|
// Same target is reused
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layout.ignore_change = false;
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
void thread::get_current_vertex_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count>& sampler_descriptors, bool skip_textures, bool skip_vertex_inputs)
|
void thread::get_current_vertex_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count>& sampler_descriptors, bool skip_textures, bool skip_vertex_inputs)
|
||||||
{
|
{
|
||||||
if (!(m_graphics_state & rsx::pipeline_state::vertex_program_dirty))
|
if (!(m_graphics_state & rsx::pipeline_state::vertex_program_dirty))
|
||||||
|
@ -213,6 +213,24 @@ namespace rsx
|
|||||||
std::array<attribute_buffer_placement, 16> attribute_placement;
|
std::array<attribute_buffer_placement, 16> attribute_placement;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct framebuffer_layout
|
||||||
|
{
|
||||||
|
u16 width;
|
||||||
|
u16 height;
|
||||||
|
std::array<u32, 4> color_addresses;
|
||||||
|
std::array<u32, 4> color_pitch;
|
||||||
|
std::array<u32, 4> actual_color_pitch;
|
||||||
|
u32 zeta_address;
|
||||||
|
u32 zeta_pitch;
|
||||||
|
u32 actual_zeta_pitch;
|
||||||
|
rsx::surface_target target;
|
||||||
|
rsx::surface_color_format color_format;
|
||||||
|
rsx::surface_depth_format depth_format;
|
||||||
|
rsx::surface_antialiasing aa_mode;
|
||||||
|
u32 aa_factors[2];
|
||||||
|
bool ignore_change;
|
||||||
|
};
|
||||||
|
|
||||||
namespace reports
|
namespace reports
|
||||||
{
|
{
|
||||||
struct occlusion_query_info
|
struct occlusion_query_info
|
||||||
@ -391,6 +409,8 @@ namespace rsx
|
|||||||
bool m_textures_dirty[16];
|
bool m_textures_dirty[16];
|
||||||
bool m_vertex_textures_dirty[4];
|
bool m_vertex_textures_dirty[4];
|
||||||
bool m_framebuffer_state_contested = false;
|
bool m_framebuffer_state_contested = false;
|
||||||
|
rsx::framebuffer_creation_context m_framebuffer_contest_type = rsx::framebuffer_creation_context::context_draw;
|
||||||
|
|
||||||
u32 m_graphics_state = 0;
|
u32 m_graphics_state = 0;
|
||||||
u64 ROP_sync_timestamp = 0;
|
u64 ROP_sync_timestamp = 0;
|
||||||
|
|
||||||
@ -401,6 +421,8 @@ namespace rsx
|
|||||||
std::array<u32, 4> get_color_surface_addresses() const;
|
std::array<u32, 4> get_color_surface_addresses() const;
|
||||||
u32 get_zeta_surface_address() const;
|
u32 get_zeta_surface_address() const;
|
||||||
|
|
||||||
|
framebuffer_layout get_framebuffer_layout(rsx::framebuffer_creation_context context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analyze vertex inputs and group all interleaved blocks
|
* Analyze vertex inputs and group all interleaved blocks
|
||||||
*/
|
*/
|
||||||
|
@ -2516,231 +2516,55 @@ void VKGSRender::open_command_buffer()
|
|||||||
m_current_command_buffer->begin();
|
m_current_command_buffer->begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
||||||
{
|
{
|
||||||
|
if (m_framebuffer_state_contested && (m_framebuffer_contest_type != context))
|
||||||
|
{
|
||||||
|
// Clear commands affect contested memory
|
||||||
|
m_rtts_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_draw_fbo && !m_rtts_dirty)
|
if (m_draw_fbo && !m_rtts_dirty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_rtts_dirty = false;
|
m_rtts_dirty = false;
|
||||||
|
|
||||||
u32 clip_width = rsx::method_registers.surface_clip_width();
|
|
||||||
u32 clip_height = rsx::method_registers.surface_clip_height();
|
|
||||||
u32 clip_x = rsx::method_registers.surface_clip_origin_x();
|
|
||||||
u32 clip_y = rsx::method_registers.surface_clip_origin_y();
|
|
||||||
|
|
||||||
framebuffer_status_valid = false;
|
framebuffer_status_valid = false;
|
||||||
m_framebuffer_state_contested = false;
|
m_framebuffer_state_contested = false;
|
||||||
|
|
||||||
if (clip_width == 0 || clip_height == 0)
|
const auto layout = get_framebuffer_layout(context);
|
||||||
|
if (!framebuffer_status_valid)
|
||||||
{
|
{
|
||||||
LOG_ERROR(RSX, "Invalid framebuffer setup, w=%d, h=%d", clip_width, clip_height);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto surface_addresses = get_color_surface_addresses();
|
if (m_draw_fbo && layout.ignore_change)
|
||||||
auto zeta_address = get_zeta_surface_address();
|
|
||||||
|
|
||||||
const auto zeta_pitch = rsx::method_registers.surface_z_pitch();
|
|
||||||
const u32 surface_pitchs[] = { rsx::method_registers.surface_a_pitch(), rsx::method_registers.surface_b_pitch(),
|
|
||||||
rsx::method_registers.surface_c_pitch(), rsx::method_registers.surface_d_pitch() };
|
|
||||||
|
|
||||||
const auto color_fmt = rsx::method_registers.surface_color();
|
|
||||||
const auto depth_fmt = rsx::method_registers.surface_depth_fmt();
|
|
||||||
const auto target = rsx::method_registers.surface_color_target();
|
|
||||||
|
|
||||||
const auto aa_mode = rsx::method_registers.surface_antialias();
|
|
||||||
const u32 aa_factor_u = (aa_mode == rsx::surface_antialiasing::center_1_sample) ? 1 : 2;
|
|
||||||
const u32 aa_factor_v = (aa_mode == rsx::surface_antialiasing::center_1_sample || aa_mode == rsx::surface_antialiasing::diagonal_centered_2_samples) ? 1 : 2;
|
|
||||||
|
|
||||||
//NOTE: Its is possible that some renders are done on a swizzled context. Pitch is meaningless in that case
|
|
||||||
//Seen in Nier (color) and GT HD concept (z buffer)
|
|
||||||
//Restriction is that the dimensions are powers of 2. Also, dimensions are passed via log2w and log2h entries
|
|
||||||
const auto required_zeta_pitch = std::max<u32>((u32)(depth_fmt == rsx::surface_depth_format::z16 ? clip_width * 2 : clip_width * 4) * aa_factor_u, 64u);
|
|
||||||
const auto required_color_pitch = std::max<u32>((u32)rsx::utility::get_packed_pitch(color_fmt, clip_width) * aa_factor_v, 64u);
|
|
||||||
const bool stencil_test_enabled = depth_fmt == rsx::surface_depth_format::z24s8 && rsx::method_registers.stencil_test_enabled();
|
|
||||||
const auto lg2w = rsx::method_registers.surface_log2_width();
|
|
||||||
const auto lg2h = rsx::method_registers.surface_log2_height();
|
|
||||||
const auto clipw_log2 = (u32)floor(log2(clip_width));
|
|
||||||
const auto cliph_log2 = (u32)floor(log2(clip_height));
|
|
||||||
|
|
||||||
if (zeta_address)
|
|
||||||
{
|
{
|
||||||
if (!rsx::method_registers.depth_test_enabled() &&
|
// Nothing has changed, we're still using the same framebuffer
|
||||||
!stencil_test_enabled &&
|
// Update flags to match current
|
||||||
target != rsx::surface_target::none)
|
|
||||||
|
const auto aa_mode = rsx::method_registers.surface_antialias();
|
||||||
|
|
||||||
|
for (u32 index = 0; index < 4; index++)
|
||||||
{
|
{
|
||||||
//Disable depth buffer if depth testing is not enabled, unless a clear command is targeting the depth buffer
|
if (auto surface = std::get<1>(m_rtts.m_bound_render_targets[index]))
|
||||||
const bool is_depth_clear = !!(context & rsx::framebuffer_creation_context::context_clear_depth);
|
|
||||||
if (!is_depth_clear)
|
|
||||||
{
|
{
|
||||||
zeta_address = 0;
|
surface->write_aa_mode = layout.aa_mode;
|
||||||
m_framebuffer_state_contested = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zeta_address && zeta_pitch < required_zeta_pitch)
|
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil))
|
||||||
{
|
{
|
||||||
if (lg2w < clipw_log2 || lg2h < cliph_log2)
|
ds->write_aa_mode = layout.aa_mode;
|
||||||
{
|
|
||||||
//Cannot fit
|
|
||||||
zeta_address = 0;
|
|
||||||
|
|
||||||
if (lg2w > 0 || lg2h > 0)
|
|
||||||
{
|
|
||||||
//Something was actually declared for the swizzle context dimensions
|
|
||||||
LOG_WARNING(RSX, "Invalid swizzled context depth surface dims, LG2W=%d, LG2H=%d, clip_w=%d, clip_h=%d", lg2w, lg2h, clip_width, clip_height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_TRACE(RSX, "Swizzled context depth surface, LG2W=%d, LG2H=%d, clip_w=%d, clip_h=%d", lg2w, lg2h, clip_width, clip_height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &index : rsx::utility::get_rtt_indexes(target))
|
|
||||||
{
|
|
||||||
if (surface_pitchs[index] < required_color_pitch)
|
|
||||||
{
|
|
||||||
if (lg2w < clipw_log2 || lg2h < cliph_log2)
|
|
||||||
{
|
|
||||||
surface_addresses[index] = 0;
|
|
||||||
|
|
||||||
if (lg2w > 0 || lg2h > 0)
|
|
||||||
{
|
|
||||||
//Something was actually declared for the swizzle context dimensions
|
|
||||||
LOG_WARNING(RSX, "Invalid swizzled context color surface dims, LG2W=%d, LG2H=%d, clip_w=%d, clip_h=%d", lg2w, lg2h, clip_width, clip_height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_TRACE(RSX, "Swizzled context color surface, LG2W=%d, LG2H=%d, clip_w=%d, clip_h=%d", lg2w, lg2h, clip_width, clip_height);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface_addresses[index] == zeta_address)
|
|
||||||
{
|
|
||||||
LOG_TRACE(RSX, "Framebuffer at 0x%X has aliasing color/depth targets, zeta_pitch = %d, color_pitch=%d", zeta_address, zeta_pitch, surface_pitchs[index]);
|
|
||||||
if (context == rsx::framebuffer_creation_context::context_clear_depth ||
|
|
||||||
rsx::method_registers.depth_test_enabled() || stencil_test_enabled ||
|
|
||||||
(!rsx::method_registers.color_write_enabled() && rsx::method_registers.depth_write_enabled()))
|
|
||||||
{
|
|
||||||
// Use address for depth data
|
|
||||||
// TODO: create a temporary render buffer for this to keep MRT outputs aligned
|
|
||||||
surface_addresses[index] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Use address for color data
|
|
||||||
zeta_address = 0;
|
|
||||||
m_framebuffer_state_contested = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (surface_addresses[index])
|
|
||||||
framebuffer_status_valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!framebuffer_status_valid && !zeta_address)
|
|
||||||
{
|
|
||||||
LOG_WARNING(RSX, "Framebuffer setup failed. Draw calls may have been lost");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//At least one attachment exists
|
|
||||||
framebuffer_status_valid = true;
|
|
||||||
|
|
||||||
const auto fbo_width = rsx::apply_resolution_scale(clip_width, true);
|
|
||||||
const auto fbo_height = rsx::apply_resolution_scale(clip_height, true);
|
|
||||||
const auto bpp = get_format_block_size_in_bytes(color_fmt);
|
|
||||||
|
|
||||||
//Window (raster) offsets
|
|
||||||
const auto window_offset_x = rsx::method_registers.window_offset_x();
|
|
||||||
const auto window_offset_y = rsx::method_registers.window_offset_y();
|
|
||||||
const auto window_clip_width = rsx::method_registers.window_clip_horizontal();
|
|
||||||
const auto window_clip_height = rsx::method_registers.window_clip_vertical();
|
|
||||||
|
|
||||||
if (window_offset_x || window_offset_y)
|
|
||||||
{
|
|
||||||
//Window offset is what affects the raster position!
|
|
||||||
//Tested with Turbo: Super stunt squad that only changes the window offset to declare new framebuffers
|
|
||||||
//Sampling behavior clearly indicates the addresses are expected to have changed
|
|
||||||
if (auto clip_type = rsx::method_registers.window_clip_type())
|
|
||||||
LOG_ERROR(RSX, "Unknown window clip type 0x%X" HERE, clip_type);
|
|
||||||
|
|
||||||
for (const auto &index : rsx::utility::get_rtt_indexes(target))
|
|
||||||
{
|
|
||||||
if (surface_addresses[index])
|
|
||||||
{
|
|
||||||
const u32 window_offset_bytes = (std::max<u32>(surface_pitchs[index], required_color_pitch) * window_offset_y) + ((aa_factor_u * bpp) * window_offset_x);
|
|
||||||
surface_addresses[index] += window_offset_bytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zeta_address)
|
|
||||||
{
|
|
||||||
const auto depth_bpp = (depth_fmt == rsx::surface_depth_format::z16 ? 2 : 4);
|
|
||||||
zeta_address += (std::max<u32>(zeta_pitch, required_zeta_pitch) * window_offset_y) + ((aa_factor_u * depth_bpp) * window_offset_x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((window_clip_width && window_clip_width < clip_width) ||
|
|
||||||
(window_clip_height && window_clip_height < clip_height))
|
|
||||||
{
|
|
||||||
LOG_ERROR(RSX, "Unexpected window clip dimensions: window_clip=%dx%d, surface_clip=%dx%d",
|
|
||||||
window_clip_width, window_clip_height, clip_width, clip_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_draw_fbo)
|
|
||||||
{
|
|
||||||
bool really_changed = false;
|
|
||||||
|
|
||||||
if (m_draw_fbo->width() == fbo_width && m_draw_fbo->height() == fbo_height)
|
|
||||||
{
|
|
||||||
for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i)
|
|
||||||
{
|
|
||||||
if (m_surface_info[i].address != surface_addresses[i])
|
|
||||||
{
|
|
||||||
really_changed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!really_changed)
|
|
||||||
{
|
|
||||||
if (zeta_address == m_depth_surface_info.address)
|
|
||||||
{
|
|
||||||
// Nothing has changed, we're still using the same framebuffer
|
|
||||||
// Update flags to match current
|
|
||||||
|
|
||||||
const auto aa_mode = rsx::method_registers.surface_antialias();
|
|
||||||
|
|
||||||
for (u32 index = 0; index < 4; index++)
|
|
||||||
{
|
|
||||||
if (auto surface = std::get<1>(m_rtts.m_bound_render_targets[index]))
|
|
||||||
{
|
|
||||||
surface->write_aa_mode = aa_mode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil))
|
|
||||||
{
|
|
||||||
ds->write_aa_mode = aa_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_rtts.prepare_render_target(&*m_current_command_buffer,
|
m_rtts.prepare_render_target(&*m_current_command_buffer,
|
||||||
color_fmt, depth_fmt,
|
layout.color_format, layout.depth_format,
|
||||||
clip_width, clip_height,
|
layout.width, layout.height,
|
||||||
target,
|
layout.target,
|
||||||
surface_addresses, zeta_address,
|
layout.color_addresses, layout.zeta_address,
|
||||||
(*m_device), &*m_current_command_buffer);
|
(*m_device), &*m_current_command_buffer);
|
||||||
|
|
||||||
//Reset framebuffer information
|
//Reset framebuffer information
|
||||||
@ -2759,9 +2583,9 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_surface_info[i].address = m_surface_info[i].pitch = 0;
|
m_surface_info[i].address = m_surface_info[i].pitch = 0;
|
||||||
m_surface_info[i].width = clip_width;
|
m_surface_info[i].width = layout.width;
|
||||||
m_surface_info[i].height = clip_height;
|
m_surface_info[i].height = layout.height;
|
||||||
m_surface_info[i].color_format = color_fmt;
|
m_surface_info[i].color_format = layout.color_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Process depth surface as well
|
//Process depth surface as well
|
||||||
@ -2775,13 +2599,13 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_depth_surface_info.address = m_depth_surface_info.pitch = 0;
|
m_depth_surface_info.address = m_depth_surface_info.pitch = 0;
|
||||||
m_depth_surface_info.width = clip_width;
|
m_depth_surface_info.width = layout.width;
|
||||||
m_depth_surface_info.height = clip_height;
|
m_depth_surface_info.height = layout.height;
|
||||||
m_depth_surface_info.depth_format = depth_fmt;
|
m_depth_surface_info.depth_format = layout.depth_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Bind created rtts as current fbo...
|
//Bind created rtts as current fbo...
|
||||||
std::vector<u8> draw_buffers = rsx::utility::get_rtt_indexes(target);
|
const auto draw_buffers = rsx::utility::get_rtt_indexes(layout.target);
|
||||||
m_draw_buffers_count = 0;
|
m_draw_buffers_count = 0;
|
||||||
|
|
||||||
std::vector<vk::image*> bound_images;
|
std::vector<vk::image*> bound_images;
|
||||||
@ -2793,14 +2617,13 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
|||||||
{
|
{
|
||||||
bound_images.push_back(surface);
|
bound_images.push_back(surface);
|
||||||
|
|
||||||
m_surface_info[index].address = surface_addresses[index];
|
m_surface_info[index].address = layout.color_addresses[index];
|
||||||
m_surface_info[index].pitch = std::max(surface_pitchs[index], required_color_pitch);
|
m_surface_info[index].pitch = layout.color_pitch[index];
|
||||||
surface->rsx_pitch = surface_pitchs[index];
|
surface->rsx_pitch = layout.color_pitch[index];
|
||||||
|
|
||||||
surface->write_aa_mode = aa_mode;
|
surface->write_aa_mode = layout.aa_mode;
|
||||||
m_texture_cache.notify_surface_changed(surface_addresses[index]);
|
m_texture_cache.notify_surface_changed(layout.color_addresses[index]);
|
||||||
|
m_texture_cache.tag_framebuffer(layout.color_addresses[index]);
|
||||||
m_texture_cache.tag_framebuffer(surface_addresses[index]);
|
|
||||||
m_draw_buffers_count++;
|
m_draw_buffers_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2810,26 +2633,25 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
|||||||
auto ds = std::get<1>(m_rtts.m_bound_depth_stencil);
|
auto ds = std::get<1>(m_rtts.m_bound_depth_stencil);
|
||||||
bound_images.push_back(ds);
|
bound_images.push_back(ds);
|
||||||
|
|
||||||
m_depth_surface_info.address = zeta_address;
|
m_depth_surface_info.address = layout.zeta_address;
|
||||||
m_depth_surface_info.pitch = std::max(zeta_pitch, required_zeta_pitch);
|
m_depth_surface_info.pitch = layout.zeta_pitch;
|
||||||
ds->rsx_pitch = m_depth_surface_info.pitch;
|
ds->rsx_pitch = layout.zeta_pitch;
|
||||||
|
|
||||||
ds->write_aa_mode = aa_mode;
|
ds->write_aa_mode = layout.aa_mode;
|
||||||
m_texture_cache.notify_surface_changed(zeta_address);
|
m_texture_cache.notify_surface_changed(layout.zeta_address);
|
||||||
|
m_texture_cache.tag_framebuffer(layout.zeta_address);
|
||||||
m_texture_cache.tag_framebuffer(zeta_address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_cfg.video.write_color_buffers)
|
if (g_cfg.video.write_color_buffers)
|
||||||
{
|
{
|
||||||
const auto color_fmt_info = vk::get_compatible_gcm_format(color_fmt);
|
const auto color_fmt_info = vk::get_compatible_gcm_format(layout.color_format);
|
||||||
for (u8 index : draw_buffers)
|
for (u8 index : draw_buffers)
|
||||||
{
|
{
|
||||||
if (!m_surface_info[index].address || !m_surface_info[index].pitch) continue;
|
if (!m_surface_info[index].address || !m_surface_info[index].pitch) continue;
|
||||||
|
|
||||||
const u32 range = m_surface_info[index].pitch * m_surface_info[index].height * aa_factor_v;
|
const u32 range = m_surface_info[index].pitch * m_surface_info[index].height * layout.aa_factors[1];
|
||||||
m_texture_cache.lock_memory_region(std::get<1>(m_rtts.m_bound_render_targets[index]), m_surface_info[index].address, range,
|
m_texture_cache.lock_memory_region(std::get<1>(m_rtts.m_bound_render_targets[index]), m_surface_info[index].address, range,
|
||||||
m_surface_info[index].width, m_surface_info[index].height, m_surface_info[index].pitch, color_fmt_info.first, color_fmt_info.second);
|
m_surface_info[index].width, m_surface_info[index].height, layout.actual_color_pitch[index], color_fmt_info.first, color_fmt_info.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2838,17 +2660,19 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
|||||||
if (m_depth_surface_info.address && m_depth_surface_info.pitch)
|
if (m_depth_surface_info.address && m_depth_surface_info.pitch)
|
||||||
{
|
{
|
||||||
const u32 gcm_format = (m_depth_surface_info.depth_format != rsx::surface_depth_format::z16)? CELL_GCM_TEXTURE_DEPTH16 : CELL_GCM_TEXTURE_DEPTH24_D8;
|
const u32 gcm_format = (m_depth_surface_info.depth_format != rsx::surface_depth_format::z16)? CELL_GCM_TEXTURE_DEPTH16 : CELL_GCM_TEXTURE_DEPTH24_D8;
|
||||||
const u32 range = m_depth_surface_info.pitch * m_depth_surface_info.height * aa_factor_v;
|
const u32 range = m_depth_surface_info.pitch * m_depth_surface_info.height * layout.aa_factors[1];
|
||||||
m_texture_cache.lock_memory_region(std::get<1>(m_rtts.m_bound_depth_stencil), m_depth_surface_info.address, range,
|
m_texture_cache.lock_memory_region(std::get<1>(m_rtts.m_bound_depth_stencil), m_depth_surface_info.address, range,
|
||||||
m_depth_surface_info.width, m_depth_surface_info.height, m_depth_surface_info.pitch, gcm_format, false);
|
m_depth_surface_info.width, m_depth_surface_info.height, layout.actual_zeta_pitch, gcm_format, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto vk_depth_format = (zeta_address == 0) ? VK_FORMAT_UNDEFINED : vk::get_compatible_depth_surface_format(m_device->get_formats_support(), depth_fmt);
|
auto vk_depth_format = (layout.zeta_address == 0) ? VK_FORMAT_UNDEFINED : vk::get_compatible_depth_surface_format(m_device->get_formats_support(), layout.depth_format);
|
||||||
m_current_renderpass_id = vk::get_render_pass_location(vk::get_compatible_surface_format(color_fmt).first, vk_depth_format, m_draw_buffers_count);
|
m_current_renderpass_id = vk::get_render_pass_location(vk::get_compatible_surface_format(layout.color_format).first, vk_depth_format, m_draw_buffers_count);
|
||||||
|
|
||||||
//Search old framebuffers for this same configuration
|
//Search old framebuffers for this same configuration
|
||||||
bool framebuffer_found = false;
|
bool framebuffer_found = false;
|
||||||
|
const auto fbo_width = rsx::apply_resolution_scale(layout.width, true);
|
||||||
|
const auto fbo_height = rsx::apply_resolution_scale(layout.height, true);
|
||||||
|
|
||||||
for (auto &fbo : m_framebuffers_to_clean)
|
for (auto &fbo : m_framebuffers_to_clean)
|
||||||
{
|
{
|
||||||
|
@ -2688,8 +2688,12 @@ public:
|
|||||||
|
|
||||||
void unmap()
|
void unmap()
|
||||||
{
|
{
|
||||||
//mapped = false;
|
if (g_cfg.video.disable_vulkan_mem_allocator)
|
||||||
//heap->unmap();
|
{
|
||||||
|
heap->unmap();
|
||||||
|
mapped = false;
|
||||||
|
_ptr = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user