mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-08-11 18:50:55 +00:00
rsx: Obey MSAA resolve during memory persistence transfer
- Ugh. This is a bandaid on a festering wound, AA badly needs a rewrite Also silence some warnings
This commit is contained in:
parent
fb20c27e7b
commit
0f24379c0e
8 changed files with 165 additions and 45 deletions
|
@ -1593,8 +1593,8 @@ namespace rsx
|
||||||
|
|
||||||
if (requires_processing)
|
if (requires_processing)
|
||||||
{
|
{
|
||||||
const auto w = rsx::apply_resolution_scale(internal_width, true);
|
const auto w = rsx::apply_resolution_scale(std::min<u16>(internal_width, surface_width), true);
|
||||||
const auto h = rsx::apply_resolution_scale(internal_height, true);
|
const auto h = rsx::apply_resolution_scale(std::min<u16>(internal_height, surface_height), true);
|
||||||
|
|
||||||
auto command = update_subresource_cache ? deferred_request_command::copy_image_dynamic : deferred_request_command::copy_image_static;
|
auto command = update_subresource_cache ? deferred_request_command::copy_image_dynamic : deferred_request_command::copy_image_static;
|
||||||
return { texptr->get_surface(), command, texaddr, format, 0, 0, w, h, 1,
|
return { texptr->get_surface(), command, texaddr, format, 0, 0, w, h, 1,
|
||||||
|
|
|
@ -207,19 +207,13 @@ void GLGSRender::end()
|
||||||
|
|
||||||
//Check if depth buffer is bound and valid
|
//Check if depth buffer is bound and valid
|
||||||
//If ds is not initialized clear it; it seems new depth textures should have depth cleared
|
//If ds is not initialized clear it; it seems new depth textures should have depth cleared
|
||||||
auto copy_rtt_contents = [](gl::render_target *surface)
|
auto copy_rtt_contents = [](gl::render_target *surface, bool is_depth)
|
||||||
{
|
{
|
||||||
if (surface->get_internal_format() == surface->old_contents->get_internal_format())
|
if (surface->get_internal_format() == surface->old_contents->get_internal_format())
|
||||||
{
|
{
|
||||||
//Copy data from old contents onto this one
|
//Copy data from old contents onto this one
|
||||||
//1. Clip a rectangular region defining the data
|
const auto region = rsx::get_transferable_region(surface);
|
||||||
//2. Perform a GPU blit
|
gl::g_hw_blitter->scale_image(surface->old_contents, surface, { 0, 0, std::get<0>(region), std::get<1>(region) }, { 0, 0, std::get<2>(region) , std::get<3>(region) }, !is_depth, is_depth, {});
|
||||||
u16 parent_w = surface->old_contents->width();
|
|
||||||
u16 parent_h = surface->old_contents->height();
|
|
||||||
u16 copy_w, copy_h;
|
|
||||||
|
|
||||||
std::tie(std::ignore, std::ignore, copy_w, copy_h) = rsx::clip_region<u16>(parent_w, parent_h, 0, 0, surface->width(), surface->height(), true);
|
|
||||||
glCopyImageSubData(surface->old_contents->id(), GL_TEXTURE_2D, 0, 0, 0, 0, surface->id(), GL_TEXTURE_2D, 0, 0, 0, 0, copy_w, copy_h, 1);
|
|
||||||
surface->set_cleared();
|
surface->set_cleared();
|
||||||
}
|
}
|
||||||
//TODO: download image contents and reupload them or do a memory cast to copy memory contents if not compatible
|
//TODO: download image contents and reupload them or do a memory cast to copy memory contents if not compatible
|
||||||
|
@ -293,14 +287,14 @@ void GLGSRender::end()
|
||||||
if (g_cfg.video.strict_rendering_mode)
|
if (g_cfg.video.strict_rendering_mode)
|
||||||
{
|
{
|
||||||
if (ds && ds->old_contents != nullptr)
|
if (ds && ds->old_contents != nullptr)
|
||||||
copy_rtt_contents(ds);
|
copy_rtt_contents(ds, true);
|
||||||
|
|
||||||
for (auto &rtt : m_rtts.m_bound_render_targets)
|
for (auto &rtt : m_rtts.m_bound_render_targets)
|
||||||
{
|
{
|
||||||
if (auto surface = std::get<1>(rtt))
|
if (auto surface = std::get<1>(rtt))
|
||||||
{
|
{
|
||||||
if (surface->old_contents != nullptr)
|
if (surface->old_contents != nullptr)
|
||||||
copy_rtt_contents(surface);
|
copy_rtt_contents(surface, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -366,7 +366,24 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
||||||
{
|
{
|
||||||
if (depth_address == m_depth_surface_info.address)
|
if (depth_address == m_depth_surface_info.address)
|
||||||
{
|
{
|
||||||
//Nothing has changed, we're still using the same framebuffer
|
// Nothing has changed, we're still using the same framebuffer
|
||||||
|
// Update flags to match current
|
||||||
|
|
||||||
|
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->aa_mode = aa_mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil))
|
||||||
|
{
|
||||||
|
ds->aa_mode = aa_mode;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1161,33 +1161,34 @@ void VKGSRender::end()
|
||||||
|
|
||||||
if (g_cfg.video.strict_rendering_mode)
|
if (g_cfg.video.strict_rendering_mode)
|
||||||
{
|
{
|
||||||
auto copy_rtt_contents = [&](vk::render_target* surface)
|
auto copy_rtt_contents = [&](vk::render_target* surface, bool is_depth)
|
||||||
{
|
{
|
||||||
if (surface->info.format == surface->old_contents->info.format)
|
if (surface->info.format == surface->old_contents->info.format)
|
||||||
{
|
{
|
||||||
const VkImageAspectFlags aspect = surface->attachment_aspect_flag;
|
const auto region = rsx::get_transferable_region(surface);
|
||||||
|
const auto src_w = std::get<0>(region);
|
||||||
|
const auto src_h = std::get<1>(region);
|
||||||
|
const auto dst_w = std::get<2>(region);
|
||||||
|
const auto dst_h = std::get<3>(region);
|
||||||
|
|
||||||
const u16 parent_w = surface->old_contents->width();
|
if (!is_depth || (src_w == dst_w && src_h == dst_h))
|
||||||
const u16 parent_h = surface->old_contents->height();
|
{
|
||||||
u16 copy_w, copy_h;
|
const VkImageAspectFlags aspect = surface->attachment_aspect_flag;
|
||||||
|
|
||||||
std::tie(std::ignore, std::ignore, copy_w, copy_h) = rsx::clip_region<u16>(parent_w, parent_h, 0, 0, surface->width(), surface->height(), true);
|
vk::copy_scaled_image(*m_current_command_buffer, surface->old_contents->value, surface->value,
|
||||||
|
surface->old_contents->current_layout, surface->current_layout, 0, 0, src_w, src_h,
|
||||||
|
0, 0, dst_w, dst_h, 1, aspect, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto rp = vk::get_render_pass_location(VK_FORMAT_UNDEFINED, surface->info.format, 0);
|
||||||
|
auto render_pass = m_render_passes[rp];
|
||||||
|
|
||||||
VkImageSubresourceRange subresource_range = { aspect, 0, 1, 0, 1 };
|
vk::change_image_layout(*m_current_command_buffer, surface->old_contents, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
VkImageLayout old_layout = surface->current_layout;
|
|
||||||
|
|
||||||
vk::change_image_layout(*m_current_command_buffer, surface, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range);
|
m_depth_scaler->run(*m_current_command_buffer, { 0, 0, (f32)src_w, (f32)src_h }, { 0, 0, (f32)dst_w, (f32)dst_h }, surface,
|
||||||
vk::change_image_layout(*m_current_command_buffer, surface->old_contents, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range);
|
surface->old_contents, surface->old_contents->get_view(0xAAE4, rsx::default_remap_vector), render_pass, m_framebuffers_to_clean);
|
||||||
|
}
|
||||||
VkImageCopy copy_rgn;
|
|
||||||
copy_rgn.srcOffset = { 0, 0, 0 };
|
|
||||||
copy_rgn.dstOffset = { 0, 0, 0 };
|
|
||||||
copy_rgn.dstSubresource = { aspect, 0, 0, 1 };
|
|
||||||
copy_rgn.srcSubresource = { aspect, 0, 0, 1 };
|
|
||||||
copy_rgn.extent = { copy_w, copy_h, 1 };
|
|
||||||
|
|
||||||
vkCmdCopyImage(*m_current_command_buffer, surface->old_contents->value, surface->old_contents->current_layout, surface->value, surface->current_layout, 1, ©_rgn);
|
|
||||||
vk::change_image_layout(*m_current_command_buffer, surface, old_layout, subresource_range);
|
|
||||||
|
|
||||||
surface->dirty = false;
|
surface->dirty = false;
|
||||||
}
|
}
|
||||||
|
@ -1202,13 +1203,13 @@ void VKGSRender::end()
|
||||||
if (auto surface = std::get<1>(rtt))
|
if (auto surface = std::get<1>(rtt))
|
||||||
{
|
{
|
||||||
if (surface->old_contents != nullptr)
|
if (surface->old_contents != nullptr)
|
||||||
copy_rtt_contents(surface);
|
copy_rtt_contents(surface, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ds && ds->old_contents)
|
if (ds && ds->old_contents)
|
||||||
{
|
{
|
||||||
copy_rtt_contents(ds);
|
copy_rtt_contents(ds, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2734,7 +2735,24 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
||||||
{
|
{
|
||||||
if (zeta_address == m_depth_surface_info.address)
|
if (zeta_address == m_depth_surface_info.address)
|
||||||
{
|
{
|
||||||
//Nothing has changed, we're still using the same framebuffer
|
// Nothing has changed, we're still using the same framebuffer
|
||||||
|
// Update flags to match current
|
||||||
|
|
||||||
|
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->aa_mode = aa_mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil))
|
||||||
|
{
|
||||||
|
ds->aa_mode = aa_mode;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3324,8 +3342,11 @@ bool VKGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst
|
||||||
vk::change_image_layout(*m_current_command_buffer, result.src_image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
vk::change_image_layout(*m_current_command_buffer, result.src_image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
vk::change_image_layout(*m_current_command_buffer, result.dst_image, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
vk::change_image_layout(*m_current_command_buffer, result.dst_image, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
m_depth_scaler->run(*m_current_command_buffer, result.dst_image->width(), result.dst_image->height(), result.dst_image,
|
// TODO: Insets
|
||||||
result.src_view, render_pass, m_framebuffers_to_clean);
|
const areaf src_area = { 0, 0, (f32)result.src_image->width(), (f32)result.src_image->height() };
|
||||||
|
const areaf dst_area = { 0, 0, (f32)result.dst_image->width(), (f32)result.dst_image->height() };
|
||||||
|
m_depth_scaler->run(*m_current_command_buffer, src_area, dst_area, result.dst_image, result.src_image,
|
||||||
|
result.src_view, render_pass, m_framebuffers_to_clean);
|
||||||
|
|
||||||
vk::change_image_layout(*m_current_command_buffer, result.src_image, old_src_layout);
|
vk::change_image_layout(*m_current_command_buffer, result.src_image, old_src_layout);
|
||||||
vk::change_image_layout(*m_current_command_buffer, result.dst_image, old_dst_layout);
|
vk::change_image_layout(*m_current_command_buffer, result.dst_image, old_dst_layout);
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace vk
|
||||||
void change_image_layout(VkCommandBuffer cmd, vk::image *image, VkImageLayout new_layout, VkImageSubresourceRange range);
|
void change_image_layout(VkCommandBuffer cmd, vk::image *image, VkImageLayout new_layout, VkImageSubresourceRange range);
|
||||||
void change_image_layout(VkCommandBuffer cmd, vk::image *image, VkImageLayout new_layout);
|
void change_image_layout(VkCommandBuffer cmd, vk::image *image, VkImageLayout new_layout);
|
||||||
void copy_image(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout, u32 width, u32 height, u32 mipmaps, VkImageAspectFlagBits aspect);
|
void copy_image(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout, u32 width, u32 height, u32 mipmaps, VkImageAspectFlagBits aspect);
|
||||||
void copy_scaled_image(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout, u32 src_x_offset, u32 src_y_offset, u32 src_width, u32 src_height, u32 dst_x_offset, u32 dst_y_offset, u32 dst_width, u32 dst_height, u32 mipmaps, VkImageAspectFlagBits aspect, bool compatible_formats);
|
void copy_scaled_image(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout, u32 src_x_offset, u32 src_y_offset, u32 src_width, u32 src_height, u32 dst_x_offset, u32 dst_y_offset, u32 dst_width, u32 dst_height, u32 mipmaps, VkImageAspectFlags aspect, bool compatible_formats);
|
||||||
|
|
||||||
std::pair<VkFormat, VkComponentMapping> get_compatible_surface_format(rsx::surface_color_format color_format);
|
std::pair<VkFormat, VkComponentMapping> get_compatible_surface_format(rsx::surface_color_format color_format);
|
||||||
size_t get_render_pass_location(VkFormat color_surface_format, VkFormat depth_stencil_format, u8 color_surface_count);
|
size_t get_render_pass_location(VkFormat color_surface_format, VkFormat depth_stencil_format, u8 color_surface_count);
|
||||||
|
|
|
@ -126,7 +126,7 @@ namespace vk
|
||||||
check_heap();
|
check_heap();
|
||||||
|
|
||||||
const auto size = count * sizeof(f32);
|
const auto size = count * sizeof(f32);
|
||||||
m_vao_offset = m_vao.alloc<16>(size);
|
m_vao_offset = (u32)m_vao.alloc<16>(size);
|
||||||
auto dst = m_vao.map(m_vao_offset, size);
|
auto dst = m_vao.map(m_vao_offset, size);
|
||||||
std::memcpy(dst, data, size);
|
std::memcpy(dst, data, size);
|
||||||
m_vao.unmap();
|
m_vao.unmap();
|
||||||
|
@ -631,7 +631,7 @@ namespace vk
|
||||||
|
|
||||||
void update_uniforms(vk::glsl::program* /*program*/) override
|
void update_uniforms(vk::glsl::program* /*program*/) override
|
||||||
{
|
{
|
||||||
m_ubo_offset = m_ubo.alloc<256>(128);
|
m_ubo_offset = (u32)m_ubo.alloc<256>(128);
|
||||||
auto dst = (f32*)m_ubo.map(m_ubo_offset, 128);
|
auto dst = (f32*)m_ubo.map(m_ubo_offset, 128);
|
||||||
dst[0] = m_scale_offset.r;
|
dst[0] = m_scale_offset.r;
|
||||||
dst[1] = m_scale_offset.g;
|
dst[1] = m_scale_offset.g;
|
||||||
|
@ -713,12 +713,18 @@ namespace vk
|
||||||
|
|
||||||
struct depth_scaling_pass : public overlay_pass
|
struct depth_scaling_pass : public overlay_pass
|
||||||
{
|
{
|
||||||
|
areaf src_area;
|
||||||
|
areaf dst_area;
|
||||||
|
u16 src_width;
|
||||||
|
u16 src_height;
|
||||||
|
|
||||||
depth_scaling_pass()
|
depth_scaling_pass()
|
||||||
{
|
{
|
||||||
vs_src =
|
vs_src =
|
||||||
{
|
{
|
||||||
"#version 450\n"
|
"#version 450\n"
|
||||||
"#extension GL_ARB_separate_shader_objects : enable\n"
|
"#extension GL_ARB_separate_shader_objects : enable\n"
|
||||||
|
"layout(std140, set=0, binding=1) uniform static_data{ vec4 regs[8]; };\n"
|
||||||
"layout(location=0) out vec2 tc0;\n"
|
"layout(location=0) out vec2 tc0;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"void main()\n"
|
"void main()\n"
|
||||||
|
@ -726,7 +732,7 @@ namespace vk
|
||||||
" vec2 positions[] = {vec2(-1., -1.), vec2(1., -1.), vec2(-1., 1.), vec2(1., 1.)};\n"
|
" vec2 positions[] = {vec2(-1., -1.), vec2(1., -1.), vec2(-1., 1.), vec2(1., 1.)};\n"
|
||||||
" vec2 coords[] = {vec2(0., 0.), vec2(1., 0.), vec2(0., 1.), vec2(1., 1.)};\n"
|
" vec2 coords[] = {vec2(0., 0.), vec2(1., 0.), vec2(0., 1.), vec2(1., 1.)};\n"
|
||||||
" gl_Position = vec4(positions[gl_VertexIndex % 4], 0., 1.);\n"
|
" gl_Position = vec4(positions[gl_VertexIndex % 4], 0., 1.);\n"
|
||||||
" tc0 = coords[gl_VertexIndex % 4];\n"
|
" tc0 = coords[gl_VertexIndex % 4] * regs[0].xy + regs[0].zw;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -749,6 +755,42 @@ namespace vk
|
||||||
m_vertex_shader.id = 100006;
|
m_vertex_shader.id = 100006;
|
||||||
m_fragment_shader.id = 100007;
|
m_fragment_shader.id = 100007;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update_uniforms(vk::glsl::program* /*program*/) override
|
||||||
|
{
|
||||||
|
m_ubo_offset = (u32)m_ubo.alloc<256>(128);
|
||||||
|
auto dst = (f32*)m_ubo.map(m_ubo_offset, 128);
|
||||||
|
dst[0] = f32(src_area.x2 - src_area.x1) / src_width;
|
||||||
|
dst[1] = f32(src_area.y2 - src_area.y1) / src_height;
|
||||||
|
dst[2] = src_area.x1 / f32(src_area.x2 - src_area.x1);
|
||||||
|
dst[3] = src_area.y1 / f32(src_area.y2 - src_area.y1);
|
||||||
|
m_ubo.unmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_up_viewport(vk::command_buffer &cmd, u16 max_w, u16 max_h) override
|
||||||
|
{
|
||||||
|
VkRect2D region = { { s32(dst_area.x1), s32(dst_area.y1) },{ u32(dst_area.x2 - dst_area.x1), u32(dst_area.y2 - dst_area.y1) } };
|
||||||
|
vkCmdSetScissor(cmd, 0, 1, ®ion);
|
||||||
|
|
||||||
|
VkViewport vp{};
|
||||||
|
vp.x = dst_area.x1;
|
||||||
|
vp.y = dst_area.y1;
|
||||||
|
vp.width = f32(region.extent.width);
|
||||||
|
vp.height = f32(region.extent.height);
|
||||||
|
vp.minDepth = 0.f;
|
||||||
|
vp.maxDepth = 1.f;
|
||||||
|
vkCmdSetViewport(cmd, 0, 1, &vp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(vk::command_buffer &cmd, const areaf& src_rect, const areaf& dst_rect, vk::image* target, vk::image* src, vk::image_view* src_view, VkRenderPass render_pass, std::list<std::unique_ptr<vk::framebuffer_holder>>& framebuffer_resources)
|
||||||
|
{
|
||||||
|
src_area = src_rect;
|
||||||
|
dst_area = dst_rect;
|
||||||
|
src_width = src->width();
|
||||||
|
src_height = src->height();
|
||||||
|
|
||||||
|
overlay_pass::run(cmd, target->width(), target->height(), target, src_view, render_pass, framebuffer_resources);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct attachment_clear_pass : public overlay_pass
|
struct attachment_clear_pass : public overlay_pass
|
||||||
|
@ -806,7 +848,7 @@ namespace vk
|
||||||
|
|
||||||
void update_uniforms(vk::glsl::program* /*program*/) override
|
void update_uniforms(vk::glsl::program* /*program*/) override
|
||||||
{
|
{
|
||||||
m_ubo_offset = m_ubo.alloc<256>(128);
|
m_ubo_offset = (u32)m_ubo.alloc<256>(128);
|
||||||
auto dst = (f32*)m_ubo.map(m_ubo_offset, 128);
|
auto dst = (f32*)m_ubo.map(m_ubo_offset, 128);
|
||||||
dst[0] = clear_color.r;
|
dst[0] = clear_color.r;
|
||||||
dst[1] = clear_color.g;
|
dst[1] = clear_color.g;
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace vk
|
||||||
VkImageLayout srcLayout, VkImageLayout dstLayout,
|
VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||||
u32 src_x_offset, u32 src_y_offset, u32 src_width, u32 src_height,
|
u32 src_x_offset, u32 src_y_offset, u32 src_width, u32 src_height,
|
||||||
u32 dst_x_offset, u32 dst_y_offset, u32 dst_width, u32 dst_height,
|
u32 dst_x_offset, u32 dst_y_offset, u32 dst_width, u32 dst_height,
|
||||||
u32 mipmaps, VkImageAspectFlagBits aspect, bool compatible_formats)
|
u32 mipmaps, VkImageAspectFlags aspect, bool compatible_formats)
|
||||||
{
|
{
|
||||||
VkImageSubresourceLayers a_src = {}, a_dst = {};
|
VkImageSubresourceLayers a_src = {}, a_dst = {};
|
||||||
a_src.aspectMask = aspect;
|
a_src.aspectMask = aspect;
|
||||||
|
|
|
@ -586,6 +586,52 @@ namespace rsx
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the regions used for memory transfer between rendertargets on succession events
|
||||||
|
*/
|
||||||
|
template <typename SurfaceType>
|
||||||
|
std::tuple<u16, u16, u16, u16> get_transferable_region(SurfaceType* surface)
|
||||||
|
{
|
||||||
|
const u16 src_w = surface->old_contents->width();
|
||||||
|
const u16 src_h = surface->old_contents->height();
|
||||||
|
u16 dst_w = src_w;
|
||||||
|
u16 dst_h = src_h;
|
||||||
|
|
||||||
|
switch (surface->old_contents->aa_mode)
|
||||||
|
{
|
||||||
|
case rsx::surface_antialiasing::center_1_sample:
|
||||||
|
break;
|
||||||
|
case rsx::surface_antialiasing::diagonal_centered_2_samples:
|
||||||
|
dst_w *= 2;
|
||||||
|
break;
|
||||||
|
case rsx::surface_antialiasing::square_centered_4_samples:
|
||||||
|
case rsx::surface_antialiasing::square_rotated_4_samples:
|
||||||
|
dst_w *= 2;
|
||||||
|
dst_h *= 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (surface->aa_mode)
|
||||||
|
{
|
||||||
|
case rsx::surface_antialiasing::center_1_sample:
|
||||||
|
break;
|
||||||
|
case rsx::surface_antialiasing::diagonal_centered_2_samples:
|
||||||
|
dst_w /= 2;
|
||||||
|
break;
|
||||||
|
case rsx::surface_antialiasing::square_centered_4_samples:
|
||||||
|
case rsx::surface_antialiasing::square_rotated_4_samples:
|
||||||
|
dst_w /= 2;
|
||||||
|
dst_h /= 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const f32 scale_x = (f32)dst_w / src_w;
|
||||||
|
const f32 scale_y = (f32)dst_h / src_h;
|
||||||
|
|
||||||
|
std::tie(std::ignore, std::ignore, dst_w, dst_h) = clip_region<u16>(dst_w, dst_h, 0, 0, surface->width(), surface->height(), true);
|
||||||
|
return std::make_tuple(u16(dst_w / scale_x), u16(dst_h / scale_y), dst_w, dst_h);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove restart index and emulate using degenerate triangles
|
* Remove restart index and emulate using degenerate triangles
|
||||||
* Can be used as a workaround when restart_index doesnt work too well
|
* Can be used as a workaround when restart_index doesnt work too well
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue