gl: Implement rgba8 -> fp16 casting pass

-- Is this actually necessary? The two format are binary compatible
This commit is contained in:
kd-11 2017-11-30 21:50:19 +03:00
parent fe9090bd39
commit bec6c1a939
2 changed files with 76 additions and 4 deletions

View File

@ -198,4 +198,47 @@ namespace gl
overlay_pass::run(w, h, target, true);
}
};
struct rgba8_rg16_convert_pass : public overlay_pass
{
rgba8_rg16_convert_pass()
{
vs_src =
{
"#version 420\n\n"
"\n"
"void main()\n"
"{\n"
" vec2 positions[] = {vec2(-1., -1.), vec2(1., -1.), vec2(-1., 1.), vec2(1., 1.)};\n"
" gl_Position = vec4(positions[gl_VertexID % 4], 0., 1.);\n"
"}\n"
};
fs_src =
{
"#version 420\n\n"
"layout(binding=31) uniform sampler2D fs0;\n"
"layout(location=0) out vec4 ocol;\n"
"\n"
"void main()\n"
"{\n"
" uvec4 rgba_in = uvec4(texelFetch(fs0, ivec2(gl_FragCoord.xy), 0) * 255. + vec4(0.5)).wyzx;\n"
" uint value = rgba_in.x | rgba_in.y << 8 | rgba_in.z << 16 | rgba_in.w << 24;\n"
" ocol.xy = unpackHalf2x16(value);\n"
" if (isnan(ocol.x)) ocol.x = 1.;\n"
" if (isnan(ocol.y)) ocol.y = 1.;\n"
" if (isinf(ocol.x)) ocol.x = 65504.;\n"
" if (isinf(ocol.y)) ocol.y = 65504.;\n"
"}\n"
};
}
void run(u16 w, u16 h, GLuint target, GLuint source)
{
glActiveTexture(GL_TEXTURE31);
glBindTexture(GL_TEXTURE_2D, source);
overlay_pass::run(w, h, target, false);
}
};
}

View File

@ -14,6 +14,7 @@
#include "Utilities/mutex.h"
#include "Emu/System.h"
#include "GLRenderTargets.h"
#include "GLOverlays.h"
#include "../Common/TextureUtils.h"
#include "../Common/texture_cache.h"
#include "../../Memory/vm.h"
@ -266,6 +267,19 @@ namespace gl
type = gl_type;
pack_unpack_swap_bytes = swap_bytes;
if (format == gl::texture::format::rgba)
{
switch (type)
{
case gl::texture::type::f16:
gcm_format = CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT;
break;
case gl::texture::type::f32:
gcm_format = CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT;
break;
}
}
real_pitch = width * get_pixel_size(format, type);
}
@ -448,7 +462,7 @@ namespace gl
rsx::scale_image_nearest(dst, const_cast<const void*>(data), width, height, rsx_pitch, real_pitch, pixel_size, samples_u, samples_v);
}
/* switch (gcm_format)
switch (gcm_format)
{
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
rsx::shuffle_texel_data_wzyx<u16>(dst, rsx_pitch, width, height);
@ -456,7 +470,7 @@ namespace gl
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
rsx::shuffle_texel_data_wzyx<u32>(dst, rsx_pitch, width, height);
break;
}*/
}
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
@ -566,6 +580,7 @@ namespace gl
private:
blitter m_hw_blitter;
gl::rgba8_rg16_convert_pass m_rgba8_rg16_converter;
std::vector<u32> m_temporary_surfaces;
cached_texture_section& create_texture(u32 id, u32 texaddr, u32 texsize, u32 w, u32 h, u32 depth, u32 mipmaps)
@ -634,14 +649,24 @@ namespace gl
glTexParameteri(dst_type, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(dst_type, GL_TEXTURE_MAX_LEVEL, 0);
m_temporary_surfaces.push_back(dst_id);
//Empty GL_ERROR
glGetError();
if (ifmt != sized_internal_fmt)
{
if (sized_internal_fmt == GL_RG16F && ifmt == GL_RGBA8_EXT)
{
//TODO: Better sized internal format detection
m_rgba8_rg16_converter.run(width, height, dst_id, src_id);
return dst_id;
}
}
glCopyImageSubData(src_id, GL_TEXTURE_2D, 0, x, y, 0,
dst_id, dst_type, 0, 0, 0, 0, width, height, 1);
m_temporary_surfaces.push_back(dst_id);
//Check for error
if (GLenum err = glGetError())
{
@ -808,6 +833,8 @@ namespace gl
{
m_hw_blitter.init();
g_hw_blitter = &m_hw_blitter;
m_rgba8_rg16_converter.create();
}
void destroy() override
@ -815,6 +842,8 @@ namespace gl
clear();
g_hw_blitter = nullptr;
m_hw_blitter.destroy();
m_rgba8_rg16_converter.destroy();
}
bool is_depth_texture(const u32 rsx_address, const u32 rsx_size) override