mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
rsx: Add anaglyph 3D filter
This commit is contained in:
parent
6e3406b3f5
commit
1725f7a34b
5 changed files with 151 additions and 27 deletions
|
@ -154,7 +154,7 @@ private:
|
|||
|
||||
void update_draw_state();
|
||||
|
||||
GLuint get_present_source(gl::present_surface_info* info, const rsx::avconf* avconfig);
|
||||
gl::texture* get_present_source(gl::present_surface_info* info, const rsx::avconf* avconfig);
|
||||
|
||||
public:
|
||||
void set_viewport();
|
||||
|
|
|
@ -740,15 +740,39 @@ namespace gl
|
|||
fs_src =
|
||||
"#version 420\n\n"
|
||||
"layout(binding=31) uniform sampler2D fs0;\n"
|
||||
"layout(binding=30) uniform sampler2D fs1;\n"
|
||||
"layout(location=0) in vec2 tc0;\n"
|
||||
"layout(location=0) out vec4 ocol;\n"
|
||||
"\n"
|
||||
"uniform float gamma;\n"
|
||||
"uniform int limit_range;\n"
|
||||
"uniform int stereo;\n"
|
||||
"uniform int stereo_image_count;\n"
|
||||
"\n"
|
||||
"vec4 read_source()\n"
|
||||
"{\n"
|
||||
" if (stereo == 0) return texture(fs0, tc0);\n"
|
||||
"\n"
|
||||
" vec4 left, right;\n"
|
||||
" if (stereo_image_count == 2)\n"
|
||||
" {\n"
|
||||
" left = texture(fs0, tc0);\n"
|
||||
" right = texture(fs1, tc0);\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" vec2 coord_left = tc0 * vec2(1.f, 0.4898f);\n"
|
||||
" vec2 coord_right = coord_left + vec2(0.f, 0.510204f);\n"
|
||||
" left = texture(fs0, coord_left);\n"
|
||||
" right = texture(fs0, coord_right);\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" return vec4(left.r, right.g, right.b, 1.);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 color = texture(fs0, tc0);\n"
|
||||
" vec4 color = read_source();\n"
|
||||
" color.rgb = pow(color.rgb, vec3(gamma));\n"
|
||||
" if (limit_range > 0)\n"
|
||||
" ocol = ((color * 220.) + 16.) / 255.;\n"
|
||||
|
@ -759,13 +783,19 @@ namespace gl
|
|||
input_filter = GL_LINEAR;
|
||||
}
|
||||
|
||||
void run(const areau& viewport, GLuint source, f32 gamma, bool limited_rgb)
|
||||
void run(const areau& viewport, const rsx::simple_array<GLuint>& source, f32 gamma, bool limited_rgb, bool _3d)
|
||||
{
|
||||
program_handle.uniforms["gamma"] = gamma;
|
||||
program_handle.uniforms["limit_range"] = limited_rgb + 0;
|
||||
program_handle.uniforms["stereo"] = _3d + 0;
|
||||
program_handle.uniforms["stereo_image_count"] = (source[1] == GL_NONE? 1 : 2);
|
||||
|
||||
saved_sampler_state saved(31, m_sampler);
|
||||
glBindTexture(GL_TEXTURE_2D, source);
|
||||
glBindTexture(GL_TEXTURE_2D, source[0]);
|
||||
|
||||
saved_sampler_state saved2(30, m_sampler);
|
||||
glBindTexture(GL_TEXTURE_2D, source[1]);
|
||||
|
||||
overlay_pass::run(viewport, GL_NONE, false, false);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
LOG_CHANNEL(screenshot);
|
||||
|
||||
GLuint GLGSRender::get_present_source(gl::present_surface_info* info, const rsx::avconf* avconfig)
|
||||
gl::texture* GLGSRender::get_present_source(gl::present_surface_info* info, const rsx::avconf* avconfig)
|
||||
{
|
||||
GLuint image = GL_NONE;
|
||||
gl::texture* image = nullptr;
|
||||
|
||||
// Check the surface store first
|
||||
gl::command_context cmd = { gl_state };
|
||||
|
@ -45,7 +45,7 @@ GLuint GLGSRender::get_present_source(gl::present_surface_info* info, const rsx:
|
|||
if (viable)
|
||||
{
|
||||
surface->read_barrier(cmd);
|
||||
image = section.surface->get_surface(rsx::surface_access::read)->id();
|
||||
image = section.surface->get_surface(rsx::surface_access::read);
|
||||
|
||||
info->width = rsx::apply_resolution_scale(std::min(surface_width, static_cast<u16>(info->width)), true);
|
||||
info->height = rsx::apply_resolution_scale(std::min(surface_height, static_cast<u16>(info->height)), true);
|
||||
|
@ -56,7 +56,7 @@ GLuint GLGSRender::get_present_source(gl::present_surface_info* info, const rsx:
|
|||
{
|
||||
// Hack - this should be the first location to check for output
|
||||
// The render might have been done offscreen or in software and a blit used to display
|
||||
if (const auto tex = surface->get_raw_texture(); tex) image = tex->id();
|
||||
if (const auto tex = surface->get_raw_texture(); tex) image = tex;
|
||||
}
|
||||
|
||||
if (!image)
|
||||
|
@ -76,7 +76,7 @@ GLuint GLGSRender::get_present_source(gl::present_surface_info* info, const rsx:
|
|||
m_gl_texture_cache.invalidate_range(cmd, range, rsx::invalidation_cause::read);
|
||||
|
||||
m_flip_tex_color->copy_from(vm::base(info->address), gl::texture::format::bgra, gl::texture::type::uint_8_8_8_8, unpack_settings);
|
||||
image = m_flip_tex_color->id();
|
||||
image = m_flip_tex_color.get();
|
||||
}
|
||||
|
||||
return image;
|
||||
|
@ -121,7 +121,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
|
|||
// Enable drawing to window backbuffer
|
||||
gl::screen.bind();
|
||||
|
||||
GLuint image_to_flip = GL_NONE;
|
||||
GLuint image_to_flip = GL_NONE, image_to_flip2 = GL_NONE;
|
||||
|
||||
if (info.buffer < display_buffers_count && buffer_width && buffer_height)
|
||||
{
|
||||
|
@ -133,7 +133,29 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
|
|||
present_info.format = av_format;
|
||||
present_info.address = rsx::get_address(display_buffers[info.buffer].offset, CELL_GCM_LOCATION_LOCAL, HERE);
|
||||
|
||||
image_to_flip = get_present_source(&present_info, avconfig);
|
||||
const auto image_to_flip_ = get_present_source(&present_info, avconfig);
|
||||
image_to_flip = image_to_flip_->id();
|
||||
|
||||
if (avconfig->_3d) [[unlikely]]
|
||||
{
|
||||
const auto min_expected_height = rsx::apply_resolution_scale(buffer_height + 30, true);
|
||||
if (image_to_flip_->height() < min_expected_height)
|
||||
{
|
||||
// Get image for second eye
|
||||
const u32 image_offset = (buffer_height + 30) * buffer_pitch + display_buffers[info.buffer].offset;
|
||||
present_info.width = buffer_width;
|
||||
present_info.height = buffer_height;
|
||||
present_info.address = rsx::get_address(image_offset, CELL_GCM_LOCATION_LOCAL, HERE);
|
||||
|
||||
image_to_flip2 = get_present_source(&present_info, avconfig)->id();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Account for possible insets
|
||||
buffer_height = std::min<u32>(image_to_flip_->height() - min_expected_height, rsx::apply_resolution_scale(buffer_height, true));
|
||||
}
|
||||
}
|
||||
|
||||
buffer_width = present_info.width;
|
||||
buffer_height = present_info.height;
|
||||
}
|
||||
|
@ -194,7 +216,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
|
|||
|
||||
areai screen_area = coordi({}, { static_cast<int>(buffer_width), static_cast<int>(buffer_height) });
|
||||
|
||||
if (g_cfg.video.full_rgb_range_output && rsx::fcmp(avconfig->gamma, 1.f))
|
||||
if (g_cfg.video.full_rgb_range_output && rsx::fcmp(avconfig->gamma, 1.f) && !avconfig->_3d)
|
||||
{
|
||||
// Blit source image to the screen
|
||||
m_flip_fbo.recreate();
|
||||
|
@ -208,9 +230,10 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
|
|||
{
|
||||
const f32 gamma = avconfig->gamma;
|
||||
const bool limited_range = !g_cfg.video.full_rgb_range_output;
|
||||
const rsx::simple_array<GLuint> images{ image_to_flip, image_to_flip2 };
|
||||
|
||||
gl::screen.bind();
|
||||
m_video_output_pass.run(areau(aspect_ratio), image_to_flip, gamma, limited_range);
|
||||
m_video_output_pass.run(areau(aspect_ratio), images, gamma, limited_range, avconfig->_3d);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1048,9 +1048,11 @@ namespace vk
|
|||
{
|
||||
float gamma;
|
||||
int limit_range;
|
||||
int stereo;
|
||||
int stereo_image_count;
|
||||
};
|
||||
|
||||
float data[2];
|
||||
float data[4];
|
||||
}
|
||||
config;
|
||||
|
||||
|
@ -1072,6 +1074,7 @@ namespace vk
|
|||
fs_src =
|
||||
"#version 420\n\n"
|
||||
"layout(set=0, binding=1) uniform sampler2D fs0;\n"
|
||||
"layout(set=0, binding=2) uniform sampler2D fs1;\n"
|
||||
"layout(location=0) in vec2 tc0;\n"
|
||||
"layout(location=0) out vec4 ocol;\n"
|
||||
"\n"
|
||||
|
@ -1079,11 +1082,34 @@ namespace vk
|
|||
"{\n"
|
||||
" float gamma;\n"
|
||||
" int limit_range;\n"
|
||||
" int stereo;\n"
|
||||
" int stereo_image_count;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"vec4 read_source()\n"
|
||||
"{\n"
|
||||
" if (stereo == 0) return texture(fs0, tc0);\n"
|
||||
"\n"
|
||||
" vec4 left, right;\n"
|
||||
" if (stereo_image_count == 2)\n"
|
||||
" {\n"
|
||||
" left = texture(fs0, tc0);\n"
|
||||
" right = texture(fs1, tc0);\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" vec2 coord_left = tc0 * vec2(1.f, 0.4898f);\n"
|
||||
" vec2 coord_right = coord_left + vec2(0.f, 0.510204f);\n"
|
||||
" left = texture(fs0, coord_left);\n"
|
||||
" right = texture(fs0, coord_right);\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" return vec4(left.r, right.g, right.b, 1.);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 color = texture(fs0, tc0);\n"
|
||||
" vec4 color = read_source();\n"
|
||||
" color.rgb = pow(color.rgb, vec3(gamma));\n"
|
||||
" if (limit_range > 0)\n"
|
||||
" ocol = ((color * 220.) + 16.) / 255.;\n"
|
||||
|
@ -1094,6 +1120,8 @@ namespace vk
|
|||
renderpass_config.set_depth_mask(false);
|
||||
renderpass_config.set_color_mask(0, true, true, true, true);
|
||||
renderpass_config.set_attachment_count(1);
|
||||
|
||||
m_num_usable_samplers = 2;
|
||||
}
|
||||
|
||||
std::vector<VkPushConstantRange> get_push_constants() override
|
||||
|
@ -1101,23 +1129,39 @@ namespace vk
|
|||
VkPushConstantRange constant;
|
||||
constant.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
constant.offset = 0;
|
||||
constant.size = 8;
|
||||
constant.size = 16;
|
||||
|
||||
return { constant };
|
||||
}
|
||||
|
||||
void update_uniforms(vk::command_buffer& cmd, vk::glsl::program* /*program*/) override
|
||||
{
|
||||
vkCmdPushConstants(cmd, m_pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, 8, config.data);
|
||||
vkCmdPushConstants(cmd, m_pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, config.data);
|
||||
}
|
||||
|
||||
void run(vk::command_buffer &cmd, const areau& viewport, vk::framebuffer* target, vk::viewable_image* src,
|
||||
f32 gamma, bool limited_rgb, VkRenderPass render_pass)
|
||||
void run(vk::command_buffer &cmd, const areau& viewport, vk::framebuffer* target,
|
||||
const rsx::simple_array<vk::viewable_image*>& src,
|
||||
f32 gamma, bool limited_rgb, bool _3d, VkRenderPass render_pass)
|
||||
{
|
||||
config.gamma = gamma;
|
||||
config.limit_range = limited_rgb? 1 : 0;
|
||||
config.stereo = _3d? 1 : 0;
|
||||
config.stereo_image_count = std::min(::size32(src), 2u);
|
||||
|
||||
overlay_pass::run(cmd, viewport, target, { src->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector) }, render_pass);
|
||||
std::vector<vk::image_view*> views;
|
||||
views.reserve(2);
|
||||
|
||||
for (auto& img : src)
|
||||
{
|
||||
views.push_back(img->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector));
|
||||
}
|
||||
|
||||
if (views.size() < 2)
|
||||
{
|
||||
views.push_back(vk::null_image_view(cmd, VK_IMAGE_VIEW_TYPE_2D));
|
||||
}
|
||||
|
||||
overlay_pass::run(cmd, viewport, target, views, render_pass);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -431,7 +431,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
|||
}
|
||||
|
||||
// Scan memory for required data. This is done early to optimize waiting for the driver image acquire below.
|
||||
vk::image* image_to_flip = nullptr;
|
||||
vk::image *image_to_flip = nullptr, *image_to_flip2 = nullptr;
|
||||
if (info.buffer < display_buffers_count && buffer_width && buffer_height)
|
||||
{
|
||||
vk::present_surface_info present_info;
|
||||
|
@ -442,6 +442,27 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
|||
present_info.address = rsx::get_address(display_buffers[info.buffer].offset, CELL_GCM_LOCATION_LOCAL, HERE);
|
||||
|
||||
image_to_flip = get_present_source(&present_info, avconfig);
|
||||
|
||||
if (avconfig->_3d) [[unlikely]]
|
||||
{
|
||||
const auto min_expected_height = rsx::apply_resolution_scale(buffer_height + 30, true);
|
||||
if (image_to_flip->height() < min_expected_height)
|
||||
{
|
||||
// Get image for second eye
|
||||
const u32 image_offset = (buffer_height + 30) * buffer_pitch + display_buffers[info.buffer].offset;
|
||||
present_info.width = buffer_width;
|
||||
present_info.height = buffer_height;
|
||||
present_info.address = rsx::get_address(image_offset, CELL_GCM_LOCATION_LOCAL, HERE);
|
||||
|
||||
image_to_flip2 = get_present_source(&present_info, avconfig);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Account for possible insets
|
||||
buffer_height = std::min<u32>(image_to_flip->height() - min_expected_height, rsx::apply_resolution_scale(buffer_height, true));
|
||||
}
|
||||
}
|
||||
|
||||
buffer_width = present_info.width;
|
||||
buffer_height = present_info.height;
|
||||
}
|
||||
|
@ -526,7 +547,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
|||
|
||||
VkRenderPass single_target_pass = VK_NULL_HANDLE;
|
||||
vk::framebuffer_holder* direct_fbo = nullptr;
|
||||
vk::viewable_image* calibration_src = nullptr;
|
||||
rsx::simple_array<vk::viewable_image*> calibration_src;
|
||||
|
||||
if (!image_to_flip || aspect_ratio.width < csize.width || aspect_ratio.height < csize.height)
|
||||
{
|
||||
|
@ -540,13 +561,19 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
|||
|
||||
if (image_to_flip)
|
||||
{
|
||||
if (!g_cfg.video.full_rgb_range_output || !rsx::fcmp(avconfig->gamma, 1.f)) [[unlikely]]
|
||||
if (!g_cfg.video.full_rgb_range_output || !rsx::fcmp(avconfig->gamma, 1.f) || avconfig->_3d) [[unlikely]]
|
||||
{
|
||||
calibration_src = dynamic_cast<vk::viewable_image*>(image_to_flip);
|
||||
verify("Image handle not viewable!" HERE), calibration_src;
|
||||
calibration_src.push_back(dynamic_cast<vk::viewable_image*>(image_to_flip));
|
||||
verify("Image not viewable" HERE), calibration_src.front();
|
||||
|
||||
if (image_to_flip2)
|
||||
{
|
||||
calibration_src.push_back(dynamic_cast<vk::viewable_image*>(image_to_flip2));
|
||||
verify("Image not viewable" HERE), calibration_src.back();
|
||||
}
|
||||
}
|
||||
|
||||
if (!calibration_src) [[likely]]
|
||||
if (calibration_src.empty()) [[likely]]
|
||||
{
|
||||
vk::copy_scaled_image(*m_current_command_buffer, image_to_flip->value, target_image, image_to_flip->current_layout, target_layout,
|
||||
{ 0, 0, static_cast<s32>(buffer_width), static_cast<s32>(buffer_height) }, aspect_ratio, 1, VK_IMAGE_ASPECT_COLOR_BIT, false);
|
||||
|
@ -564,7 +591,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
|||
direct_fbo->add_ref();
|
||||
|
||||
image_to_flip->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
m_video_output_pass->run(*m_current_command_buffer, areau(aspect_ratio), direct_fbo, calibration_src, avconfig->gamma, !g_cfg.video.full_rgb_range_output, single_target_pass);
|
||||
m_video_output_pass->run(*m_current_command_buffer, areau(aspect_ratio), direct_fbo, calibration_src, avconfig->gamma, !g_cfg.video.full_rgb_range_output, avconfig->_3d, single_target_pass);
|
||||
image_to_flip->pop_layout(*m_current_command_buffer);
|
||||
|
||||
direct_fbo->release();
|
||||
|
|
Loading…
Add table
Reference in a new issue