#include "stdafx.h" #include "GLResolveHelper.h" #include namespace gl { std::unordered_map> g_resolve_helpers; std::unordered_map> g_unresolve_helpers; std::unordered_map> g_depth_resolvers; std::unordered_map> g_depth_unresolvers; 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) { ensure(src->samples() > 1 && dst->samples() == 1); 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) { ensure(dst->samples() > 1 && src->samples() == 1); if (src->aspect() == gl::image_aspect::color) [[ likely ]] { 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); return; } auto get_unresolver_pass = [](GLuint aspect_bits) -> std::unique_ptr& { auto& pass = g_depth_unresolvers[aspect_bits]; if (!pass) { ds_resolve_pass_base* ptr = nullptr; switch (aspect_bits) { case gl::image_aspect::depth: ptr = new depth_only_unresolver(); break; case gl::image_aspect::stencil: ptr = new stencil_only_unresolver(); break; case (gl::image_aspect::depth | gl::image_aspect::stencil): ptr = new depth_stencil_unresolver(); break; default: fmt::throw_exception("Unreachable"); } pass.reset(ptr); } return pass; }; if (src->aspect() == (gl::image_aspect::depth | gl::image_aspect::stencil) && !gl::get_driver_caps().ARB_shader_stencil_export_supported) { // Special handling rsx_log.error("Unsupported."); return; } auto& pass = get_unresolver_pass(src->aspect()); pass->run(cmd, dst, src); } // Implementation void cs_resolve_base::build(const std::string& format_prefix, bool unresolve) { is_unresolve = unresolve; 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/ColorUnresolvePass.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); create(); } void cs_resolve_base::bind_resources() { 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, is_unresolve ? GL_WRITE_ONLY : GL_READ_ONLY, msaa_view->view_format()); glBindImageTexture(GL_COMPUTE_IMAGE_SLOT(1), resolved_view->id(), 0, GL_FALSE, 0, is_unresolve ? GL_READ_ONLY : GL_WRITE_ONLY, resolved_view->view_format()); } void cs_resolve_base::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); } void ds_resolve_pass_base::build(bool depth, bool stencil, bool unresolve) { m_config.resolve_depth = depth; m_config.resolve_stencil = stencil; m_config.is_unresolve = unresolve; vs_src = #include "Emu/RSX/Program/GLSLSnippets/GenericVSPassthrough.glsl" ; static const char* depth_resolver = #include "Emu/RSX/Program/MSAA/DepthResolvePass.glsl" ; static const char* depth_unresolver = #include "Emu/RSX/Program/MSAA/DepthUnresolvePass.glsl" ; static const char* stencil_resolver = #include "Emu/RSX/Program/MSAA/StencilResolvePass.glsl" ; static const char* stencil_unresolver = #include "Emu/RSX/Program/MSAA/StencilUnresolvePass.glsl" ; static const char* depth_stencil_resolver = #include "Emu/RSX/Program/MSAA/DepthStencilResolvePass.glsl" ; static const char* depth_stencil_unresolver = #include "Emu/RSX/Program/MSAA/DepthStencilUnresolvePass.glsl" ; if (m_config.resolve_depth && m_config.resolve_stencil) { fs_src = m_config.is_unresolve ? depth_stencil_unresolver : depth_stencil_resolver; } else if (m_config.resolve_depth) { fs_src = m_config.is_unresolve ? depth_unresolver : depth_resolver; } else if (m_config.resolve_stencil) { fs_src = m_config.is_unresolve ? stencil_unresolver : stencil_resolver; } create(); rsx_log.notice("Resolve shader:\n%s", fs_src); } void ds_resolve_pass_base::run(gl::command_context& cmd, gl::viewable_image* msaa_image, gl::viewable_image* resolve_image) { const auto read_resource = m_config.is_unresolve ? resolve_image : msaa_image; saved_sampler_state saved(GL_TEMP_IMAGE_SLOT(0), m_sampler); cmd->bind_texture(GL_TEMP_IMAGE_SLOT(0), GL_TEXTURE_2D, read_resource->id()); GLuint image_aspect_bits = 0; if (m_config.resolve_depth) image_aspect_bits |= gl::image_aspect::depth; if (m_config.resolve_stencil) image_aspect_bits |= gl::image_aspect::stencil; areau viewport{}; viewport.x2 = msaa_image->width(); viewport.y2 = msaa_image->height(); overlay_pass::run(cmd, viewport, GL_NONE, image_aspect_bits, false); } }