mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 18:53:28 +01:00
gl: Reimplement textures
- Separate texture data from texture views
This commit is contained in:
parent
cf1b700ebc
commit
6d46ac1ad6
@ -209,7 +209,7 @@ void GLGSRender::end()
|
||||
//If ds is not initialized clear it; it seems new depth textures should have depth cleared
|
||||
auto copy_rtt_contents = [](gl::render_target *surface)
|
||||
{
|
||||
if (surface->get_compatible_internal_format() == surface->old_contents->get_compatible_internal_format())
|
||||
if (surface->get_internal_format() == surface->old_contents->get_internal_format())
|
||||
{
|
||||
//Copy data from old contents onto this one
|
||||
//1. Clip a rectangular region defning the data
|
||||
@ -284,7 +284,7 @@ void GLGSRender::end()
|
||||
}
|
||||
|
||||
if (ds && ds->old_contents != nullptr && ds->get_rsx_pitch() == ds->old_contents->get_rsx_pitch() &&
|
||||
ds->old_contents->get_compatible_internal_format() == gl::texture::internal_format::rgba8)
|
||||
ds->old_contents->get_internal_format() == gl::texture::internal_format::rgba8)
|
||||
{
|
||||
m_depth_converter.run(ds->width(), ds->height(), ds->id(), ds->old_contents->id());
|
||||
ds->old_contents = nullptr;
|
||||
@ -413,18 +413,18 @@ void GLGSRender::end()
|
||||
|
||||
if (tex.enabled())
|
||||
{
|
||||
GLenum target = gl::get_target(sampler_state->image_type);
|
||||
if (sampler_state->image_handle)
|
||||
{
|
||||
glBindTexture(target, sampler_state->image_handle);
|
||||
sampler_state->image_handle->bind();
|
||||
}
|
||||
else if (sampler_state->external_subresource_desc.external_handle)
|
||||
{
|
||||
void *unused = nullptr;
|
||||
glBindTexture(target, m_gl_texture_cache.create_temporary_subresource(unused, sampler_state->external_subresource_desc));
|
||||
m_gl_texture_cache.create_temporary_subresource(unused, sampler_state->external_subresource_desc)->bind();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto target = gl::get_target(sampler_state->image_type);
|
||||
glBindTexture(target, m_null_textures[target]->id());
|
||||
}
|
||||
}
|
||||
@ -447,12 +447,12 @@ void GLGSRender::end()
|
||||
|
||||
if (sampler_state->image_handle)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, sampler_state->image_handle);
|
||||
sampler_state->image_handle->bind();
|
||||
}
|
||||
else if (sampler_state->external_subresource_desc.external_handle)
|
||||
{
|
||||
void *unused = nullptr;
|
||||
glBindTexture(GL_TEXTURE_2D, m_gl_texture_cache.create_temporary_subresource(unused, sampler_state->external_subresource_desc));
|
||||
m_gl_texture_cache.create_temporary_subresource(unused, sampler_state->external_subresource_desc)->bind();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -660,20 +660,16 @@ void GLGSRender::on_init_thread()
|
||||
|
||||
//Array stream buffer
|
||||
{
|
||||
auto &tex = m_gl_persistent_stream_buffer;
|
||||
tex.create();
|
||||
tex.set_target(gl::texture::target::textureBuffer);
|
||||
m_gl_persistent_stream_buffer = std::make_unique<gl::texture>(GL_TEXTURE_BUFFER, 0, 0, 0, 0, GL_R8UI);
|
||||
glActiveTexture(GL_TEXTURE0 + texture_index_offset);
|
||||
tex.bind();
|
||||
glBindTexture(GL_TEXTURE_BUFFER, m_gl_persistent_stream_buffer->id());
|
||||
}
|
||||
|
||||
//Register stream buffer
|
||||
{
|
||||
auto &tex = m_gl_volatile_stream_buffer;
|
||||
tex.create();
|
||||
tex.set_target(gl::texture::target::textureBuffer);
|
||||
m_gl_volatile_stream_buffer = std::make_unique<gl::texture>(GL_TEXTURE_BUFFER, 0, 0, 0, 0, GL_R8UI);
|
||||
glActiveTexture(GL_TEXTURE0 + texture_index_offset + 1);
|
||||
tex.bind();
|
||||
glBindTexture(GL_TEXTURE_BUFFER, m_gl_volatile_stream_buffer->id());
|
||||
}
|
||||
|
||||
//Fallback null texture instead of relying on texture0
|
||||
@ -681,28 +677,20 @@ void GLGSRender::on_init_thread()
|
||||
std::vector<u32> pixeldata = {0, 0, 0, 0};
|
||||
|
||||
//1D
|
||||
auto tex1D = std::make_unique<gl::texture>();
|
||||
tex1D->create();
|
||||
tex1D->set_target(gl::texture::target::texture1D);
|
||||
tex1D->config().width(1).min_lod(0.f).max_lod(0.f).pixels(pixeldata.data()).apply();
|
||||
auto tex1D = std::make_unique<gl::texture>(GL_TEXTURE_1D, 1, 1, 1, 1, GL_RGBA8);
|
||||
tex1D->copy_from(pixeldata.data(), gl::texture::format::rgba, gl::texture::type::uint_8_8_8_8);
|
||||
|
||||
//2D
|
||||
auto tex2D = std::make_unique<gl::texture>();
|
||||
tex2D->create();
|
||||
tex2D->set_target(gl::texture::target::texture2D);
|
||||
tex2D->config().width(1).height(1).min_lod(0.f).max_lod(0.f).pixels(pixeldata.data()).apply();
|
||||
auto tex2D = std::make_unique<gl::texture>(GL_TEXTURE_2D, 1, 1, 1, 1, GL_RGBA8);
|
||||
tex2D->copy_from(pixeldata.data(), gl::texture::format::rgba, gl::texture::type::uint_8_8_8_8);
|
||||
|
||||
//3D
|
||||
auto tex3D = std::make_unique<gl::texture>();
|
||||
tex3D->create();
|
||||
tex3D->set_target(gl::texture::target::texture3D);
|
||||
tex3D->config().width(1).height(1).depth(1).min_lod(0.f).max_lod(0.f).pixels(pixeldata.data()).apply();
|
||||
auto tex3D = std::make_unique<gl::texture>(GL_TEXTURE_3D, 1, 1, 1, 1, GL_RGBA8);
|
||||
tex3D->copy_from(pixeldata.data(), gl::texture::format::rgba, gl::texture::type::uint_8_8_8_8);
|
||||
|
||||
//CUBE
|
||||
auto texCUBE = std::make_unique<gl::texture>();
|
||||
texCUBE->create();
|
||||
texCUBE->set_target(gl::texture::target::textureCUBE);
|
||||
texCUBE->config().width(1).height(1).depth(1).min_lod(0.f).max_lod(0.f).pixels(pixeldata.data()).apply();
|
||||
auto texCUBE = std::make_unique<gl::texture>(GL_TEXTURE_CUBE_MAP, 1, 1, 1, 1, GL_RGBA8);
|
||||
texCUBE->copy_from(pixeldata.data(), gl::texture::format::rgba, gl::texture::type::uint_8_8_8_8);
|
||||
|
||||
m_null_textures[GL_TEXTURE_1D] = std::move(tex1D);
|
||||
m_null_textures[GL_TEXTURE_2D] = std::move(tex2D);
|
||||
@ -745,8 +733,8 @@ void GLGSRender::on_init_thread()
|
||||
|
||||
m_persistent_stream_view.update(m_attrib_ring_buffer.get(), 0, std::min<u32>((u32)m_attrib_ring_buffer->size(), m_max_texbuffer_size));
|
||||
m_volatile_stream_view.update(m_attrib_ring_buffer.get(), 0, std::min<u32>((u32)m_attrib_ring_buffer->size(), m_max_texbuffer_size));
|
||||
m_gl_persistent_stream_buffer.copy_from(m_persistent_stream_view);
|
||||
m_gl_volatile_stream_buffer.copy_from(m_volatile_stream_view);
|
||||
m_gl_persistent_stream_buffer->copy_from(m_persistent_stream_view);
|
||||
m_gl_volatile_stream_buffer->copy_from(m_volatile_stream_view);
|
||||
|
||||
m_vao.element_array_buffer = *m_index_ring_buffer;
|
||||
|
||||
@ -871,7 +859,7 @@ void GLGSRender::on_exit()
|
||||
|
||||
if (m_flip_tex_color)
|
||||
{
|
||||
m_flip_tex_color.remove();
|
||||
m_flip_tex_color.reset();
|
||||
}
|
||||
|
||||
if (m_vao)
|
||||
@ -879,19 +867,14 @@ void GLGSRender::on_exit()
|
||||
m_vao.remove();
|
||||
}
|
||||
|
||||
m_gl_persistent_stream_buffer.remove();
|
||||
m_gl_volatile_stream_buffer.remove();
|
||||
m_gl_persistent_stream_buffer.reset();
|
||||
m_gl_volatile_stream_buffer.reset();
|
||||
|
||||
for (auto &sampler : m_gl_sampler_states)
|
||||
{
|
||||
sampler.remove();
|
||||
}
|
||||
|
||||
for (auto &tex : m_null_textures)
|
||||
{
|
||||
tex.second->remove();
|
||||
}
|
||||
|
||||
if (m_attrib_ring_buffer)
|
||||
{
|
||||
m_attrib_ring_buffer->remove();
|
||||
@ -917,6 +900,7 @@ void GLGSRender::on_exit()
|
||||
m_index_ring_buffer->remove();
|
||||
}
|
||||
|
||||
m_null_textures.clear();
|
||||
m_text_printer.close();
|
||||
m_gl_texture_cache.destroy();
|
||||
m_depth_converter.destroy();
|
||||
@ -1366,13 +1350,13 @@ void GLGSRender::flip(int buffer)
|
||||
buffer_width = render_target_texture->width();
|
||||
buffer_height = render_target_texture->height();
|
||||
|
||||
image = render_target_texture->get_view();
|
||||
image = render_target_texture->raw_handle();
|
||||
}
|
||||
else if (auto surface = m_gl_texture_cache.find_texture_from_dimensions(absolute_address))
|
||||
{
|
||||
//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
|
||||
image = surface->get_raw_view();
|
||||
image = surface->get_raw_view()->id();
|
||||
|
||||
//Reset color swizzle
|
||||
glBindTexture(GL_TEXTURE_2D, image);
|
||||
@ -1385,30 +1369,26 @@ void GLGSRender::flip(int buffer)
|
||||
LOG_WARNING(RSX, "Flip texture was not found in cache. Uploading surface from CPU");
|
||||
|
||||
if (!buffer_pitch) buffer_pitch = buffer_width * 4;
|
||||
if (!m_flip_tex_color || m_flip_tex_color.size() != sizei{ (int)buffer_width, (int)buffer_height })
|
||||
gl::pixel_unpack_settings unpack_settings;
|
||||
unpack_settings.aligment(1).row_length(buffer_pitch / 4);
|
||||
|
||||
if (!m_flip_tex_color || m_flip_tex_color->size2D() != sizei{ (int)buffer_width, (int)buffer_height })
|
||||
{
|
||||
m_flip_tex_color.recreate(gl::texture::target::texture2D);
|
||||
|
||||
m_flip_tex_color.config()
|
||||
.size({ (int)buffer_width, (int)buffer_height })
|
||||
.type(gl::texture::type::uint_8_8_8_8)
|
||||
.format(gl::texture::format::bgra);
|
||||
|
||||
m_flip_tex_color.pixel_unpack_settings().aligment(1).row_length(buffer_pitch / 4);
|
||||
m_flip_tex_color.reset(new gl::texture(GL_TEXTURE_2D, buffer_width, buffer_height, 1, 1, GL_RGBA8));
|
||||
}
|
||||
|
||||
if (buffer_region.tile)
|
||||
{
|
||||
std::unique_ptr<u8[]> temp(new u8[buffer_height * buffer_pitch]);
|
||||
buffer_region.read(temp.get(), buffer_width, buffer_height, buffer_pitch);
|
||||
m_flip_tex_color.copy_from(temp.get(), gl::texture::format::bgra, gl::texture::type::uint_8_8_8_8);
|
||||
m_flip_tex_color->copy_from(temp.get(), gl::texture::format::bgra, gl::texture::type::uint_8_8_8_8, unpack_settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flip_tex_color.copy_from(buffer_region.ptr, gl::texture::format::bgra, gl::texture::type::uint_8_8_8_8);
|
||||
m_flip_tex_color->copy_from(buffer_region.ptr, 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->id();
|
||||
}
|
||||
|
||||
areai screen_area = coordi({}, { (int)buffer_width, (int)buffer_height });
|
||||
|
@ -281,8 +281,8 @@ private:
|
||||
|
||||
gl::buffer_view m_persistent_stream_view;
|
||||
gl::buffer_view m_volatile_stream_view;
|
||||
gl::texture m_gl_persistent_stream_buffer;
|
||||
gl::texture m_gl_volatile_stream_buffer;
|
||||
std::unique_ptr<gl::texture> m_gl_persistent_stream_buffer;
|
||||
std::unique_ptr<gl::texture> m_gl_volatile_stream_buffer;
|
||||
|
||||
std::unique_ptr<gl::ring_buffer> m_attrib_ring_buffer;
|
||||
std::unique_ptr<gl::ring_buffer> m_fragment_constants_buffer;
|
||||
@ -323,7 +323,7 @@ private:
|
||||
//buffer
|
||||
gl::fbo draw_fbo;
|
||||
gl::fbo m_flip_fbo;
|
||||
gl::texture m_flip_tex_color;
|
||||
std::unique_ptr<gl::texture> m_flip_tex_color;
|
||||
|
||||
//vaos are mandatory for core profile
|
||||
gl::vao m_vao;
|
||||
|
@ -306,279 +306,6 @@ namespace gl
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void texture::settings::apply(const texture &texture) const
|
||||
{
|
||||
save_binding_state save(texture);
|
||||
|
||||
texture.pixel_unpack_settings().apply();
|
||||
|
||||
if (compressed_format(m_internal_format))
|
||||
{
|
||||
int compressed_image_size = m_compressed_image_size;
|
||||
if (!compressed_image_size)
|
||||
{
|
||||
switch (m_internal_format)
|
||||
{
|
||||
case texture::internal_format::compressed_rgb_s3tc_dxt1:
|
||||
compressed_image_size = ((m_width + 2) / 3) * ((m_height + 2) / 3) * 6;
|
||||
break;
|
||||
|
||||
case texture::internal_format::compressed_rgba_s3tc_dxt1:
|
||||
compressed_image_size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 8;
|
||||
break;
|
||||
|
||||
case texture::internal_format::compressed_rgba_s3tc_dxt3:
|
||||
case texture::internal_format::compressed_rgba_s3tc_dxt5:
|
||||
compressed_image_size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 16;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Tried to load unimplemented internal_format type." HERE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_parent->get_target() != gl::texture::target::texture2D)
|
||||
fmt::throw_exception("Mutable compressed texture of non-2D type is unimplemented" HERE);
|
||||
|
||||
glCompressedTexImage2D((GLenum)m_parent->get_target(), m_level, (GLint)m_internal_format, m_width, m_height, 0, compressed_image_size, m_pixels);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ((GLenum)m_parent->get_target())
|
||||
{
|
||||
case GL_TEXTURE_1D:
|
||||
{
|
||||
glTexImage1D(GL_TEXTURE_1D, m_level, (GLint)m_internal_format, m_width, 0, (GLint)m_format, (GLint)m_type, m_pixels);
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_2D:
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, m_level, (GLint)m_internal_format, m_width, m_height, 0, (GLint)m_format, (GLint)m_type, m_pixels);
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_3D:
|
||||
{
|
||||
glTexImage3D(GL_TEXTURE_3D, m_level, (GLint)m_internal_format, m_width, m_height, m_depth, 0, (GLint)m_format, (GLint)m_type, m_pixels);
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_CUBE_MAP:
|
||||
{
|
||||
for (int face = 0; face < 6; ++face)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, m_level, (GLint)m_internal_format, m_width, m_height, 0, (GLint)m_format, (GLint)m_type, m_pixels);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_MAX_LEVEL, m_max_level);
|
||||
|
||||
if (m_pixels && m_generate_mipmap)
|
||||
{
|
||||
glGenerateMipmap((GLenum)m_parent->get_target());
|
||||
}
|
||||
|
||||
glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_WRAP_S, (GLint)m_wrap_s);
|
||||
glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_WRAP_T, (GLint)m_wrap_t);
|
||||
glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_WRAP_R, (GLint)m_wrap_r);
|
||||
|
||||
glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_COMPARE_MODE, (GLint)m_compare_mode);
|
||||
glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_COMPARE_FUNC, (GLint)m_compare_func);
|
||||
|
||||
glTexParameterf((GLenum)m_parent->get_target(), GL_TEXTURE_MIN_LOD, m_max_lod);
|
||||
glTexParameterf((GLenum)m_parent->get_target(), GL_TEXTURE_MAX_LOD, m_min_lod);
|
||||
glTexParameterf((GLenum)m_parent->get_target(), GL_TEXTURE_LOD_BIAS, m_lod);
|
||||
|
||||
glTexParameterfv((GLenum)m_parent->get_target(), GL_TEXTURE_BORDER_COLOR, m_border_color.rgba);
|
||||
|
||||
glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_MIN_FILTER, (GLint)m_min_filter);
|
||||
glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_MAG_FILTER, (GLint)m_mag_filter);
|
||||
|
||||
glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_SWIZZLE_R, (GLint)m_swizzle_r);
|
||||
glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_SWIZZLE_G, (GLint)m_swizzle_g);
|
||||
glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_SWIZZLE_B, (GLint)m_swizzle_b);
|
||||
glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_SWIZZLE_A, (GLint)m_swizzle_a);
|
||||
|
||||
glTexParameterf((GLenum)m_parent->get_target(), GL_TEXTURE_MAX_ANISOTROPY_EXT, m_aniso);
|
||||
}
|
||||
|
||||
void texture::settings::apply()
|
||||
{
|
||||
if (m_parent)
|
||||
{
|
||||
apply(*m_parent);
|
||||
m_parent = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::swizzle(texture::channel r, texture::channel g, texture::channel b, texture::channel a)
|
||||
{
|
||||
m_swizzle_r = r;
|
||||
m_swizzle_g = g;
|
||||
m_swizzle_b = b;
|
||||
m_swizzle_a = a;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::format(texture::format format)
|
||||
{
|
||||
m_format = format;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::type(texture::type type)
|
||||
{
|
||||
m_type = type;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::internal_format(texture::internal_format format)
|
||||
{
|
||||
m_internal_format = format;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::filter(min_filter min_filter, gl::filter mag_filter)
|
||||
{
|
||||
m_min_filter = min_filter;
|
||||
m_mag_filter = mag_filter;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::width(uint width)
|
||||
{
|
||||
m_width = width;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::height(uint height)
|
||||
{
|
||||
m_height = height;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::depth(uint depth)
|
||||
{
|
||||
m_depth = depth;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::size(sizei size)
|
||||
{
|
||||
return width(size.width).height(size.height);
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::level(int value)
|
||||
{
|
||||
m_level = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::compressed_image_size(int size)
|
||||
{
|
||||
m_compressed_image_size = size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::pixels(const void* pixels)
|
||||
{
|
||||
m_pixels = pixels;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::aniso(float value)
|
||||
{
|
||||
m_aniso = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::compare_mode(texture::compare_mode value)
|
||||
{
|
||||
m_compare_mode = value;
|
||||
return *this;
|
||||
}
|
||||
texture::settings& texture::settings::compare_func(texture::compare_func value)
|
||||
{
|
||||
m_compare_func = value;
|
||||
return *this;
|
||||
}
|
||||
texture::settings& texture::settings::compare(texture::compare_func func, texture::compare_mode mode)
|
||||
{
|
||||
return compare_func(func).compare_mode(mode);
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::wrap_s(texture::wrap value)
|
||||
{
|
||||
m_wrap_s = value;
|
||||
return *this;
|
||||
}
|
||||
texture::settings& texture::settings::wrap_t(texture::wrap value)
|
||||
{
|
||||
m_wrap_t = value;
|
||||
return *this;
|
||||
}
|
||||
texture::settings& texture::settings::wrap_r(texture::wrap value)
|
||||
{
|
||||
m_wrap_r = value;
|
||||
return *this;
|
||||
}
|
||||
texture::settings& texture::settings::wrap(texture::wrap s, texture::wrap t, texture::wrap r)
|
||||
{
|
||||
return wrap_s(s).wrap_t(t).wrap_r(r);
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::max_lod(float value)
|
||||
{
|
||||
m_max_lod = value;
|
||||
return *this;
|
||||
}
|
||||
texture::settings& texture::settings::min_lod(float value)
|
||||
{
|
||||
m_min_lod = value;
|
||||
return *this;
|
||||
}
|
||||
texture::settings& texture::settings::lod(float value)
|
||||
{
|
||||
m_lod = value;
|
||||
return *this;
|
||||
}
|
||||
texture::settings& texture::settings::max_level(int value)
|
||||
{
|
||||
m_max_level = value;
|
||||
return *this;
|
||||
}
|
||||
texture::settings& texture::settings::generate_mipmap(bool value)
|
||||
{
|
||||
m_generate_mipmap = value;
|
||||
return *this;
|
||||
}
|
||||
texture::settings& texture::settings::mipmap(int level, int max_level, float lod, float min_lod, float max_lod, bool generate)
|
||||
{
|
||||
return this->level(level).max_level(max_level).lod(lod).min_lod(min_lod).max_lod(max_lod).generate_mipmap(generate);
|
||||
}
|
||||
|
||||
texture::settings& texture::settings::border_color(color4f value)
|
||||
{
|
||||
m_border_color = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture_view texture::with_level(int level)
|
||||
{
|
||||
return{ get_target(), id() };
|
||||
}
|
||||
|
||||
texture::settings texture::config()
|
||||
{
|
||||
return{ this };
|
||||
}
|
||||
|
||||
void texture::config(const settings& settings_)
|
||||
{
|
||||
settings_.apply(*this);
|
||||
}
|
||||
|
||||
bool is_primitive_native(rsx::primitive_type in)
|
||||
{
|
||||
switch (in)
|
||||
|
@ -53,6 +53,13 @@ namespace gl
|
||||
#define __glcheck
|
||||
#endif
|
||||
|
||||
//Function call wrapped in ARB_DSA vs EXT_DSA compat check
|
||||
#define DSA_CALL(func, texture_name, target, ...)\
|
||||
if (::gl::get_driver_caps().ARB_dsa_supported)\
|
||||
gl##func(texture_name, __VA_ARGS__);\
|
||||
else\
|
||||
gl##func##EXT(texture_name, target, __VA_ARGS__);
|
||||
|
||||
class capabilities;
|
||||
class blitter;
|
||||
|
||||
@ -874,7 +881,7 @@ namespace gl
|
||||
buffer::create();
|
||||
|
||||
GLbitfield buffer_storage_flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
|
||||
if (get_driver_caps().vendor_MESA) buffer_storage_flags |= GL_CLIENT_STORAGE_BIT;
|
||||
if (gl::get_driver_caps().vendor_MESA) buffer_storage_flags |= GL_CLIENT_STORAGE_BIT;
|
||||
|
||||
glBindBuffer((GLenum)m_target, m_id);
|
||||
glBufferStorage((GLenum)m_target, size, data, buffer_storage_flags);
|
||||
@ -1306,14 +1313,8 @@ namespace gl
|
||||
}
|
||||
};
|
||||
|
||||
class texture_view;
|
||||
class texture
|
||||
{
|
||||
GLuint m_id = 0;
|
||||
GLuint m_level = 0;
|
||||
class pixel_pack_settings m_pixel_pack_settings;
|
||||
class pixel_unpack_settings m_pixel_unpack_settings;
|
||||
|
||||
public:
|
||||
enum class type
|
||||
{
|
||||
@ -1462,54 +1463,121 @@ namespace gl
|
||||
depth = GL_TEXTURE_DEPTH_TYPE
|
||||
};
|
||||
|
||||
class save_binding_state
|
||||
{
|
||||
GLint m_last_binding;
|
||||
GLenum m_target;
|
||||
private:
|
||||
GLuint m_id = 0;
|
||||
GLuint m_width = 0;
|
||||
GLuint m_height = 0;
|
||||
GLuint m_depth = 0;
|
||||
GLuint m_mipmaps = 0;
|
||||
|
||||
public:
|
||||
save_binding_state(const texture& new_binding) noexcept
|
||||
{
|
||||
GLenum pname;
|
||||
switch (new_binding.get_target())
|
||||
{
|
||||
case target::texture1D: pname = GL_TEXTURE_BINDING_1D; break;
|
||||
case target::texture2D: pname = GL_TEXTURE_BINDING_2D; break;
|
||||
case target::texture3D: pname = GL_TEXTURE_BINDING_3D; break;
|
||||
case target::textureCUBE: pname = GL_TEXTURE_BINDING_CUBE_MAP; break;
|
||||
case target::textureBuffer: pname = GL_TEXTURE_BINDING_BUFFER; break;
|
||||
default:
|
||||
fmt::throw_exception("Unknown target 0x%X" HERE, (u32)new_binding.get_target());
|
||||
}
|
||||
|
||||
glGetIntegerv(pname, &m_last_binding);
|
||||
|
||||
new_binding.bind();
|
||||
m_target = (GLenum)new_binding.get_target();
|
||||
}
|
||||
|
||||
~save_binding_state() noexcept
|
||||
{
|
||||
glBindTexture(m_target, m_last_binding);
|
||||
}
|
||||
};
|
||||
|
||||
class settings;
|
||||
target m_target = target::texture2D;
|
||||
internal_format m_internal_format = internal_format::rgba8;
|
||||
std::array<GLenum, 4> m_component_layout;
|
||||
|
||||
private:
|
||||
target m_target = target::texture2D;
|
||||
class save_binding_state
|
||||
{
|
||||
GLenum target = GL_NONE;
|
||||
GLuint old_binding = GL_NONE;
|
||||
|
||||
public:
|
||||
save_binding_state(GLenum target)
|
||||
{
|
||||
this->target = target;
|
||||
switch (target)
|
||||
{
|
||||
case GL_TEXTURE_1D:
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_1D, (GLint*)&old_binding);
|
||||
break;
|
||||
case GL_TEXTURE_2D:
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&old_binding);
|
||||
break;
|
||||
case GL_TEXTURE_3D:
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_3D, (GLint*)&old_binding);
|
||||
break;
|
||||
case GL_TEXTURE_CUBE_MAP:
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, (GLint*)&old_binding);
|
||||
break;
|
||||
case GL_TEXTURE_BUFFER:
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_BUFFER, (GLint*)&old_binding);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
~save_binding_state()
|
||||
{
|
||||
glBindTexture(target, old_binding);
|
||||
}
|
||||
};
|
||||
public:
|
||||
texture(const texture&) = delete;
|
||||
texture(texture&& texture_) = delete;
|
||||
|
||||
texture(GLenum target, GLuint width, GLuint height, GLuint depth, GLuint mipmaps, GLenum sized_format)
|
||||
{
|
||||
save_binding_state save(target);
|
||||
glGenTextures(1, &m_id);
|
||||
glBindTexture(target, m_id); //Must bind to initialize the new texture
|
||||
|
||||
switch (target)
|
||||
{
|
||||
default:
|
||||
fmt::throw_exception("Invalid image target 0x%X" HERE, target);
|
||||
case GL_TEXTURE_1D:
|
||||
glTexStorage1D(target, mipmaps, sized_format, width);
|
||||
height = depth = 1;
|
||||
break;
|
||||
case GL_TEXTURE_2D:
|
||||
case GL_TEXTURE_CUBE_MAP:
|
||||
glTexStorage2D(target, mipmaps, sized_format, width, height);
|
||||
depth = 1;
|
||||
break;
|
||||
case GL_TEXTURE_3D:
|
||||
glTexStorage3D(target, mipmaps, sized_format, width, height, depth);
|
||||
break;
|
||||
case GL_TEXTURE_BUFFER:
|
||||
break;
|
||||
}
|
||||
|
||||
if (target != GL_TEXTURE_BUFFER)
|
||||
{
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
||||
glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);
|
||||
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_depth = depth;
|
||||
m_mipmaps = mipmaps;
|
||||
}
|
||||
|
||||
m_target = static_cast<texture::target>(target);
|
||||
m_internal_format = static_cast<internal_format>(sized_format);
|
||||
m_component_layout = { GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE };
|
||||
}
|
||||
|
||||
~texture()
|
||||
{
|
||||
glDeleteTextures(1, &m_id);
|
||||
}
|
||||
|
||||
void set_native_component_layout(const std::array<GLenum, 4>& layout)
|
||||
{
|
||||
m_component_layout[0] = layout[0];
|
||||
m_component_layout[1] = layout[1];
|
||||
m_component_layout[2] = layout[2];
|
||||
m_component_layout[3] = layout[3];
|
||||
}
|
||||
|
||||
target get_target() const noexcept
|
||||
{
|
||||
return m_target;
|
||||
}
|
||||
|
||||
void set_target(target target) noexcept
|
||||
{
|
||||
m_target = target;
|
||||
}
|
||||
|
||||
static bool compressed_format(internal_format format_) noexcept
|
||||
{
|
||||
switch (format_)
|
||||
@ -1529,225 +1597,86 @@ namespace gl
|
||||
return m_id;
|
||||
}
|
||||
|
||||
uint level() const noexcept
|
||||
{
|
||||
return m_level;
|
||||
}
|
||||
|
||||
void recreate() noexcept
|
||||
{
|
||||
if (created())
|
||||
remove();
|
||||
|
||||
create();
|
||||
}
|
||||
|
||||
void recreate(target target_) noexcept
|
||||
{
|
||||
if (created())
|
||||
remove();
|
||||
|
||||
create(target_);
|
||||
}
|
||||
|
||||
void create() noexcept
|
||||
{
|
||||
glGenTextures(1, &m_id);
|
||||
}
|
||||
|
||||
void create(target target_) noexcept
|
||||
{
|
||||
set_target(target_);
|
||||
create();
|
||||
}
|
||||
|
||||
bool created() const noexcept
|
||||
{
|
||||
return m_id != 0;
|
||||
}
|
||||
|
||||
void remove() noexcept
|
||||
{
|
||||
glDeleteTextures(1, &m_id);
|
||||
m_id = 0;
|
||||
}
|
||||
|
||||
void set_id(GLuint id) noexcept
|
||||
{
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
void set_level(int level) noexcept
|
||||
{
|
||||
m_level = level;
|
||||
}
|
||||
|
||||
texture_view with_level(int level);
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return created();
|
||||
return (m_id != 0);
|
||||
}
|
||||
|
||||
void bind() const noexcept
|
||||
GLuint width() const
|
||||
{
|
||||
glBindTexture((GLenum)get_target(), id());
|
||||
return m_width;
|
||||
}
|
||||
|
||||
settings config();
|
||||
|
||||
void config(const settings& settings_);
|
||||
|
||||
class pixel_pack_settings& pixel_pack_settings()
|
||||
GLuint height() const
|
||||
{
|
||||
return m_pixel_pack_settings;
|
||||
return m_height;
|
||||
}
|
||||
|
||||
const class pixel_pack_settings& pixel_pack_settings() const
|
||||
GLuint depth() const
|
||||
{
|
||||
return m_pixel_pack_settings;
|
||||
return m_depth;
|
||||
}
|
||||
|
||||
class pixel_unpack_settings& pixel_unpack_settings()
|
||||
GLuint levels() const
|
||||
{
|
||||
return m_pixel_unpack_settings;
|
||||
return m_mipmaps;
|
||||
}
|
||||
|
||||
const class pixel_unpack_settings& pixel_unpack_settings() const
|
||||
sizei size2D() const
|
||||
{
|
||||
return m_pixel_unpack_settings;
|
||||
return{ (int)m_width, (int)m_height };
|
||||
}
|
||||
|
||||
int width() const
|
||||
texture::internal_format get_internal_format() const
|
||||
{
|
||||
save_binding_state save(*this);
|
||||
GLint result;
|
||||
glGetTexLevelParameteriv((GLenum)get_target(), level(), GL_TEXTURE_WIDTH, &result);
|
||||
return (int)result;
|
||||
return m_internal_format;
|
||||
}
|
||||
|
||||
int height() const
|
||||
std::array<GLenum, 4> get_native_component_layout() const
|
||||
{
|
||||
save_binding_state save(*this);
|
||||
GLint result;
|
||||
glGetTexLevelParameteriv((GLenum)get_target(), level(), GL_TEXTURE_HEIGHT, &result);
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
int depth() const
|
||||
{
|
||||
save_binding_state save(*this);
|
||||
GLint result;
|
||||
glGetTexLevelParameteriv((GLenum)get_target(), level(), GL_TEXTURE_DEPTH, &result);
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
sizei size() const
|
||||
{
|
||||
return{ width(), height() };
|
||||
}
|
||||
|
||||
size3i size3d() const
|
||||
{
|
||||
return{ width(), height(), depth() };
|
||||
}
|
||||
|
||||
texture::format get_internal_format() const
|
||||
{
|
||||
save_binding_state save(*this);
|
||||
GLint result;
|
||||
glGetTexLevelParameteriv((GLenum)get_target(), level(), GL_TEXTURE_INTERNAL_FORMAT, &result);
|
||||
return (texture::format)result;
|
||||
}
|
||||
|
||||
virtual texture::internal_format get_compatible_internal_format() const
|
||||
{
|
||||
return (texture::internal_format)get_internal_format();
|
||||
}
|
||||
|
||||
texture::channel_type get_channel_type(texture::channel_name channel) const
|
||||
{
|
||||
save_binding_state save(*this);
|
||||
GLint result;
|
||||
glGetTexLevelParameteriv((GLenum)get_target(), level(), (GLenum)channel, &result);
|
||||
return (texture::channel_type)result;
|
||||
}
|
||||
|
||||
int get_channel_count() const
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (get_channel_type(channel_name::red) != channel_type::none)
|
||||
result++;
|
||||
if (get_channel_type(channel_name::green) != channel_type::none)
|
||||
result++;
|
||||
if (get_channel_type(channel_name::blue) != channel_type::none)
|
||||
result++;
|
||||
if (get_channel_type(channel_name::alpha) != channel_type::none)
|
||||
result++;
|
||||
if (get_channel_type(channel_name::depth) != channel_type::none)
|
||||
result++;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool compressed() const
|
||||
{
|
||||
save_binding_state save(*this);
|
||||
GLint result;
|
||||
glGetTexLevelParameteriv((GLenum)get_target(), level(), GL_TEXTURE_COMPRESSED, &result);
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
int compressed_size() const
|
||||
{
|
||||
save_binding_state save(*this);
|
||||
GLint result;
|
||||
glGetTexLevelParameteriv((GLenum)get_target(), level(), GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &result);
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
texture() = default;
|
||||
texture(texture&) = delete;
|
||||
|
||||
texture(texture&& texture_)
|
||||
{
|
||||
swap(texture_);
|
||||
}
|
||||
texture(target target_, GLuint id = 0)
|
||||
{
|
||||
m_target = target_;
|
||||
set_id(id);
|
||||
}
|
||||
|
||||
~texture()
|
||||
{
|
||||
if (created())
|
||||
remove();
|
||||
}
|
||||
|
||||
void swap(texture& texture_)
|
||||
{
|
||||
auto my_old_id = id();
|
||||
auto my_old_target = get_target();
|
||||
set_id(texture_.id());
|
||||
set_target(texture_.get_target());
|
||||
texture_.set_id(my_old_id);
|
||||
texture_.set_target(my_old_target);
|
||||
}
|
||||
|
||||
texture& operator = (const texture& rhs) = delete;
|
||||
texture& operator = (texture&& rhs)
|
||||
{
|
||||
swap(rhs);
|
||||
return *this;
|
||||
return m_component_layout;
|
||||
}
|
||||
|
||||
void copy_from(const void* src, texture::format format, texture::type type, class pixel_unpack_settings pixel_settings)
|
||||
{
|
||||
save_binding_state save(*this);
|
||||
pixel_settings.apply();
|
||||
__glcheck glTexSubImage2D((GLenum)get_target(), level(), 0, 0, width(), height(), (GLenum)format, (GLenum)type, src);
|
||||
|
||||
switch ((GLenum)m_target)
|
||||
{
|
||||
case GL_TEXTURE_1D:
|
||||
{
|
||||
DSA_CALL(TextureSubImage1D, m_id, GL_TEXTURE_1D, 0, 0, m_width, (GLenum)format, (GLenum)type, src);
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_2D:
|
||||
{
|
||||
DSA_CALL(TextureSubImage2D, m_id, GL_TEXTURE_2D, 0, 0, 0, m_width, m_height, (GLenum)format, (GLenum)type, src);
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_3D:
|
||||
{
|
||||
DSA_CALL(TextureSubImage3D, m_id, GL_TEXTURE_3D, 0, 0, 0, 0, m_width, m_height, m_depth, (GLenum)format, (GLenum)type, src);
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_CUBE_MAP:
|
||||
{
|
||||
if (::gl::get_driver_caps().ARB_dsa_supported)
|
||||
{
|
||||
glTextureSubImage3D(m_id, 0, 0, 0, 0, m_width, m_height, 6, (GLenum)format, (GLenum)type, src);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING(RSX, "Cubemap upload via texture::copy_from is halfplemented!");
|
||||
u8* ptr = (u8*)src;
|
||||
for (int face = 0; face < 6; ++face)
|
||||
{
|
||||
glTextureSubImage2DEXT(m_id, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, 0, 0, m_width, m_height, (GLenum)format, (GLenum)type, ptr);
|
||||
ptr += (m_width * m_height * 4); //TODO
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void copy_from(buffer &buf, u32 gl_format_type, u32 offset, u32 length)
|
||||
@ -1755,12 +1684,7 @@ namespace gl
|
||||
if (get_target() != target::textureBuffer)
|
||||
fmt::throw_exception("OpenGL error: texture cannot copy from buffer" HERE);
|
||||
|
||||
auto caps = get_driver_caps();
|
||||
|
||||
if (caps.EXT_dsa_supported)
|
||||
__glcheck glTextureBufferRangeEXT(id(), (GLenum)target::textureBuffer, gl_format_type, buf.id(), offset, length);
|
||||
else
|
||||
__glcheck glTextureBufferRange(id(), gl_format_type, buf.id(), offset, length);
|
||||
DSA_CALL(TextureBufferRange, m_id, GL_TEXTURE_BUFFER, gl_format_type, buf.id(), offset, length);
|
||||
}
|
||||
|
||||
void copy_from(buffer_view &view)
|
||||
@ -1786,14 +1710,11 @@ namespace gl
|
||||
|
||||
void copy_to(void* dst, texture::format format, texture::type type, class pixel_pack_settings pixel_settings) const
|
||||
{
|
||||
save_binding_state save(*this);
|
||||
pixel_settings.apply();
|
||||
__glcheck glGetTexImage((GLenum)get_target(), level(), (GLenum)format, (GLenum)type, dst);
|
||||
}
|
||||
|
||||
void copy_to(void* dst, texture::type type, class pixel_pack_settings pixel_settings) const
|
||||
{
|
||||
copy_to(dst, get_internal_format(), type, pixel_settings);
|
||||
if (gl::get_driver_caps().ARB_dsa_supported)
|
||||
glGetTextureImage(m_id, 0, (GLenum)format, (GLenum)type, m_width * m_height * 16, dst);
|
||||
else
|
||||
glGetTextureImageEXT(m_id, (GLenum)m_target, 0, (GLenum)format, (GLenum)type, dst);
|
||||
}
|
||||
|
||||
void copy_to(const buffer& buf, texture::format format, texture::type type, class pixel_pack_settings pixel_settings) const
|
||||
@ -1802,30 +1723,114 @@ namespace gl
|
||||
copy_to(nullptr, format, type, pixel_settings);
|
||||
}
|
||||
|
||||
void copy_to(const buffer& buf, texture::type type, class pixel_pack_settings pixel_settings) const
|
||||
{
|
||||
buffer::save_binding_state save_buffer(buffer::target::pixel_pack, buf);
|
||||
copy_to(nullptr, get_internal_format(), type, pixel_settings);
|
||||
}
|
||||
|
||||
void copy_to(void* dst, texture::format format, texture::type type) const
|
||||
{
|
||||
copy_to(dst, format, type, pixel_pack_settings());
|
||||
}
|
||||
|
||||
void copy_to(void* dst, texture::type type) const
|
||||
{
|
||||
copy_to(dst, get_internal_format(), type, pixel_pack_settings());
|
||||
}
|
||||
|
||||
void copy_to(const buffer& buf, texture::format format, texture::type type) const
|
||||
{
|
||||
copy_to(buf, format, type, pixel_pack_settings());
|
||||
}
|
||||
};
|
||||
|
||||
void copy_to(const buffer& buf, texture::type type) const
|
||||
class texture_view
|
||||
{
|
||||
GLuint m_id = 0;
|
||||
GLenum m_target = 0;
|
||||
GLenum m_format = 0;
|
||||
texture *m_image_data = nullptr;
|
||||
|
||||
GLenum component_swizzle[4];
|
||||
|
||||
void create(texture* data, GLenum target, GLenum sized_format, const GLenum* argb_swizzle = nullptr)
|
||||
{
|
||||
copy_to(buf, get_internal_format(), type, pixel_pack_settings());
|
||||
m_target = target;
|
||||
m_format = sized_format;
|
||||
m_image_data = data;
|
||||
|
||||
const auto num_levels = data->levels();
|
||||
const auto num_layers = (target != GL_TEXTURE_CUBE_MAP) ? 1 : 6;
|
||||
|
||||
glGenTextures(1, &m_id);
|
||||
glTextureView(m_id, target, data->id(), sized_format, 0, num_levels, 0, num_layers);
|
||||
|
||||
if (argb_swizzle)
|
||||
{
|
||||
component_swizzle[0] = argb_swizzle[1];
|
||||
component_swizzle[1] = argb_swizzle[2];
|
||||
component_swizzle[2] = argb_swizzle[3];
|
||||
component_swizzle[3] = argb_swizzle[0];
|
||||
|
||||
glBindTexture(m_target, m_id);
|
||||
glTexParameteriv(m_target, GL_TEXTURE_SWIZZLE_RGBA, (GLint*)component_swizzle);
|
||||
}
|
||||
else
|
||||
{
|
||||
component_swizzle[0] = GL_RED;
|
||||
component_swizzle[1] = GL_GREEN;
|
||||
component_swizzle[2] = GL_BLUE;
|
||||
component_swizzle[3] = GL_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
texture_view(const texture_view&) = delete;
|
||||
texture_view(texture_view&&) = delete;
|
||||
|
||||
texture_view(texture* data, GLenum target, GLenum sized_format, const GLenum* argb_swizzle = nullptr)
|
||||
{
|
||||
create(data, target, sized_format, argb_swizzle);
|
||||
}
|
||||
|
||||
texture_view(texture* data, const GLenum* argb_swizzle = nullptr)
|
||||
{
|
||||
GLenum target = (GLenum)data->get_target();
|
||||
GLenum sized_format = (GLenum)data->get_internal_format();
|
||||
create(data, target, sized_format, argb_swizzle);
|
||||
}
|
||||
|
||||
~texture_view()
|
||||
{
|
||||
glDeleteTextures(1, &m_id);
|
||||
}
|
||||
|
||||
GLuint id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
GLenum target() const
|
||||
{
|
||||
return m_target;
|
||||
}
|
||||
|
||||
GLenum internal_format() const
|
||||
{
|
||||
return m_format;
|
||||
}
|
||||
|
||||
bool compare_swizzle(GLenum* argb_swizzle) const
|
||||
{
|
||||
return (argb_swizzle[0] == component_swizzle[3] &&
|
||||
argb_swizzle[1] == component_swizzle[0] &&
|
||||
argb_swizzle[2] == component_swizzle[1] &&
|
||||
argb_swizzle[3] == component_swizzle[2]);
|
||||
}
|
||||
|
||||
void bind() const
|
||||
{
|
||||
glBindTexture(m_target, m_id);
|
||||
}
|
||||
|
||||
texture* image() const
|
||||
{
|
||||
return m_image_data;
|
||||
}
|
||||
|
||||
std::array<GLenum, 4> component_mapping() const
|
||||
{
|
||||
return{ component_swizzle[3], component_swizzle[0], component_swizzle[1], component_swizzle[2] };
|
||||
}
|
||||
};
|
||||
|
||||
@ -1929,96 +1934,6 @@ namespace gl
|
||||
}
|
||||
};
|
||||
|
||||
class texture::settings
|
||||
{
|
||||
texture *m_parent;
|
||||
|
||||
texture::channel m_swizzle_r = texture::channel::r;
|
||||
texture::channel m_swizzle_g = texture::channel::g;
|
||||
texture::channel m_swizzle_b = texture::channel::b;
|
||||
texture::channel m_swizzle_a = texture::channel::a;
|
||||
|
||||
texture::format m_format = texture::format::rgba;
|
||||
texture::internal_format m_internal_format = texture::internal_format::rgba;
|
||||
texture::type m_type = texture::type::ubyte;
|
||||
|
||||
gl::min_filter m_min_filter = gl::min_filter::nearest;
|
||||
gl::filter m_mag_filter = gl::filter::nearest;
|
||||
|
||||
uint m_width = 0;
|
||||
uint m_height = 0;
|
||||
uint m_depth = 1;
|
||||
int m_level = 0;
|
||||
|
||||
int m_compressed_image_size = 0;
|
||||
|
||||
const void* m_pixels = nullptr;
|
||||
float m_aniso = 1.f;
|
||||
texture::compare_mode m_compare_mode = texture::compare_mode::none;
|
||||
texture::compare_func m_compare_func = texture::compare_func::greater;
|
||||
|
||||
texture::wrap m_wrap_s = texture::wrap::repeat;
|
||||
texture::wrap m_wrap_t = texture::wrap::repeat;
|
||||
texture::wrap m_wrap_r = texture::wrap::repeat;
|
||||
|
||||
float m_max_lod = 1000.f;
|
||||
float m_min_lod = -1000.f;
|
||||
float m_lod = 0.f;
|
||||
int m_max_level = 1000;
|
||||
bool m_generate_mipmap = false;
|
||||
|
||||
color4f m_border_color;
|
||||
|
||||
public:
|
||||
settings(texture *parent = nullptr) : m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
~settings()
|
||||
{
|
||||
apply();
|
||||
}
|
||||
|
||||
void apply(const texture &texture) const;
|
||||
void apply();
|
||||
|
||||
settings& swizzle(
|
||||
texture::channel r = texture::channel::r,
|
||||
texture::channel g = texture::channel::g,
|
||||
texture::channel b = texture::channel::b,
|
||||
texture::channel a = texture::channel::a);
|
||||
|
||||
settings& format(texture::format format);
|
||||
settings& type(texture::type type);
|
||||
settings& internal_format(texture::internal_format format);
|
||||
settings& filter(min_filter min_filter, filter mag_filter);
|
||||
settings& width(uint width);
|
||||
settings& height(uint height);
|
||||
settings& depth(uint depth);
|
||||
settings& size(sizei size);
|
||||
settings& level(int value);
|
||||
settings& compressed_image_size(int size);
|
||||
settings& pixels(const void* pixels);
|
||||
settings& aniso(float value);
|
||||
settings& compare_mode(texture::compare_mode value);
|
||||
settings& compare_func(texture::compare_func value);
|
||||
settings& compare(texture::compare_func func, texture::compare_mode mode);
|
||||
|
||||
settings& wrap_s(texture::wrap value);
|
||||
settings& wrap_t(texture::wrap value);
|
||||
settings& wrap_r(texture::wrap value);
|
||||
settings& wrap(texture::wrap s, texture::wrap t, texture::wrap r);
|
||||
|
||||
settings& max_lod(float value);
|
||||
settings& min_lod(float value);
|
||||
settings& lod(float value);
|
||||
settings& max_level(int value);
|
||||
settings& generate_mipmap(bool value);
|
||||
settings& mipmap(int level, int max_level, float lod, float min_lod, float max_lod, bool generate);
|
||||
|
||||
settings& border_color(color4f value);
|
||||
};
|
||||
|
||||
enum class indices_type
|
||||
{
|
||||
ubyte = GL_UNSIGNED_BYTE,
|
||||
@ -2110,14 +2025,8 @@ namespace gl
|
||||
{
|
||||
save_binding_state save(m_parent);
|
||||
|
||||
switch (rhs.get_target())
|
||||
{
|
||||
case texture::target::texture1D: glFramebufferTexture1D(GL_FRAMEBUFFER, m_id, GL_TEXTURE_1D, rhs.id(), rhs.level()); break;
|
||||
case texture::target::texture2D: glFramebufferTexture2D(GL_FRAMEBUFFER, m_id, GL_TEXTURE_2D, rhs.id(), rhs.level()); break;
|
||||
case texture::target::texture3D: glFramebufferTexture3D(GL_FRAMEBUFFER, m_id, GL_TEXTURE_3D, rhs.id(), rhs.level(), 0); break;
|
||||
case texture::target::textureBuffer:
|
||||
fmt::throw_exception("Tried to assign unsupported texture of type textureBuffer to fbo." HERE);
|
||||
}
|
||||
verify(HERE), rhs.get_target() == texture::target::texture2D;
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, m_id, GL_TEXTURE_2D, rhs.id(), 0);
|
||||
}
|
||||
|
||||
void operator = (const GLuint rhs)
|
||||
@ -2479,7 +2388,7 @@ namespace gl
|
||||
return result;
|
||||
}
|
||||
|
||||
int texture(GLint location, int active_texture, const gl::texture& texture)
|
||||
int texture(GLint location, int active_texture, const gl::texture_view& texture)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + active_texture);
|
||||
texture.bind();
|
||||
@ -2488,12 +2397,12 @@ namespace gl
|
||||
return active_texture;
|
||||
}
|
||||
|
||||
int texture(const std::string &name, int active_texture, const gl::texture& texture_)
|
||||
int texture(const std::string &name, int active_texture, const gl::texture_view& texture_)
|
||||
{
|
||||
return texture(location(name), active_texture, texture_);
|
||||
}
|
||||
|
||||
int texture(const std::string &name, const gl::texture& texture_)
|
||||
int texture(const std::string &name, const gl::texture_view& texture_)
|
||||
{
|
||||
int atex;
|
||||
auto finded = locations.find(name);
|
||||
@ -2813,43 +2722,4 @@ namespace gl
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class texture_view : public texture
|
||||
{
|
||||
public:
|
||||
texture_view(texture::target target_, GLuint id) : texture(target_, id)
|
||||
{
|
||||
}
|
||||
|
||||
~texture_view()
|
||||
{
|
||||
set_id(0);
|
||||
}
|
||||
};
|
||||
|
||||
class fbo_view : public fbo
|
||||
{
|
||||
public:
|
||||
fbo_view(GLuint id) : fbo(id)
|
||||
{
|
||||
}
|
||||
|
||||
~fbo_view()
|
||||
{
|
||||
set_id(0);
|
||||
}
|
||||
};
|
||||
|
||||
class rbo_view : public rbo
|
||||
{
|
||||
public:
|
||||
rbo_view(GLuint id) : rbo(id)
|
||||
{
|
||||
}
|
||||
|
||||
~rbo_view()
|
||||
{
|
||||
set_id(0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -328,7 +328,9 @@ namespace gl
|
||||
u32 num_elements = 0;
|
||||
std::vector<std::unique_ptr<gl::texture>> resources;
|
||||
std::unordered_map<u64, std::unique_ptr<gl::texture>> temp_image_cache;
|
||||
std::unordered_map<u64, std::unique_ptr<gl::texture_view>> temp_view_cache;
|
||||
std::unordered_map<u64, std::unique_ptr<gl::texture>> font_cache;
|
||||
std::unordered_map<u64, std::unique_ptr<gl::texture_view>> view_cache;
|
||||
bool is_font_draw = false;
|
||||
|
||||
ui_overlay_renderer()
|
||||
@ -390,31 +392,28 @@ namespace gl
|
||||
};
|
||||
}
|
||||
|
||||
gl::texture* load_simple_image(rsx::overlays::image_info* desc, bool temp_resource)
|
||||
gl::texture_view* load_simple_image(rsx::overlays::image_info* desc, bool temp_resource)
|
||||
{
|
||||
auto tex = std::make_unique<gl::texture>(gl::texture::target::texture2D);
|
||||
tex->create();
|
||||
tex->config()
|
||||
.size({ desc->w, desc->h })
|
||||
.format(gl::texture::format::rgba)
|
||||
.type(gl::texture::type::uint_8_8_8_8)
|
||||
.wrap(gl::texture::wrap::clamp_to_border, gl::texture::wrap::clamp_to_border, gl::texture::wrap::clamp_to_border)
|
||||
.swizzle(gl::texture::channel::a, gl::texture::channel::b, gl::texture::channel::g, gl::texture::channel::r)
|
||||
.filter(gl::min_filter::linear, gl::filter::linear)
|
||||
.apply();
|
||||
auto tex = std::make_unique<gl::texture>(GL_TEXTURE_2D, desc->w, desc->h, 1, 1, GL_RGBA8);
|
||||
tex->copy_from(desc->data, gl::texture::format::rgba, gl::texture::type::uint_8_8_8_8);
|
||||
|
||||
GLenum remap[] = { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA };
|
||||
auto view = std::make_unique<gl::texture_view>(tex.get(), remap);
|
||||
|
||||
auto result = view.get();
|
||||
if (!temp_resource)
|
||||
{
|
||||
resources.push_back(std::move(tex));
|
||||
view_cache[view_cache.size()] = std::move(view);
|
||||
}
|
||||
else
|
||||
{
|
||||
u64 key = (u64)desc;
|
||||
temp_image_cache[key] = std::move(tex);
|
||||
temp_view_cache[key] = std::move(view);
|
||||
}
|
||||
|
||||
return resources.back().get();
|
||||
return result;
|
||||
}
|
||||
|
||||
void create()
|
||||
@ -445,38 +444,32 @@ namespace gl
|
||||
temp_image_cache.clear();
|
||||
}
|
||||
|
||||
gl::texture* find_font(rsx::overlays::font *font)
|
||||
gl::texture_view* find_font(rsx::overlays::font *font)
|
||||
{
|
||||
u64 key = (u64)font;
|
||||
auto found = font_cache.find(key);
|
||||
if (found != font_cache.end())
|
||||
auto found = view_cache.find(key);
|
||||
if (found != view_cache.end())
|
||||
return found->second.get();
|
||||
|
||||
//Create font file
|
||||
auto tex = std::make_unique<gl::texture>(gl::texture::target::texture2D);
|
||||
tex->create();
|
||||
tex->config()
|
||||
.size({ (int)font->width, (int)font->height })
|
||||
.format(gl::texture::format::r)
|
||||
.type(gl::texture::type::ubyte)
|
||||
.internal_format(gl::texture::internal_format::r8)
|
||||
.wrap(gl::texture::wrap::clamp_to_border, gl::texture::wrap::clamp_to_border, gl::texture::wrap::clamp_to_border)
|
||||
.swizzle(gl::texture::channel::r, gl::texture::channel::r, gl::texture::channel::r, gl::texture::channel::r)
|
||||
.filter(gl::min_filter::linear, gl::filter::linear)
|
||||
.apply();
|
||||
auto tex = std::make_unique<gl::texture>(GL_TEXTURE_2D, (int)font->width, (int)font->height, 1, 1, GL_R8);
|
||||
tex->copy_from(font->glyph_data.data(), gl::texture::format::r, gl::texture::type::ubyte);
|
||||
|
||||
auto result = tex.get();
|
||||
GLenum remap[] = { GL_RED, GL_RED, GL_RED, GL_RED };
|
||||
auto view = std::make_unique<gl::texture_view>(tex.get(), remap);
|
||||
|
||||
auto result = view.get();
|
||||
font_cache[key] = std::move(tex);
|
||||
view_cache[key] = std::move(view);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
gl::texture* find_temp_image(rsx::overlays::image_info *desc)
|
||||
gl::texture_view* find_temp_image(rsx::overlays::image_info *desc)
|
||||
{
|
||||
auto key = (u64)desc;
|
||||
auto cached = temp_image_cache.find(key);
|
||||
if (cached != temp_image_cache.end())
|
||||
auto cached = temp_view_cache.find(key);
|
||||
if (cached != temp_view_cache.end())
|
||||
{
|
||||
return cached->second.get();
|
||||
}
|
||||
@ -553,7 +546,7 @@ namespace gl
|
||||
}
|
||||
default:
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, resources[cmd.first.texture_ref - 1]->id());
|
||||
glBindTexture(GL_TEXTURE_2D, view_cache[cmd.first.texture_ref - 1]->id());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ OPENGL_PROC(PFNGLBINDVERTEXARRAYPROC, BindVertexArray);
|
||||
OPENGL_PROC(PFNGLDELETEVERTEXARRAYSPROC, DeleteVertexArrays);
|
||||
OPENGL_PROC(PFNGLDEPTHRANGEFPROC, DepthRangef);
|
||||
OPENGL_PROC(PFNGLTEXIMAGE3DPROC, TexImage3D);
|
||||
OPENGL_PROC(PFNGLTEXSUBIMAGE3DPROC, TexSubImage3D);
|
||||
|
||||
OPENGL_PROC(PFNGLVERTEXATTRIB1FPROC, VertexAttrib1f);
|
||||
OPENGL_PROC(PFNGLVERTEXATTRIB1DPROC, VertexAttrib1d);
|
||||
@ -175,6 +176,12 @@ OPENGL_PROC(PFNGLMULTIDRAWARRAYSPROC, MultiDrawArrays);
|
||||
|
||||
OPENGL_PROC(PFNGLGETTEXTUREIMAGEEXTPROC, GetTextureImageEXT);
|
||||
OPENGL_PROC(PFNGLGETTEXTUREIMAGEPROC, GetTextureImage);
|
||||
OPENGL_PROC(PFNGLTEXTURESUBIMAGE1DEXTPROC, TextureSubImage1DEXT);
|
||||
OPENGL_PROC(PFNGLTEXTURESUBIMAGE1DPROC, TextureSubImage1D);
|
||||
OPENGL_PROC(PFNGLTEXTURESUBIMAGE2DEXTPROC, TextureSubImage2DEXT);
|
||||
OPENGL_PROC(PFNGLTEXTURESUBIMAGE2DPROC, TextureSubImage2D);
|
||||
OPENGL_PROC(PFNGLTEXTURESUBIMAGE3DEXTPROC, TextureSubImage3DEXT);
|
||||
OPENGL_PROC(PFNGLTEXTURESUBIMAGE3DPROC, TextureSubImage3D);
|
||||
|
||||
OPENGL_PROC(PFNGLCLEARBUFFERFVPROC, ClearBufferfv);
|
||||
|
||||
@ -212,10 +219,13 @@ OPENGL_PROC(PFNGLDELETESYNCPROC, DeleteSync);
|
||||
//KHR_debug
|
||||
OPENGL_PROC(PFNGLDEBUGMESSAGECALLBACKPROC, DebugMessageCallback);
|
||||
|
||||
//Immutable textures
|
||||
OPENGL_PROC(PFNGLTEXSTORAGE1DPROC, TexStorage1D);
|
||||
OPENGL_PROC(PFNGLTEXSTORAGE2DPROC, TexStorage2D);
|
||||
OPENGL_PROC(PFNGLTEXSTORAGE3DPROC, TexStorage3D);
|
||||
OPENGL_PROC(PFNGLTEXSUBIMAGE3DPROC, TexSubImage3D);
|
||||
|
||||
//Texture_View
|
||||
OPENGL_PROC(PFNGLTEXTUREVIEWPROC, TextureView);
|
||||
|
||||
//Texture_Barrier
|
||||
OPENGL_PROC(PFNGLTEXTUREBARRIERPROC, TextureBarrier);
|
||||
|
@ -49,7 +49,7 @@ namespace rsx
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class render_target : public texture, public rsx::ref_counted, public rsx::render_target_descriptor<u32>
|
||||
class render_target : public texture, public rsx::ref_counted, public rsx::render_target_descriptor<texture*>
|
||||
{
|
||||
bool is_cleared = false;
|
||||
|
||||
@ -62,14 +62,14 @@ namespace gl
|
||||
u16 surface_width = 0;
|
||||
u16 surface_pixel_size = 0;
|
||||
|
||||
texture::internal_format compatible_internal_format = texture::internal_format::rgba8;
|
||||
std::array<GLenum, 4> native_component_mapping;
|
||||
u32 current_remap_encoding = 0;
|
||||
std::unordered_map<u32, std::unique_ptr<texture_view>> views;
|
||||
|
||||
public:
|
||||
render_target *old_contents = nullptr;
|
||||
|
||||
render_target() {}
|
||||
render_target(GLuint width, GLuint height, GLenum sized_format)
|
||||
:texture(GL_TEXTURE_2D, width, height, 1, 1, sized_format)
|
||||
{}
|
||||
|
||||
void set_cleared(bool clear=true)
|
||||
{
|
||||
@ -113,59 +113,37 @@ namespace gl
|
||||
return surface_height;
|
||||
}
|
||||
|
||||
u32 get_surface() override
|
||||
texture* get_surface() override
|
||||
{
|
||||
return get_view(0xAAE4, rsx::default_remap_vector);
|
||||
return (gl::texture*)this;
|
||||
}
|
||||
|
||||
u32 get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap)
|
||||
texture_view* get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap)
|
||||
{
|
||||
if (remap_encoding != current_remap_encoding)
|
||||
auto found = views.find(remap_encoding);
|
||||
if (found != views.end())
|
||||
{
|
||||
current_remap_encoding = remap_encoding;
|
||||
|
||||
bind();
|
||||
apply_swizzle_remap(GL_TEXTURE_2D, native_component_mapping, remap);
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
auto mapping = gl::apply_swizzle_remap(get_native_component_layout(), remap);
|
||||
auto view = std::make_unique<texture_view>(this, mapping.data());
|
||||
auto result = view.get();
|
||||
views[remap_encoding] = std::move(view);
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 raw_handle() const
|
||||
{
|
||||
return id();
|
||||
}
|
||||
|
||||
u32 get_view()
|
||||
{
|
||||
//Get view with components in true native layout
|
||||
//TODO: Implement real image views
|
||||
const GLenum rgba_remap[4] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glBindTexture(GL_TEXTURE_2D, id());
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, (GLint*)rgba_remap);
|
||||
|
||||
//Reset view encoding
|
||||
current_remap_encoding = 0;
|
||||
return id();
|
||||
}
|
||||
|
||||
void set_compatible_format(texture::internal_format format)
|
||||
{
|
||||
compatible_internal_format = format;
|
||||
}
|
||||
|
||||
texture::internal_format get_compatible_internal_format() const override
|
||||
{
|
||||
return compatible_internal_format;
|
||||
}
|
||||
|
||||
void update_surface()
|
||||
{
|
||||
internal_width = width();
|
||||
internal_height = height();
|
||||
surface_width = rsx::apply_inverse_resolution_scale(internal_width, true);
|
||||
surface_height = rsx::apply_inverse_resolution_scale(internal_height, true);
|
||||
|
||||
bind();
|
||||
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, (GLint*)&native_component_mapping[0]);
|
||||
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, (GLint*)&native_component_mapping[1]);
|
||||
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, (GLint*)&native_component_mapping[2]);
|
||||
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, (GLint*)&native_component_mapping[3]);
|
||||
}
|
||||
|
||||
bool matches_dimensions(u16 _width, u16 _height) const
|
||||
@ -192,27 +170,15 @@ struct gl_render_target_traits
|
||||
gl::render_target* old_surface
|
||||
)
|
||||
{
|
||||
std::unique_ptr<gl::render_target> result(new gl::render_target());
|
||||
|
||||
auto format = rsx::internals::surface_color_format_to_gl(surface_color_format);
|
||||
auto internal_fmt = rsx::internals::sized_internal_format(surface_color_format);
|
||||
|
||||
result->recreate(gl::texture::target::texture2D);
|
||||
std::unique_ptr<gl::render_target> result(new gl::render_target(rsx::apply_resolution_scale((u16)width, true),
|
||||
rsx::apply_resolution_scale((u16)height, true), (GLenum)internal_fmt));
|
||||
result->set_native_pitch((u16)width * format.channel_count * format.channel_size);
|
||||
result->set_compatible_format(internal_fmt);
|
||||
|
||||
__glcheck result->config()
|
||||
.size({ (int)rsx::apply_resolution_scale((u16)width, true), (int)rsx::apply_resolution_scale((u16)height, true) })
|
||||
.type(format.type)
|
||||
.format(format.format)
|
||||
.internal_format(internal_fmt)
|
||||
.swizzle(format.swizzle.r, format.swizzle.g, format.swizzle.b, format.swizzle.a)
|
||||
.wrap(gl::texture::wrap::clamp_to_border, gl::texture::wrap::clamp_to_border, gl::texture::wrap::clamp_to_border)
|
||||
.apply();
|
||||
|
||||
__glcheck result->pixel_pack_settings().swap_bytes(format.swap_bytes).aligment(1);
|
||||
__glcheck result->pixel_unpack_settings().swap_bytes(format.swap_bytes).aligment(1);
|
||||
|
||||
std::array<GLenum, 4> native_layout = { (GLenum)format.swizzle.a, (GLenum)format.swizzle.r, (GLenum)format.swizzle.g, (GLenum)format.swizzle.b };
|
||||
result->set_native_component_layout(native_layout);
|
||||
result->old_contents = old_surface;
|
||||
|
||||
result->set_cleared();
|
||||
@ -229,32 +195,17 @@ struct gl_render_target_traits
|
||||
gl::render_target* old_surface
|
||||
)
|
||||
{
|
||||
std::unique_ptr<gl::render_target> result(new gl::render_target());
|
||||
|
||||
auto format = rsx::internals::surface_depth_format_to_gl(surface_depth_format);
|
||||
result->recreate(gl::texture::target::texture2D);
|
||||
|
||||
const auto scale = rsx::get_resolution_scale();
|
||||
|
||||
__glcheck result->config()
|
||||
.size({ (int)rsx::apply_resolution_scale((u16)width, true), (int)rsx::apply_resolution_scale((u16)height, true) })
|
||||
.type(format.type)
|
||||
.format(format.format)
|
||||
.internal_format(format.internal_format)
|
||||
.swizzle(gl::texture::channel::r, gl::texture::channel::r, gl::texture::channel::r, gl::texture::channel::r)
|
||||
.wrap(gl::texture::wrap::clamp_to_border, gl::texture::wrap::clamp_to_border, gl::texture::wrap::clamp_to_border)
|
||||
.apply();
|
||||
|
||||
__glcheck result->pixel_pack_settings().aligment(1);
|
||||
__glcheck result->pixel_unpack_settings().aligment(1);
|
||||
std::unique_ptr<gl::render_target> result(new gl::render_target(rsx::apply_resolution_scale((u16)width, true),
|
||||
rsx::apply_resolution_scale((u16)height, true), (GLenum)format.internal_format));
|
||||
|
||||
u16 native_pitch = (u16)width * 2;
|
||||
if (surface_depth_format == rsx::surface_depth_format::z24s8)
|
||||
native_pitch *= 2;
|
||||
|
||||
std::array<GLenum, 4> native_layout = { GL_RED, GL_RED, GL_RED, GL_RED };
|
||||
result->set_native_pitch(native_pitch);
|
||||
result->set_compatible_format(format.internal_format);
|
||||
|
||||
result->set_native_component_layout(native_layout);
|
||||
result->old_contents = old_surface;
|
||||
|
||||
result->update_surface();
|
||||
@ -291,7 +242,7 @@ struct gl_render_target_traits
|
||||
return false;
|
||||
|
||||
auto internal_fmt = rsx::internals::sized_internal_format(format);
|
||||
return rtt->get_compatible_internal_format() == internal_fmt && rtt->matches_dimensions((u16)width, (u16)height);
|
||||
return rtt->get_internal_format() == internal_fmt && rtt->matches_dimensions((u16)width, (u16)height);
|
||||
}
|
||||
|
||||
static
|
||||
@ -309,7 +260,7 @@ struct gl_render_target_traits
|
||||
{
|
||||
auto pixel_format = rsx::internals::surface_color_format_to_gl(color_format);
|
||||
std::vector<u8> result(width * height * pixel_format.channel_count * pixel_format.channel_size);
|
||||
color_buffer->bind();
|
||||
glBindTexture(GL_TEXTURE_2D, color_buffer->id());
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, (GLenum)pixel_format.format, (GLenum)pixel_format.type, result.data());
|
||||
return result;
|
||||
}
|
||||
@ -319,7 +270,7 @@ struct gl_render_target_traits
|
||||
std::vector<u8> result(width * height * 4);
|
||||
|
||||
auto pixel_format = rsx::internals::surface_depth_format_to_gl(depth_format);
|
||||
depth_stencil_buffer->bind();
|
||||
glBindTexture(GL_TEXTURE_2D, depth_stencil_buffer->id());
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, (GLenum)pixel_format.format, (GLenum)pixel_format.type, result.data());
|
||||
return result;
|
||||
}
|
||||
@ -354,10 +305,7 @@ struct gl_render_targets : public rsx::surface_store<gl_render_target_traits>
|
||||
invalidated_resources.remove_if([&](auto &rtt)
|
||||
{
|
||||
if (rtt->deref_count >= 2)
|
||||
{
|
||||
rtt->remove();
|
||||
return true;
|
||||
}
|
||||
|
||||
rtt->deref_count++;
|
||||
return false;
|
||||
|
@ -336,7 +336,7 @@ namespace gl
|
||||
fmt::throw_exception("Unknown format 0x%x" HERE, texture_format);
|
||||
}
|
||||
|
||||
GLuint create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps,
|
||||
gl::texture* create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps,
|
||||
rsx::texture_dimension_extended type, rsx::texture_colorspace colorspace)
|
||||
{
|
||||
if (is_compressed_format(gcm_format))
|
||||
@ -347,43 +347,29 @@ namespace gl
|
||||
height = align(height, 4);
|
||||
}
|
||||
|
||||
GLuint id = 0;
|
||||
GLenum target;
|
||||
GLenum internal_format = get_sized_internal_format(gcm_format);
|
||||
|
||||
if (colorspace != rsx::texture_colorspace::rgb_linear)
|
||||
internal_format = get_srgb_format(internal_format);
|
||||
|
||||
glGenTextures(1, &id);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case rsx::texture_dimension_extended::texture_dimension_1d:
|
||||
target = GL_TEXTURE_1D;
|
||||
glBindTexture(GL_TEXTURE_1D, id);
|
||||
glTexStorage1D(GL_TEXTURE_1D, mipmaps, internal_format, width);
|
||||
break;
|
||||
case rsx::texture_dimension_extended::texture_dimension_2d:
|
||||
target = GL_TEXTURE_2D;
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
glTexStorage2D(GL_TEXTURE_2D, mipmaps, internal_format, width, height);
|
||||
break;
|
||||
case rsx::texture_dimension_extended::texture_dimension_3d:
|
||||
target = GL_TEXTURE_3D;
|
||||
glBindTexture(GL_TEXTURE_3D, id);
|
||||
glTexStorage3D(GL_TEXTURE_3D, mipmaps, internal_format, width, height, depth);
|
||||
break;
|
||||
case rsx::texture_dimension_extended::texture_dimension_cubemap:
|
||||
target = GL_TEXTURE_CUBE_MAP;
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, id);
|
||||
glTexStorage2D(GL_TEXTURE_CUBE_MAP, mipmaps, internal_format, width, height);
|
||||
break;
|
||||
}
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
return id;
|
||||
return new gl::texture(target, width, height, depth, mipmaps, internal_format);
|
||||
}
|
||||
|
||||
void fill_texture(rsx::texture_dimension_extended dim, u16 mipmap_count, int format, u16 width, u16 height, u16 depth,
|
||||
@ -494,7 +480,7 @@ namespace gl
|
||||
}
|
||||
}
|
||||
|
||||
void apply_swizzle_remap(GLenum target, const std::array<GLenum, 4>& swizzle_remap, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap)
|
||||
std::array<GLenum, 4> apply_swizzle_remap(const std::array<GLenum, 4>& swizzle_remap, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap)
|
||||
{
|
||||
//Remapping tables; format is A-R-G-B
|
||||
//Remap input table. Contains channel index to read color from
|
||||
@ -503,7 +489,7 @@ namespace gl
|
||||
//Remap control table. Controls whether the remap value is used, or force either 0 or 1
|
||||
const auto remap_lookup = decoded_remap.second;
|
||||
|
||||
GLenum remap_values[4];
|
||||
std::array<GLenum, 4> remap_values;
|
||||
|
||||
for (u8 channel = 0; channel < 4; ++channel)
|
||||
{
|
||||
@ -523,10 +509,7 @@ namespace gl
|
||||
}
|
||||
}
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, remap_values[0]);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, remap_values[1]);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, remap_values[2]);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, remap_values[3]);
|
||||
return remap_values;
|
||||
}
|
||||
|
||||
void upload_texture(GLuint id, u32 texaddr, u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, bool is_swizzled, rsx::texture_dimension_extended type,
|
||||
@ -538,10 +521,7 @@ namespace gl
|
||||
size_t texture_data_sz = get_placed_texture_storage_size(width, height, depth, gcm_format, mipmaps, is_cubemap, 256, 512);
|
||||
std::vector<gsl::byte> data_upload_buf(texture_data_sz);
|
||||
|
||||
const std::array<GLenum, 4>& glRemap = get_swizzle_remap(gcm_format);
|
||||
|
||||
GLenum target;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case rsx::texture_dimension_extended::texture_dimension_1d:
|
||||
@ -567,12 +547,6 @@ namespace gl
|
||||
if (static_state)
|
||||
{
|
||||
//Usually for vertex textures
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, glRemap[0]);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, glRemap[1]);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, glRemap[2]);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, glRemap[3]);
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
||||
@ -581,10 +555,6 @@ namespace gl
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
apply_swizzle_remap(target, glRemap, decoded_remap);
|
||||
}
|
||||
|
||||
//The rest of sampler state is now handled by sampler state objects
|
||||
const auto format_type = get_format_type(gcm_format);
|
||||
|
@ -10,6 +10,8 @@ namespace rsx
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class texture;
|
||||
|
||||
GLenum get_target(rsx::texture_dimension_extended type);
|
||||
GLenum get_sized_internal_format(u32 gcm_format);
|
||||
std::tuple<GLenum, GLenum> get_format_type(u32 texture_format);
|
||||
@ -17,7 +19,7 @@ namespace gl
|
||||
float max_aniso(rsx::texture_max_anisotropy aniso);
|
||||
std::array<GLenum, 4> get_swizzle_remap(u32 texture_format);
|
||||
|
||||
GLuint create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, rsx::texture_dimension_extended type, rsx::texture_colorspace colorspace);
|
||||
texture* create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, rsx::texture_dimension_extended type, rsx::texture_colorspace colorspace);
|
||||
|
||||
/**
|
||||
* is_swizzled - determines whether input bytes are in morton order
|
||||
@ -31,7 +33,7 @@ namespace gl
|
||||
const std::vector<rsx_subresource_layout>& subresources_layout, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap, bool static_state,
|
||||
rsx::texture_colorspace colorspace);
|
||||
|
||||
void apply_swizzle_remap(GLenum target, const std::array<GLenum, 4>& swizzle_remap, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap);
|
||||
std::array<GLenum, 4> apply_swizzle_remap(const std::array<GLenum, 4>& swizzle_remap, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap);
|
||||
|
||||
class sampler_state
|
||||
{
|
||||
|
@ -48,22 +48,20 @@ namespace gl
|
||||
blit_src.remove();
|
||||
}
|
||||
|
||||
u32 scale_image(u32 src, u32 dst, areai src_rect, areai dst_rect, bool linear_interpolation, bool is_depth_copy)
|
||||
void scale_image(texture* src, texture* dst, areai src_rect, areai dst_rect, bool linear_interpolation, bool is_depth_copy)
|
||||
{
|
||||
s32 old_fbo = 0;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo);
|
||||
|
||||
u32 dst_tex = dst;
|
||||
filter interp = linear_interpolation ? filter::linear : filter::nearest;
|
||||
|
||||
GLenum attachment = is_depth_copy ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0;
|
||||
|
||||
blit_src.bind();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, src, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, src->id(), 0);
|
||||
blit_src.check();
|
||||
|
||||
blit_dst.bind();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, dst_tex, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, dst->id(), 0);
|
||||
blit_dst.check();
|
||||
|
||||
GLboolean scissor_test_enabled = glIsEnabled(GL_SCISSOR_TEST);
|
||||
@ -82,7 +80,6 @@ namespace gl
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, old_fbo);
|
||||
return dst_tex;
|
||||
}
|
||||
};
|
||||
|
||||
@ -93,8 +90,11 @@ namespace gl
|
||||
u32 pbo_id = 0;
|
||||
u32 pbo_size = 0;
|
||||
|
||||
u32 vram_texture = 0;
|
||||
u32 scaled_texture = 0;
|
||||
gl::texture* vram_texture = nullptr;
|
||||
|
||||
std::unique_ptr<gl::texture_view> view;
|
||||
std::unique_ptr<gl::texture> managed_texture;
|
||||
std::unique_ptr<gl::texture> scaled_texture;
|
||||
|
||||
bool is_depth = false;
|
||||
|
||||
@ -203,19 +203,27 @@ namespace gl
|
||||
synchronized = false;
|
||||
is_depth = false;
|
||||
|
||||
vram_texture = 0;
|
||||
vram_texture = nullptr;
|
||||
managed_texture.reset();
|
||||
view.reset();
|
||||
}
|
||||
|
||||
void create(u16 w, u16 h, u16 depth, u16 mipmaps, void*,
|
||||
void create(u16 w, u16 h, u16 depth, u16 mipmaps, gl::texture_view* _view,
|
||||
gl::texture* image, u32 rsx_pitch, bool read_only,
|
||||
gl::texture::format gl_format, gl::texture::type gl_type, bool swap_bytes)
|
||||
{
|
||||
if (read_only)
|
||||
{
|
||||
managed_texture.reset(image);
|
||||
view.reset(_view);
|
||||
|
||||
aa_mode = rsx::surface_antialiasing::center_1_sample;
|
||||
}
|
||||
else
|
||||
{
|
||||
view.reset();
|
||||
managed_texture.reset();
|
||||
|
||||
if (pbo_id == 0)
|
||||
init_buffer();
|
||||
|
||||
@ -232,18 +240,21 @@ namespace gl
|
||||
this->depth = depth;
|
||||
this->mipmaps = mipmaps;
|
||||
|
||||
vram_texture = image->id();
|
||||
vram_texture = image;
|
||||
set_format(gl_format, gl_type, swap_bytes);
|
||||
}
|
||||
|
||||
void create_read_only(u32 id, u32 width, u32 height, u32 depth, u32 mipmaps)
|
||||
void create_read_only(gl::texture* image, gl::texture_view* _view, u32 width, u32 height, u32 depth, u32 mipmaps)
|
||||
{
|
||||
//Only to be used for ro memory, we dont care about most members, just dimensions and the vram texture handle
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->depth = depth;
|
||||
this->mipmaps = mipmaps;
|
||||
vram_texture = id;
|
||||
|
||||
managed_texture.reset(image);
|
||||
view.reset(_view);
|
||||
vram_texture = image;
|
||||
|
||||
rsx_pitch = 0;
|
||||
real_pitch = 0;
|
||||
@ -292,23 +303,17 @@ namespace gl
|
||||
|
||||
void set_source(gl::texture &source)
|
||||
{
|
||||
vram_texture = source.id();
|
||||
vram_texture = &source;
|
||||
}
|
||||
|
||||
void copy_texture(bool=false)
|
||||
{
|
||||
if (!glIsTexture(vram_texture))
|
||||
{
|
||||
LOG_ERROR(RSX, "Attempted to download rtt texture, but texture handle was invalid! (0x%X)", vram_texture);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pbo_id)
|
||||
{
|
||||
init_buffer();
|
||||
}
|
||||
|
||||
u32 target_texture = vram_texture;
|
||||
u32 target_texture = vram_texture->id();
|
||||
if ((rsx::get_resolution_scale_percent() != 100 && context == rsx::texture_upload_context::framebuffer_storage) ||
|
||||
(real_pitch != rsx_pitch))
|
||||
{
|
||||
@ -331,43 +336,32 @@ namespace gl
|
||||
areai src_area = { 0, 0, 0, 0 };
|
||||
const areai dst_area = { 0, 0, (s32)real_width, (s32)real_height };
|
||||
|
||||
GLenum ifmt = 0;
|
||||
glBindTexture(GL_TEXTURE_2D, vram_texture);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&ifmt);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &src_area.x2);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &src_area.y2);
|
||||
auto ifmt = vram_texture->get_internal_format();
|
||||
src_area.x2 = vram_texture->width();
|
||||
src_area.y2 = vram_texture->height();
|
||||
|
||||
if (src_area.x2 != dst_area.x2 || src_area.y2 != dst_area.y2)
|
||||
{
|
||||
if (scaled_texture != 0)
|
||||
if (scaled_texture)
|
||||
{
|
||||
int sw, sh, fmt;
|
||||
glBindTexture(GL_TEXTURE_2D, scaled_texture);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &sw);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &sh);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
|
||||
|
||||
if ((u32)sw != real_width || (u32)sh != real_height || (GLenum)fmt != ifmt)
|
||||
auto sfmt = scaled_texture->get_internal_format();
|
||||
if (scaled_texture->width() != real_width ||
|
||||
scaled_texture->height() != real_height ||
|
||||
sfmt != ifmt)
|
||||
{
|
||||
glDeleteTextures(1, &scaled_texture);
|
||||
scaled_texture = 0;
|
||||
//Discard current scaled texture
|
||||
scaled_texture.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (scaled_texture == 0)
|
||||
if (!scaled_texture)
|
||||
{
|
||||
glGenTextures(1, &scaled_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, scaled_texture);
|
||||
glTexStorage2D(GL_TEXTURE_2D, 1, ifmt, real_width, real_height);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
scaled_texture = std::make_unique<gl::texture>(GL_TEXTURE_2D, real_width, real_height, 1, 1, (GLenum)ifmt);
|
||||
}
|
||||
|
||||
bool linear_interp = false; //TODO: Make optional or detect full sized sources
|
||||
g_hw_blitter->scale_image(vram_texture, scaled_texture, src_area, dst_area, linear_interp, is_depth);
|
||||
target_texture = scaled_texture;
|
||||
g_hw_blitter->scale_image(vram_texture, scaled_texture.get(), src_area, dst_area, linear_interp, is_depth);
|
||||
target_texture = scaled_texture->id();
|
||||
}
|
||||
}
|
||||
|
||||
@ -386,12 +380,12 @@ namespace gl
|
||||
if (GLenum err = glGetError())
|
||||
{
|
||||
bool recovered = false;
|
||||
if (target_texture == scaled_texture)
|
||||
if (target_texture == scaled_texture->id())
|
||||
{
|
||||
if (get_driver_caps().EXT_dsa_supported)
|
||||
glGetTextureImageEXT(vram_texture, GL_TEXTURE_2D, 0, (GLenum)format, (GLenum)type, nullptr);
|
||||
glGetTextureImageEXT(vram_texture->id(), GL_TEXTURE_2D, 0, (GLenum)format, (GLenum)type, nullptr);
|
||||
else
|
||||
glGetTextureImage(vram_texture, 0, (GLenum)format, (GLenum)type, pbo_size, nullptr);
|
||||
glGetTextureImage(vram_texture->id(), 0, (GLenum)format, (GLenum)type, pbo_size, nullptr);
|
||||
|
||||
if (!glGetError())
|
||||
{
|
||||
@ -424,10 +418,10 @@ namespace gl
|
||||
u32 min_width = std::min((u16)tex->width(), width);
|
||||
u32 min_height = std::min((u16)tex->height(), height);
|
||||
|
||||
tex->bind();
|
||||
glBindTexture(GL_TEXTURE_2D, tex->id());
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, pack_unpack_swap_bytes);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_id);
|
||||
glTexSubImage2D((GLenum)tex->get_target(), 0, 0, 0, min_width, min_height, (GLenum)format, (GLenum)type, nullptr);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, min_width, min_height, (GLenum)format, (GLenum)type, nullptr);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
@ -513,19 +507,17 @@ namespace gl
|
||||
if (pbo_id == 0)
|
||||
{
|
||||
//Read-only texture, destroy texture memory
|
||||
glDeleteTextures(1, &vram_texture);
|
||||
managed_texture.reset();
|
||||
view.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Destroy pbo cache since vram texture is managed elsewhere
|
||||
glDeleteBuffers(1, &pbo_id);
|
||||
|
||||
if (scaled_texture)
|
||||
glDeleteTextures(1, &scaled_texture);
|
||||
scaled_texture.reset();
|
||||
}
|
||||
|
||||
vram_texture = 0;
|
||||
scaled_texture = 0;
|
||||
vram_texture = nullptr;
|
||||
pbo_id = 0;
|
||||
pbo_size = 0;
|
||||
|
||||
@ -568,14 +560,19 @@ namespace gl
|
||||
return vram_texture == 0;
|
||||
}
|
||||
|
||||
u32 get_raw_view() const
|
||||
gl::texture_view* get_raw_view() const
|
||||
{
|
||||
return vram_texture;
|
||||
return view.get();
|
||||
}
|
||||
|
||||
u32 get_raw_texture() const
|
||||
gl::texture* get_raw_texture() const
|
||||
{
|
||||
return vram_texture;
|
||||
return managed_texture.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<gl::texture_view>& get_view()
|
||||
{
|
||||
return view;
|
||||
}
|
||||
|
||||
bool is_depth_texture() const
|
||||
@ -585,44 +582,50 @@ namespace gl
|
||||
|
||||
bool has_compatible_format(gl::texture* tex) const
|
||||
{
|
||||
GLenum fmt;
|
||||
glBindTexture(GL_TEXTURE_2D, vram_texture);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&fmt);
|
||||
|
||||
if (auto as_rtt = dynamic_cast<gl::render_target*>(tex))
|
||||
{
|
||||
const auto rtt_internal_fmt = (GLenum)as_rtt->get_compatible_internal_format();
|
||||
if (rtt_internal_fmt != fmt)
|
||||
{
|
||||
//When high precision Z is enabled, RTT depth surfaces use DEPTH32F instead of DEPTH24
|
||||
if (rtt_internal_fmt == GL_DEPTH32F_STENCIL8 && fmt == GL_DEPTH24_STENCIL8)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Match
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return (gl::texture::format)fmt == tex->get_internal_format();
|
||||
//TODO
|
||||
return (tex->get_internal_format() == vram_texture->get_internal_format());
|
||||
}
|
||||
};
|
||||
|
||||
class texture_cache : public rsx::texture_cache<void*, cached_texture_section, u32, u32, gl::texture, gl::texture::format>
|
||||
class texture_cache : public rsx::texture_cache<void*, cached_texture_section, gl::texture*, gl::texture_view*, gl::texture, gl::texture::format>
|
||||
{
|
||||
private:
|
||||
|
||||
blitter m_hw_blitter;
|
||||
std::vector<u32> m_temporary_surfaces;
|
||||
struct discardable_storage
|
||||
{
|
||||
std::unique_ptr<gl::texture> image;
|
||||
std::unique_ptr<gl::texture_view> view;
|
||||
|
||||
cached_texture_section& create_texture(u32 id, u32 texaddr, u32 texsize, u32 w, u32 h, u32 depth, u32 mipmaps)
|
||||
discardable_storage()
|
||||
{}
|
||||
|
||||
discardable_storage(std::unique_ptr<gl::texture>& tex)
|
||||
{
|
||||
image = std::move(tex);
|
||||
}
|
||||
|
||||
discardable_storage(std::unique_ptr<gl::texture_view>& _view)
|
||||
{
|
||||
view = std::move(_view);
|
||||
}
|
||||
|
||||
discardable_storage(std::unique_ptr<gl::texture>& tex, std::unique_ptr<gl::texture_view>& _view)
|
||||
{
|
||||
image = std::move(tex);
|
||||
view = std::move(_view);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
blitter m_hw_blitter;
|
||||
std::vector<discardable_storage> m_temporary_surfaces;
|
||||
|
||||
cached_texture_section& create_texture(gl::texture* image, gl::texture_view* view, u32 texaddr, u32 texsize, u32 w, u32 h, u32 depth, u32 mipmaps)
|
||||
{
|
||||
cached_texture_section& tex = find_cached_texture(texaddr, texsize, true, w, h, depth);
|
||||
tex.reset(texaddr, texsize, false);
|
||||
tex.create_read_only(id, w, h, depth, mipmaps);
|
||||
tex.create_read_only(image, view, w, h, depth, mipmaps);
|
||||
read_only_range = tex.get_min_max(read_only_range);
|
||||
return tex;
|
||||
}
|
||||
@ -646,95 +649,63 @@ namespace gl
|
||||
|
||||
void clear_temporary_subresources()
|
||||
{
|
||||
for (u32 &id : m_temporary_surfaces)
|
||||
{
|
||||
glDeleteTextures(1, &id);
|
||||
}
|
||||
|
||||
m_temporary_surfaces.resize(0);
|
||||
}
|
||||
|
||||
u32 create_temporary_subresource_impl(u32 src_id, GLenum sized_internal_fmt, GLenum dst_type, u32 gcm_format,
|
||||
gl::texture_view* create_temporary_subresource_impl(gl::texture* src, GLenum sized_internal_fmt, GLenum dst_type, u32 gcm_format,
|
||||
u16 x, u16 y, u16 width, u16 height, const texture_channel_remap_t& remap, bool copy)
|
||||
{
|
||||
u32 dst_id = 0;
|
||||
|
||||
if (sized_internal_fmt == GL_NONE)
|
||||
sized_internal_fmt = gl::get_sized_internal_format(gcm_format);
|
||||
|
||||
GLenum ifmt;
|
||||
glBindTexture(GL_TEXTURE_2D, src_id);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&ifmt);
|
||||
|
||||
auto ifmt = src->get_internal_format();
|
||||
switch (ifmt)
|
||||
{
|
||||
case GL_DEPTH_COMPONENT16:
|
||||
case GL_DEPTH_COMPONENT24:
|
||||
case GL_DEPTH24_STENCIL8:
|
||||
sized_internal_fmt = ifmt;
|
||||
case gl::texture::internal_format::depth16:
|
||||
case gl::texture::internal_format::depth24_stencil8:
|
||||
case gl::texture::internal_format::depth32f_stencil8:
|
||||
sized_internal_fmt = (GLenum)ifmt;
|
||||
break;
|
||||
}
|
||||
|
||||
glGenTextures(1, &dst_id);
|
||||
glBindTexture(dst_type, dst_id);
|
||||
|
||||
if (dst_type == GL_TEXTURE_2D)
|
||||
glTexStorage2D(GL_TEXTURE_2D, 1, sized_internal_fmt, width, height);
|
||||
else if (dst_type == GL_TEXTURE_1D)
|
||||
glTexStorage1D(GL_TEXTURE_1D, 1, sized_internal_fmt, width);
|
||||
|
||||
glTexParameteri(dst_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(dst_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(dst_type, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(dst_type, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
|
||||
m_temporary_surfaces.push_back(dst_id);
|
||||
auto dst = std::make_unique<gl::texture>(dst_type, width, height, 1, 1, sized_internal_fmt);
|
||||
|
||||
if (copy)
|
||||
{
|
||||
//Empty GL_ERROR
|
||||
glGetError();
|
||||
|
||||
glCopyImageSubData(src_id, GL_TEXTURE_2D, 0, x, y, 0,
|
||||
dst_id, dst_type, 0, 0, 0, 0, width, height, 1);
|
||||
glCopyImageSubData(src->id(), GL_TEXTURE_2D, 0, x, y, 0,
|
||||
dst->id(), dst_type, 0, 0, 0, 0, width, height, 1);
|
||||
|
||||
//Check for error
|
||||
if (GLenum err = glGetError())
|
||||
{
|
||||
LOG_WARNING(RSX, "Failed to copy image subresource with GL error 0x%X", err);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Native texture views are needed here. It works because this routine is only called with rendertarget data
|
||||
if (ifmt != sized_internal_fmt)
|
||||
std::array<GLenum, 4> swizzle = src->get_native_component_layout();
|
||||
if ((GLenum)ifmt != sized_internal_fmt)
|
||||
{
|
||||
err_once("GL format mismatch (data cast?). Sized ifmt=0x%X vs Src ifmt=0x%X", sized_internal_fmt, ifmt);
|
||||
err_once("GL format mismatch (data cast?). Sized ifmt=0x%X vs Src ifmt=0x%X", sized_internal_fmt, (GLenum)ifmt);
|
||||
//Apply base component map onto the new texture if a data cast has been done
|
||||
apply_component_mapping_flags(dst_type, gcm_format, rsx::texture_create_flags::default_component_order);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Inherit the parent's default mapping. The caller should ensure the native order is set beforehand
|
||||
GLint src_remap[4];
|
||||
glBindTexture(GL_TEXTURE_2D, src_id);
|
||||
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, (GLint*)&src_remap[0]);
|
||||
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, (GLint*)&src_remap[1]);
|
||||
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, (GLint*)&src_remap[2]);
|
||||
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, (GLint*)&src_remap[3]);
|
||||
|
||||
glBindTexture(dst_type, dst_id);
|
||||
glTexParameteriv(dst_type, GL_TEXTURE_SWIZZLE_RGBA, src_remap);
|
||||
swizzle = get_component_mapping(gcm_format, rsx::texture_create_flags::default_component_order);
|
||||
}
|
||||
|
||||
if (memcmp(remap.first.data(), rsx::default_remap_vector.first.data(), 4) ||
|
||||
memcmp(remap.second.data(), rsx::default_remap_vector.second.data(), 4))
|
||||
set_up_remap_vector(dst_id, dst_type, remap);
|
||||
swizzle = apply_swizzle_remap(swizzle, remap);
|
||||
|
||||
return dst_id;
|
||||
auto view = std::make_unique<gl::texture_view>(dst.get(), dst_type, sized_internal_fmt, swizzle.data());
|
||||
auto result = view.get();
|
||||
|
||||
m_temporary_surfaces.push_back({ dst, view });
|
||||
return result;
|
||||
}
|
||||
|
||||
void apply_component_mapping_flags(GLenum target, u32 gcm_format, rsx::texture_create_flags flags)
|
||||
std::array<GLenum, 4> get_component_mapping(u32 gcm_format, rsx::texture_create_flags flags)
|
||||
{
|
||||
//NOTE: Depth textures should always read RRRR
|
||||
switch (gcm_format)
|
||||
@ -744,11 +715,7 @@ namespace gl
|
||||
case CELL_GCM_TEXTURE_DEPTH16:
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
||||
{
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_RED);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, GL_RED);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, GL_RED);
|
||||
return;
|
||||
return{ GL_RED, GL_RED, GL_RED, GL_RED };
|
||||
}
|
||||
default:
|
||||
break;
|
||||
@ -758,44 +725,21 @@ namespace gl
|
||||
{
|
||||
case rsx::texture_create_flags::default_component_order:
|
||||
{
|
||||
auto remap = gl::get_swizzle_remap(gcm_format);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, remap[1]);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, remap[2]);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, remap[3]);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, remap[0]);
|
||||
break;
|
||||
return gl::get_swizzle_remap(gcm_format);
|
||||
}
|
||||
case rsx::texture_create_flags::native_component_order:
|
||||
{
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_RED);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
|
||||
break;
|
||||
return{ GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE };
|
||||
}
|
||||
case rsx::texture_create_flags::swapped_native_component_order:
|
||||
{
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_ALPHA);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, GL_RED);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_GREEN);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, GL_BLUE);
|
||||
break;
|
||||
return{ GL_BLUE, GL_ALPHA, GL_RED, GL_GREEN };
|
||||
}
|
||||
default:
|
||||
fmt::throw_exception("Unknown texture create flags" HERE);
|
||||
}
|
||||
}
|
||||
|
||||
void set_up_remap_vector(u32 texture_id, GLenum texture_type, const texture_channel_remap_t& remap_vector)
|
||||
{
|
||||
std::array<GLenum, 4> swizzle_remap;
|
||||
glBindTexture(texture_type, texture_id);
|
||||
glGetTexParameteriv(texture_type, GL_TEXTURE_SWIZZLE_A, (GLint*)&swizzle_remap[0]);
|
||||
glGetTexParameteriv(texture_type, GL_TEXTURE_SWIZZLE_R, (GLint*)&swizzle_remap[1]);
|
||||
glGetTexParameteriv(texture_type, GL_TEXTURE_SWIZZLE_G, (GLint*)&swizzle_remap[2]);
|
||||
glGetTexParameteriv(texture_type, GL_TEXTURE_SWIZZLE_B, (GLint*)&swizzle_remap[3]);
|
||||
|
||||
apply_swizzle_remap(texture_type, swizzle_remap, remap_vector);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void free_texture_section(cached_texture_section& tex) override
|
||||
@ -803,40 +747,24 @@ namespace gl
|
||||
tex.destroy();
|
||||
}
|
||||
|
||||
u32 create_temporary_subresource_view(void*&, u32* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h,
|
||||
gl::texture_view* create_temporary_subresource_view(void*&, gl::texture** src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h,
|
||||
const texture_channel_remap_t& remap_vector) override
|
||||
{
|
||||
return create_temporary_subresource_impl(*src, GL_NONE, GL_TEXTURE_2D, gcm_format, x, y, w, h, remap_vector, true);
|
||||
}
|
||||
|
||||
u32 create_temporary_subresource_view(void*&, gl::texture* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h,
|
||||
gl::texture_view* create_temporary_subresource_view(void*&, gl::texture* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h,
|
||||
const texture_channel_remap_t& remap_vector) override
|
||||
{
|
||||
if (auto as_rtt = dynamic_cast<gl::render_target*>(src))
|
||||
{
|
||||
return create_temporary_subresource_impl(src->id(), (GLenum)as_rtt->get_compatible_internal_format(),
|
||||
GL_TEXTURE_2D, gcm_format, x, y, w, h, remap_vector, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return create_temporary_subresource_impl(src->id(), GL_NONE, GL_TEXTURE_2D, gcm_format, x, y, w, h,
|
||||
remap_vector, true);
|
||||
}
|
||||
return create_temporary_subresource_impl(src, (GLenum)src->get_internal_format(),
|
||||
GL_TEXTURE_2D, gcm_format, x, y, w, h, remap_vector, true);
|
||||
}
|
||||
|
||||
u32 generate_cubemap_from_images(void*&, u32 gcm_format, u16 size, const std::vector<copy_region_descriptor>& sources, const texture_channel_remap_t& /*remap_vector*/) override
|
||||
gl::texture_view* generate_cubemap_from_images(void*&, u32 gcm_format, u16 size, const std::vector<copy_region_descriptor>& sources, const texture_channel_remap_t& /*remap_vector*/) override
|
||||
{
|
||||
const GLenum ifmt = gl::get_sized_internal_format(gcm_format);
|
||||
GLuint dst_id = 0;
|
||||
|
||||
glGenTextures(1, &dst_id);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, dst_id);
|
||||
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, ifmt, size, size);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
auto dst_image = std::make_unique<gl::texture>(GL_TEXTURE_CUBE_MAP, size, size, 1, 1, ifmt);
|
||||
auto view = std::make_unique<gl::texture_view>(dst_image.get(), GL_TEXTURE_CUBE_MAP, ifmt);
|
||||
|
||||
//Empty GL_ERROR
|
||||
glGetError();
|
||||
@ -845,35 +773,27 @@ namespace gl
|
||||
{
|
||||
if (slice.src)
|
||||
{
|
||||
glCopyImageSubData(slice.src, GL_TEXTURE_2D, 0, slice.src_x, slice.src_y, 0,
|
||||
dst_id, GL_TEXTURE_CUBE_MAP, 0, slice.dst_x, slice.dst_y, slice.dst_z, slice.w, slice.h, 1);
|
||||
glCopyImageSubData(slice.src->id(), GL_TEXTURE_2D, 0, slice.src_x, slice.src_y, 0,
|
||||
dst_image->id(), GL_TEXTURE_CUBE_MAP, 0, slice.dst_x, slice.dst_y, slice.dst_z, slice.w, slice.h, 1);
|
||||
}
|
||||
}
|
||||
|
||||
m_temporary_surfaces.push_back(dst_id);
|
||||
|
||||
if (GLenum err = glGetError())
|
||||
{
|
||||
LOG_WARNING(RSX, "Failed to copy image subresource with GL error 0x%X", err);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dst_id;
|
||||
auto result = view.get();
|
||||
m_temporary_surfaces.push_back({ dst_image, view });
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 generate_3d_from_2d_images(void*&, u32 gcm_format, u16 width, u16 height, u16 depth, const std::vector<copy_region_descriptor>& sources, const texture_channel_remap_t& /*remap_vector*/) override
|
||||
gl::texture_view* generate_3d_from_2d_images(void*&, u32 gcm_format, u16 width, u16 height, u16 depth, const std::vector<copy_region_descriptor>& sources, const texture_channel_remap_t& /*remap_vector*/) override
|
||||
{
|
||||
const GLenum ifmt = gl::get_sized_internal_format(gcm_format);
|
||||
GLuint dst_id = 0;
|
||||
|
||||
glGenTextures(1, &dst_id);
|
||||
glBindTexture(GL_TEXTURE_3D, dst_id);
|
||||
glTexStorage3D(GL_TEXTURE_3D, 1, ifmt, width, height, depth);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
auto dst_image = std::make_unique<gl::texture>(GL_TEXTURE_3D, width, height, depth, 1, ifmt);
|
||||
auto view = std::make_unique<gl::texture_view>(dst_image.get(), GL_TEXTURE_3D, ifmt);
|
||||
|
||||
//Empty GL_ERROR
|
||||
glGetError();
|
||||
@ -882,49 +802,47 @@ namespace gl
|
||||
{
|
||||
if (slice.src)
|
||||
{
|
||||
glCopyImageSubData(slice.src, GL_TEXTURE_2D, 0, slice.src_x, slice.src_y, 0,
|
||||
dst_id, GL_TEXTURE_3D, 0, slice.dst_x, slice.dst_y, slice.dst_z, slice.w, slice.h, 1);
|
||||
glCopyImageSubData(slice.src->id(), GL_TEXTURE_2D, 0, slice.src_x, slice.src_y, 0,
|
||||
dst_image->id(), GL_TEXTURE_3D, 0, slice.dst_x, slice.dst_y, slice.dst_z, slice.w, slice.h, 1);
|
||||
}
|
||||
}
|
||||
|
||||
m_temporary_surfaces.push_back(dst_id);
|
||||
|
||||
if (GLenum err = glGetError())
|
||||
{
|
||||
LOG_WARNING(RSX, "Failed to copy image subresource with GL error 0x%X", err);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dst_id;
|
||||
auto result = view.get();
|
||||
m_temporary_surfaces.push_back({ dst_image, view });
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 generate_atlas_from_images(void*&, u32 gcm_format, u16 width, u16 height, const std::vector<copy_region_descriptor>& sections_to_copy,
|
||||
gl::texture_view* generate_atlas_from_images(void*&, u32 gcm_format, u16 width, u16 height, const std::vector<copy_region_descriptor>& sections_to_copy,
|
||||
const texture_channel_remap_t& remap_vector) override
|
||||
{
|
||||
auto result = create_temporary_subresource_impl(sections_to_copy.front().src, GL_NONE, GL_TEXTURE_2D, gcm_format, 0, 0, width, height, remap_vector, false);
|
||||
|
||||
for (const auto ®ion : sections_to_copy)
|
||||
{
|
||||
glCopyImageSubData(region.src, GL_TEXTURE_2D, 0, region.src_x, region.src_y, 0,
|
||||
result, GL_TEXTURE_2D, 0, region.dst_x, region.dst_y, 0, region.w, region.h, 1);
|
||||
glCopyImageSubData(region.src->id(), GL_TEXTURE_2D, 0, region.src_x, region.src_y, 0,
|
||||
result->image()->id(), GL_TEXTURE_2D, 0, region.dst_x, region.dst_y, 0, region.w, region.h, 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void update_image_contents(void*&, u32 dst, u32 src, u16 width, u16 height) override
|
||||
void update_image_contents(void*&, gl::texture_view* dst, gl::texture* src, u16 width, u16 height) override
|
||||
{
|
||||
glCopyImageSubData(src, GL_TEXTURE_2D, 0, 0, 0, 0,
|
||||
dst, GL_TEXTURE_2D, 0, 0, 0, 0, width, height, 1);
|
||||
glCopyImageSubData(src->id(), GL_TEXTURE_2D, 0, 0, 0, 0,
|
||||
dst->image()->id(), GL_TEXTURE_2D, 0, 0, 0, 0, width, height, 1);
|
||||
}
|
||||
|
||||
cached_texture_section* create_new_texture(void*&, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, u32 gcm_format,
|
||||
rsx::texture_upload_context context, rsx::texture_dimension_extended type, rsx::texture_create_flags flags,
|
||||
rsx::texture_colorspace colorspace, const texture_channel_remap_t& /*remap_vector*/) override
|
||||
rsx::texture_colorspace colorspace, const texture_channel_remap_t& remap_vector) override
|
||||
{
|
||||
u32 vram_texture = gl::create_texture(gcm_format, width, height, depth, mipmaps, type, colorspace);
|
||||
bool depth_flag = false;
|
||||
|
||||
switch (gcm_format)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
||||
@ -933,11 +851,12 @@ namespace gl
|
||||
break;
|
||||
}
|
||||
|
||||
auto target = gl::get_target(type);
|
||||
glBindTexture(target, vram_texture);
|
||||
apply_component_mapping_flags(target, gcm_format, flags);
|
||||
auto image = gl::create_texture(gcm_format, width, height, depth, mipmaps, type, colorspace);
|
||||
auto swizzle = get_component_mapping(gcm_format, flags);
|
||||
swizzle = gl::apply_swizzle_remap(swizzle, remap_vector);
|
||||
auto view = new gl::texture_view(image, swizzle.data());
|
||||
|
||||
auto& cached = create_texture(vram_texture, rsx_address, rsx_size, width, height, depth, mipmaps);
|
||||
auto& cached = create_texture(image, view, rsx_address, rsx_size, width, height, depth, mipmaps);
|
||||
cached.set_dirty(false);
|
||||
cached.set_depth_flag(depth_flag);
|
||||
cached.set_view_flags(flags);
|
||||
@ -1011,7 +930,7 @@ namespace gl
|
||||
section->set_sampler_status(rsx::texture_sampler_status::status_ready);
|
||||
}
|
||||
|
||||
gl::upload_texture(section->get_raw_texture(), rsx_address, gcm_format, width, height, depth, mipmaps,
|
||||
gl::upload_texture(section->get_raw_texture()->id(), rsx_address, gcm_format, width, height, depth, mipmaps,
|
||||
input_swizzled, type, subresource_layout, remap_vector, false, colorspace);
|
||||
return section;
|
||||
}
|
||||
@ -1021,8 +940,13 @@ namespace gl
|
||||
if (flags == section.get_view_flags())
|
||||
return;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, section.get_raw_texture());
|
||||
apply_component_mapping_flags(GL_TEXTURE_2D, gcm_format, flags);
|
||||
auto swizzle = get_component_mapping(gcm_format, flags);
|
||||
auto& view = section.get_view();
|
||||
|
||||
if (!view->compare_swizzle(swizzle.data()))
|
||||
{
|
||||
view.reset(new gl::texture_view(view->image(), swizzle.data()));
|
||||
}
|
||||
|
||||
section.set_view_flags(flags);
|
||||
section.set_sampler_status(rsx::texture_sampler_status::status_uninitialized);
|
||||
@ -1030,7 +954,15 @@ namespace gl
|
||||
|
||||
void set_up_remap_vector(cached_texture_section& section, const texture_channel_remap_t& remap_vector) override
|
||||
{
|
||||
set_up_remap_vector(section.get_raw_texture(), GL_TEXTURE_2D, remap_vector);
|
||||
auto& view = section.get_view();
|
||||
auto swizzle = view->component_mapping();
|
||||
|
||||
swizzle = apply_swizzle_remap(swizzle, remap_vector);
|
||||
if (!view->compare_swizzle(swizzle.data()))
|
||||
{
|
||||
view.reset(new gl::texture_view(view->image(), swizzle.data()));
|
||||
}
|
||||
|
||||
section.set_sampler_status(rsx::texture_sampler_status::status_ready);
|
||||
}
|
||||
|
||||
@ -1046,44 +978,39 @@ namespace gl
|
||||
|
||||
bool render_target_format_is_compatible(gl::texture* tex, u32 gcm_format) override
|
||||
{
|
||||
if (auto as_rtt = dynamic_cast<gl::render_target*>(tex))
|
||||
auto ifmt = tex->get_internal_format();
|
||||
switch (gcm_format)
|
||||
{
|
||||
auto ifmt = as_rtt->get_compatible_internal_format();
|
||||
switch (gcm_format)
|
||||
{
|
||||
default:
|
||||
//TODO
|
||||
err_once("Format incompatibility detected, reporting failure to force data copy (GL_INTERNAL_FORMAT=0x%X, GCM_FORMAT=0x%X)", (u32)ifmt, gcm_format);
|
||||
return false;
|
||||
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
||||
return (ifmt == gl::texture::internal_format::rgba16f);
|
||||
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
|
||||
return (ifmt == gl::texture::internal_format::rgba32f);
|
||||
case CELL_GCM_TEXTURE_X32_FLOAT:
|
||||
return (ifmt == gl::texture::internal_format::r32f);
|
||||
case CELL_GCM_TEXTURE_R5G6B5:
|
||||
return (ifmt == gl::texture::internal_format::r5g6b5);
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||
return (ifmt == gl::texture::internal_format::rgba8 ||
|
||||
ifmt == gl::texture::internal_format::depth24_stencil8 ||
|
||||
ifmt == gl::texture::internal_format::depth32f_stencil8);
|
||||
case CELL_GCM_TEXTURE_B8:
|
||||
return (ifmt == gl::texture::internal_format::r8);
|
||||
case CELL_GCM_TEXTURE_G8B8:
|
||||
return (ifmt == gl::texture::internal_format::rg8);
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
||||
return (ifmt == gl::texture::internal_format::depth24_stencil8 ||
|
||||
ifmt == gl::texture::internal_format::depth32f_stencil8 ||
|
||||
ifmt == gl::texture::internal_format::depth_stencil);
|
||||
case CELL_GCM_TEXTURE_DEPTH16:
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
||||
return (ifmt == gl::texture::internal_format::depth16 ||
|
||||
ifmt == gl::texture::internal_format::depth);
|
||||
}
|
||||
default:
|
||||
//TODO
|
||||
err_once("Format incompatibility detected, reporting failure to force data copy (GL_INTERNAL_FORMAT=0x%X, GCM_FORMAT=0x%X)", (u32)ifmt, gcm_format);
|
||||
return false;
|
||||
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
||||
return (ifmt == gl::texture::internal_format::rgba16f);
|
||||
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
|
||||
return (ifmt == gl::texture::internal_format::rgba32f);
|
||||
case CELL_GCM_TEXTURE_X32_FLOAT:
|
||||
return (ifmt == gl::texture::internal_format::r32f);
|
||||
case CELL_GCM_TEXTURE_R5G6B5:
|
||||
return (ifmt == gl::texture::internal_format::r5g6b5);
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||
return (ifmt == gl::texture::internal_format::rgba8 ||
|
||||
ifmt == gl::texture::internal_format::depth24_stencil8 ||
|
||||
ifmt == gl::texture::internal_format::depth32f_stencil8);
|
||||
case CELL_GCM_TEXTURE_B8:
|
||||
return (ifmt == gl::texture::internal_format::r8);
|
||||
case CELL_GCM_TEXTURE_G8B8:
|
||||
return (ifmt == gl::texture::internal_format::rg8);
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
||||
return (ifmt == gl::texture::internal_format::depth24_stencil8 ||
|
||||
ifmt == gl::texture::internal_format::depth32f_stencil8 ||
|
||||
ifmt == gl::texture::internal_format::depth_stencil);
|
||||
case CELL_GCM_TEXTURE_DEPTH16:
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
||||
return (ifmt == gl::texture::internal_format::depth16 ||
|
||||
ifmt == gl::texture::internal_format::depth);
|
||||
}
|
||||
|
||||
fmt::throw_exception("Format comparison for non-rendertargets is not implemented" HERE);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -241,7 +241,7 @@ gl::vertex_upload_info GLGSRender::set_vertex_buffer()
|
||||
(m_attrib_ring_buffer->size() - upload_info.persistent_mapping_offset) : m_max_texbuffer_size;
|
||||
|
||||
m_persistent_stream_view.update(m_attrib_ring_buffer.get(), upload_info.persistent_mapping_offset, (u32)view_size);
|
||||
m_gl_persistent_stream_buffer.copy_from(m_persistent_stream_view);
|
||||
m_gl_persistent_stream_buffer->copy_from(m_persistent_stream_view);
|
||||
upload_info.persistent_mapping_offset = 0;
|
||||
}
|
||||
}
|
||||
@ -258,7 +258,7 @@ gl::vertex_upload_info GLGSRender::set_vertex_buffer()
|
||||
(m_attrib_ring_buffer->size() - upload_info.volatile_mapping_offset) : m_max_texbuffer_size;
|
||||
|
||||
m_volatile_stream_view.update(m_attrib_ring_buffer.get(), upload_info.volatile_mapping_offset, (u32)view_size);
|
||||
m_gl_volatile_stream_buffer.copy_from(m_volatile_stream_view);
|
||||
m_gl_volatile_stream_buffer->copy_from(m_volatile_stream_view);
|
||||
upload_info.volatile_mapping_offset = 0;
|
||||
}
|
||||
}
|
||||
|
@ -733,7 +733,7 @@ namespace vk
|
||||
|
||||
image.reset(new vk::image(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
VK_IMAGE_TYPE_3D,
|
||||
vk::get_compatible_sampler_format(gcm_format),
|
||||
dst_format,
|
||||
width, height, depth, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user