diff --git a/rpcs3/Emu/RSX/GL/GLResolveHelper.cpp b/rpcs3/Emu/RSX/GL/GLResolveHelper.cpp index 23f96e74aa..fc2349429f 100644 --- a/rpcs3/Emu/RSX/GL/GLResolveHelper.cpp +++ b/rpcs3/Emu/RSX/GL/GLResolveHelper.cpp @@ -1,15 +1,105 @@ #include "stdafx.h" #include "GLResolveHelper.h" +#include + namespace gl { + std::unordered_map> g_resolve_helpers; + std::unordered_map> g_unresolve_helpers; + + static const char* get_format_string(gl::texture::internal_format format) + { + switch (format) + { + case texture::internal_format::rgb565: + return "r16"; + case texture::internal_format::rgba8: + case texture::internal_format::bgra8: + return "rgba8"; + case texture::internal_format::rgba16f: + return "rgba16f"; + case texture::internal_format::rgba32f: + return "rgba32f"; + case texture::internal_format::bgr5a1: + return "r16"; + case texture::internal_format::r8: + return "r8"; + case texture::internal_format::rg8: + return "rg8"; + case texture::internal_format::r32f: + return "r32f"; + default: + fmt::throw_exception("Unhandled internal format 0x%x", u32(format)); + } + } + void resolve_image(gl::command_context& cmd, gl::viewable_image* dst, gl::viewable_image* src) { - // TODO + ensure(src->format_class() == RSX_FORMAT_CLASS_COLOR); // TODO + { + auto& job = g_resolve_helpers[src->get_internal_format()]; + if (!job) + { + const auto fmt = get_format_string(src->get_internal_format()); + job.reset(new cs_resolve_task(fmt)); + } + + job->run(cmd, src, dst); + } } void unresolve_image(gl::command_context& cmd, gl::viewable_image* dst, gl::viewable_image* src) { - // TODO + ensure(src->format_class() == RSX_FORMAT_CLASS_COLOR); // TODO + { + auto& job = g_unresolve_helpers[src->get_internal_format()]; + if (!job) + { + const auto fmt = get_format_string(src->get_internal_format()); + job.reset(new cs_unresolve_task(fmt)); + } + + job->run(cmd, dst, src); + } + } + + void cs_resolve_base::build(const std::string& format_prefix, bool unresolve) + { + create(); + + switch (optimal_group_size) + { + default: + case 64: + cs_wave_x = 8; + cs_wave_y = 8; + break; + case 32: + cs_wave_x = 8; + cs_wave_y = 4; + break; + } + + static const char* resolve_kernel = + #include "Emu/RSX/Program/MSAA/ColorResolvePass.glsl" + ; + + static const char* unresolve_kernel = + #include "Emu/RSX/Program/MSAA/ColorResolvePass.glsl" + ; + + const std::pair syntax_replace[] = + { + { "%WORKGROUP_SIZE_X", std::to_string(cs_wave_x) }, + { "%WORKGROUP_SIZE_Y", std::to_string(cs_wave_y) }, + { "%IMAGE_FORMAT", format_prefix }, + { "%BGRA_SWAP", "0" } + }; + + m_src = unresolve ? unresolve_kernel : resolve_kernel; + m_src = fmt::replace_all(m_src, syntax_replace); + + rsx_log.notice("Resolve shader:\n%s", m_src); } } diff --git a/rpcs3/Emu/RSX/GL/GLResolveHelper.h b/rpcs3/Emu/RSX/GL/GLResolveHelper.h index 1a0bd05e80..6190e4ee7f 100644 --- a/rpcs3/Emu/RSX/GL/GLResolveHelper.h +++ b/rpcs3/Emu/RSX/GL/GLResolveHelper.h @@ -7,4 +7,60 @@ namespace gl { void resolve_image(gl::command_context& cmd, gl::viewable_image* dst, gl::viewable_image* src); void unresolve_image(gl::command_context& cmd, gl::viewable_image* dst, gl::viewable_image* src); + + struct cs_resolve_base : compute_task + { + gl::viewable_image* multisampled = nullptr; + gl::viewable_image* resolve = nullptr; + + u32 cs_wave_x = 1; + u32 cs_wave_y = 1; + + cs_resolve_base() + {} + + virtual ~cs_resolve_base() + {} + + void build(const std::string& format_prefix, bool unresolve); + + void bind_resources() override + { + auto msaa_view = multisampled->get_view(rsx::default_remap_vector.with_encoding(GL_REMAP_VIEW_MULTISAMPLED)); + auto resolved_view = resolve->get_view(rsx::default_remap_vector.with_encoding(GL_REMAP_IDENTITY)); + + glBindImageTexture(GL_COMPUTE_IMAGE_SLOT(0), msaa_view->id(), 0, GL_FALSE, 0, GL_WRITE_ONLY, msaa_view->view_format()); + glBindImageTexture(GL_COMPUTE_IMAGE_SLOT(1), resolved_view->id(), 0, GL_FALSE, 0, GL_WRITE_ONLY, resolved_view->view_format()); + } + + void run(gl::command_context& cmd, gl::viewable_image* msaa_image, gl::viewable_image* resolve_image) + { + ensure(msaa_image->samples() > 1); + ensure(resolve_image->samples() == 1); + + multisampled = msaa_image; + resolve = resolve_image; + + const u32 invocations_x = utils::align(resolve_image->width(), cs_wave_x) / cs_wave_x; + const u32 invocations_y = utils::align(resolve_image->height(), cs_wave_y) / cs_wave_y; + + compute_task::run(cmd, invocations_x, invocations_y); + } + }; + + struct cs_resolve_task : cs_resolve_base + { + cs_resolve_task(const std::string& format_prefix) + { + build(format_prefix, false); + } + }; + + struct cs_unresolve_task : cs_resolve_base + { + cs_unresolve_task(const std::string& format_prefix) + { + build(format_prefix, true); + } + }; } diff --git a/rpcs3/Emu/RSX/GL/glutils/image.h b/rpcs3/Emu/RSX/GL/glutils/image.h index 7f77410d1f..d36cf26ea5 100644 --- a/rpcs3/Emu/RSX/GL/glutils/image.h +++ b/rpcs3/Emu/RSX/GL/glutils/image.h @@ -45,7 +45,8 @@ namespace gl enum remap_constants : u32 { GL_REMAP_IDENTITY = 0xCAFEBABE, - GL_REMAP_BGRA = 0x0000AA6C + GL_REMAP_BGRA = 0x0000AA6C, + GL_REMAP_VIEW_MULTISAMPLED = 0xDEADBEEF }; struct subresource_range diff --git a/rpcs3/Emu/RSX/Program/MSAA/ColorUnresolvePass.glsl b/rpcs3/Emu/RSX/Program/MSAA/ColorUnresolvePass.glsl index 201314e8c1..373d06ce0a 100644 --- a/rpcs3/Emu/RSX/Program/MSAA/ColorUnresolvePass.glsl +++ b/rpcs3/Emu/RSX/Program/MSAA/ColorUnresolvePass.glsl @@ -7,8 +7,8 @@ layout(local_size_x=%WORKGROUP_SIZE_X, local_size_y=%WORKGROUP_SIZE_Y, local_siz layout(set=0, binding=0) uniform writeonly restrict image2DMS multisampled; layout(set=0, binding=1, %IMAGE_FORMAT) uniform readonly restrict image2D resolve; #else -layout(binding=30) uniform readonly restrict image2DMS multisampled; -layout(binding=31, %IMAGE_FORMAT) uniform readonly restrict image2D resolve; +layout(binding=0) uniform readonly restrict image2DMS multisampled; +layout(binding=1, %IMAGE_FORMAT) uniform readonly restrict image2D resolve; #endif #if %BGRA_SWAP diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp b/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp index 899c6593e0..d09e248f6c 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp @@ -998,7 +998,7 @@ namespace vk return; } - // Memory transfers + // Memory transfers vk::image* target_image = (samples() > 1) ? get_resolve_target_safe(cmd) : this; vk::blitter hw_blitter; const auto dst_bpp = get_bpp(); diff --git a/rpcs3/GLGSRender.vcxproj b/rpcs3/GLGSRender.vcxproj index 9fbbaa3d2a..dbaffc5d00 100644 --- a/rpcs3/GLGSRender.vcxproj +++ b/rpcs3/GLGSRender.vcxproj @@ -60,7 +60,7 @@ - + @@ -96,7 +96,7 @@ - + diff --git a/rpcs3/GLGSRender.vcxproj.filters b/rpcs3/GLGSRender.vcxproj.filters index dca3a91380..4866b14643 100644 --- a/rpcs3/GLGSRender.vcxproj.filters +++ b/rpcs3/GLGSRender.vcxproj.filters @@ -48,7 +48,7 @@ upscalers\fsr1 - + @@ -121,7 +121,7 @@ upscalers - +