From 6d46ac1ad6cd48ba5463856c576cd0552a407771 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sat, 7 Apr 2018 13:19:49 +0300 Subject: [PATCH] gl: Reimplement textures - Separate texture data from texture views --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 90 ++-- rpcs3/Emu/RSX/GL/GLGSRender.h | 6 +- rpcs3/Emu/RSX/GL/GLHelpers.cpp | 273 ----------- rpcs3/Emu/RSX/GL/GLHelpers.h | 674 +++++++++++---------------- rpcs3/Emu/RSX/GL/GLOverlays.h | 55 +-- rpcs3/Emu/RSX/GL/GLProcTable.h | 12 +- rpcs3/Emu/RSX/GL/GLRenderTargets.h | 114 ++--- rpcs3/Emu/RSX/GL/GLTexture.cpp | 40 +- rpcs3/Emu/RSX/GL/GLTexture.h | 6 +- rpcs3/Emu/RSX/GL/GLTextureCache.h | 475 ++++++++----------- rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp | 4 +- rpcs3/Emu/RSX/VK/VKTextureCache.h | 2 +- 12 files changed, 589 insertions(+), 1162 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 91de20cf42..65f3e768c1 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -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_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_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 pixeldata = {0, 0, 0, 0}; //1D - auto tex1D = std::make_unique(); - 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_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(); - 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_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(); - 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_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(); - 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_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)m_attrib_ring_buffer->size(), m_max_texbuffer_size)); m_volatile_stream_view.update(m_attrib_ring_buffer.get(), 0, std::min((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 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 }); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 4eec4eb81a..42bd55ce33 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -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 m_gl_persistent_stream_buffer; + std::unique_ptr m_gl_volatile_stream_buffer; std::unique_ptr m_attrib_ring_buffer; std::unique_ptr 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 m_flip_tex_color; //vaos are mandatory for core profile gl::vao m_vao; diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.cpp b/rpcs3/Emu/RSX/GL/GLHelpers.cpp index 588aee1492..31ca4a8ce5 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.cpp +++ b/rpcs3/Emu/RSX/GL/GLHelpers.cpp @@ -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) diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.h b/rpcs3/Emu/RSX/GL/GLHelpers.h index 2c66ef4a54..a06810716a 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.h +++ b/rpcs3/Emu/RSX/GL/GLHelpers.h @@ -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 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(target); + m_internal_format = static_cast(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& 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 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 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); - } - }; } diff --git a/rpcs3/Emu/RSX/GL/GLOverlays.h b/rpcs3/Emu/RSX/GL/GLOverlays.h index bec9fa694b..1c91045336 100644 --- a/rpcs3/Emu/RSX/GL/GLOverlays.h +++ b/rpcs3/Emu/RSX/GL/GLOverlays.h @@ -328,7 +328,9 @@ namespace gl u32 num_elements = 0; std::vector> resources; std::unordered_map> temp_image_cache; + std::unordered_map> temp_view_cache; std::unordered_map> font_cache; + std::unordered_map> 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::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_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(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::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_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(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; } } diff --git a/rpcs3/Emu/RSX/GL/GLProcTable.h b/rpcs3/Emu/RSX/GL/GLProcTable.h index 890a8b4a02..788c698c89 100644 --- a/rpcs3/Emu/RSX/GL/GLProcTable.h +++ b/rpcs3/Emu/RSX/GL/GLProcTable.h @@ -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); diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.h b/rpcs3/Emu/RSX/GL/GLRenderTargets.h index 720ad7ed0d..4e7f98e706 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.h +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.h @@ -49,7 +49,7 @@ namespace rsx namespace gl { - class render_target : public texture, public rsx::ref_counted, public rsx::render_target_descriptor + class render_target : public texture, public rsx::ref_counted, public rsx::render_target_descriptor { 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 native_component_mapping; - u32 current_remap_encoding = 0; + std::unordered_map> 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>& remap) + texture_view* get_view(u32 remap_encoding, const std::pair, std::array>& 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(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 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 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 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 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 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 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 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 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 invalidated_resources.remove_if([&](auto &rtt) { if (rtt->deref_count >= 2) - { - rtt->remove(); return true; - } rtt->deref_count++; return false; diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index 604c321246..9bc7456241 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -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& swizzle_remap, const std::pair, std::array>& decoded_remap) + std::array apply_swizzle_remap(const std::array& swizzle_remap, const std::pair, std::array>& 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 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 data_upload_buf(texture_data_sz); - const std::array& 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); diff --git a/rpcs3/Emu/RSX/GL/GLTexture.h b/rpcs3/Emu/RSX/GL/GLTexture.h index 3c685e4a80..43234b90c2 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.h +++ b/rpcs3/Emu/RSX/GL/GLTexture.h @@ -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 get_format_type(u32 texture_format); @@ -17,7 +19,7 @@ namespace gl float max_aniso(rsx::texture_max_anisotropy aniso); std::array 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& subresources_layout, const std::pair, std::array>& decoded_remap, bool static_state, rsx::texture_colorspace colorspace); - void apply_swizzle_remap(GLenum target, const std::array& swizzle_remap, const std::pair, std::array>& decoded_remap); + std::array apply_swizzle_remap(const std::array& swizzle_remap, const std::pair, std::array>& decoded_remap); class sampler_state { diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 2c2e49fe13..f1f938657b 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -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 view; + std::unique_ptr managed_texture; + std::unique_ptr 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_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& 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(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 + class texture_cache : public rsx::texture_cache { private: - blitter m_hw_blitter; - std::vector m_temporary_surfaces; + struct discardable_storage + { + std::unique_ptr image; + std::unique_ptr 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& tex) + { + image = std::move(tex); + } + + discardable_storage(std::unique_ptr& _view) + { + view = std::move(_view); + } + + discardable_storage(std::unique_ptr& tex, std::unique_ptr& _view) + { + image = std::move(tex); + view = std::move(_view); + } + }; + + private: + + blitter m_hw_blitter; + std::vector 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(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 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(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 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 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(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& 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& 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_CUBE_MAP, size, size, 1, 1, ifmt); + auto view = std::make_unique(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& 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& 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_3D, width, height, depth, 1, ifmt); + auto view = std::make_unique(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& sections_to_copy, + gl::texture_view* generate_atlas_from_images(void*&, u32 gcm_format, u16 width, u16 height, const std::vector& 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(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: diff --git a/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp b/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp index 23664a126c..916ce3f108 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp @@ -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; } } diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 6207d3602c..3cc881b3c2 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -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));