diff options
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 7 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 242 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 7 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_resource_manager.cpp | 4 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_resource_manager.h | 2 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 32 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 12 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 63 |
8 files changed, 153 insertions, 216 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 9f7c837d6..53b52753c 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -1019,11 +1019,8 @@ void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& s if (surface != nullptr) { unit.texture = entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle; - unit.target = entry.IsArray() ? surface->TargetLayer() : surface->Target(); - unit.swizzle.r = MaxwellToGL::SwizzleSource(texture.tic.x_source); - unit.swizzle.g = MaxwellToGL::SwizzleSource(texture.tic.y_source); - unit.swizzle.b = MaxwellToGL::SwizzleSource(texture.tic.z_source); - unit.swizzle.a = MaxwellToGL::SwizzleSource(texture.tic.w_source); + surface->UpdateSwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source, + texture.tic.w_source); } else { // Can occur when texture addr is null or its memory is unmapped/invalid unit.texture = 0; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 50286432d..a79eee03e 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -18,7 +18,6 @@ #include "video_core/morton.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_rasterizer_cache.h" -#include "video_core/renderer_opengl/gl_state.h" #include "video_core/renderer_opengl/utils.h" #include "video_core/surface.h" #include "video_core/textures/astc.h" @@ -44,14 +43,14 @@ struct FormatTuple { bool compressed; }; -static void ApplyTextureDefaults(GLenum target, u32 max_mip_level) { - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1); +static void ApplyTextureDefaults(GLuint texture, u32 max_mip_level) { + glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTextureParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTextureParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTextureParameteri(texture, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1); if (max_mip_level == 1) { - glTexParameterf(target, GL_TEXTURE_LOD_BIAS, 1000.0); + glTextureParameterf(texture, GL_TEXTURE_LOD_BIAS, 1000.0); } } @@ -529,55 +528,41 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface, CachedSurface::CachedSurface(const SurfaceParams& params) : params(params), gl_target(SurfaceTargetToGL(params.target)), cached_size_in_bytes(params.size_in_bytes) { - texture.Create(); - const auto& rect{params.GetRect()}; - - // Keep track of previous texture bindings - OpenGLState cur_state = OpenGLState::GetCurState(); - const auto& old_tex = cur_state.texture_units[0]; - SCOPE_EXIT({ - cur_state.texture_units[0] = old_tex; - cur_state.Apply(); - }); - - cur_state.texture_units[0].texture = texture.handle; - cur_state.texture_units[0].target = SurfaceTargetToGL(params.target); - cur_state.Apply(); - glActiveTexture(GL_TEXTURE0); + texture.Create(gl_target); + + // TODO(Rodrigo): Using params.GetRect() returns a different size than using its Mip*(0) + // alternatives. This signals a bug on those functions. + const auto width = static_cast<GLsizei>(params.MipWidth(0)); + const auto height = static_cast<GLsizei>(params.MipHeight(0)); const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type); gl_internal_format = format_tuple.internal_format; - gl_is_compressed = format_tuple.compressed; - if (!format_tuple.compressed) { - // Only pre-create the texture for non-compressed textures. - switch (params.target) { - case SurfaceTarget::Texture1D: - glTexStorage1D(SurfaceTargetToGL(params.target), params.max_mip_level, - format_tuple.internal_format, rect.GetWidth()); - break; - case SurfaceTarget::Texture2D: - case SurfaceTarget::TextureCubemap: - glTexStorage2D(SurfaceTargetToGL(params.target), params.max_mip_level, - format_tuple.internal_format, rect.GetWidth(), rect.GetHeight()); - break; - case SurfaceTarget::Texture3D: - case SurfaceTarget::Texture2DArray: - case SurfaceTarget::TextureCubeArray: - glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level, - format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(), - params.depth); - break; - default: - LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", - static_cast<u32>(params.target)); - UNREACHABLE(); - glTexStorage2D(GL_TEXTURE_2D, params.max_mip_level, format_tuple.internal_format, - rect.GetWidth(), rect.GetHeight()); - } + switch (params.target) { + case SurfaceTarget::Texture1D: + glTextureStorage1D(texture.handle, params.max_mip_level, format_tuple.internal_format, + width); + break; + case SurfaceTarget::Texture2D: + case SurfaceTarget::TextureCubemap: + glTextureStorage2D(texture.handle, params.max_mip_level, format_tuple.internal_format, + width, height); + break; + case SurfaceTarget::Texture3D: + case SurfaceTarget::Texture2DArray: + case SurfaceTarget::TextureCubeArray: + glTextureStorage3D(texture.handle, params.max_mip_level, format_tuple.internal_format, + width, height, params.depth); + break; + default: + LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", + static_cast<u32>(params.target)); + UNREACHABLE(); + glTextureStorage2D(texture.handle, params.max_mip_level, format_tuple.internal_format, + width, height); } - ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level); + ApplyTextureDefaults(texture.handle, params.max_mip_level); OpenGL::LabelGLObject(GL_TEXTURE, texture.handle, params.addr, params.IdentityString()); @@ -751,63 +736,50 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, const auto& rect{params.GetRect(mip_map)}; // Load data from memory to the surface - const GLint x0 = static_cast<GLint>(rect.left); - const GLint y0 = static_cast<GLint>(rect.bottom); - std::size_t buffer_offset = + const auto x0 = static_cast<GLint>(rect.left); + const auto y0 = static_cast<GLint>(rect.bottom); + auto buffer_offset = static_cast<std::size_t>(static_cast<std::size_t>(y0) * params.MipWidth(mip_map) + static_cast<std::size_t>(x0)) * GetBytesPerPixel(params.pixel_format); const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); - const GLuint target_tex = texture.handle; - OpenGLState cur_state = OpenGLState::GetCurState(); - - const auto& old_tex = cur_state.texture_units[0]; - SCOPE_EXIT({ - cur_state.texture_units[0] = old_tex; - cur_state.Apply(); - }); - cur_state.texture_units[0].texture = target_tex; - cur_state.texture_units[0].target = SurfaceTargetToGL(params.target); - cur_state.Apply(); // Ensure no bad interactions with GL_UNPACK_ALIGNMENT ASSERT(params.MipWidth(mip_map) * GetBytesPerPixel(params.pixel_format) % 4 == 0); glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.MipWidth(mip_map))); - GLsizei image_size = static_cast<GLsizei>(params.GetMipmapSizeGL(mip_map, false)); - glActiveTexture(GL_TEXTURE0); + const auto image_size = static_cast<GLsizei>(params.GetMipmapSizeGL(mip_map, false)); if (tuple.compressed) { switch (params.target) { case SurfaceTarget::Texture2D: - glCompressedTexImage2D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, - static_cast<GLsizei>(params.MipWidth(mip_map)), - static_cast<GLsizei>(params.MipHeight(mip_map)), 0, image_size, - &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage2D( + texture.handle, mip_map, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)), + static_cast<GLsizei>(params.MipHeight(mip_map)), tuple.internal_format, image_size, + &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture3D: - glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, - static_cast<GLsizei>(params.MipWidth(mip_map)), - static_cast<GLsizei>(params.MipHeight(mip_map)), - static_cast<GLsizei>(params.MipDepth(mip_map)), 0, image_size, - &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage3D( + texture.handle, mip_map, 0, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)), + static_cast<GLsizei>(params.MipHeight(mip_map)), + static_cast<GLsizei>(params.MipDepth(mip_map)), tuple.internal_format, image_size, + &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture2DArray: case SurfaceTarget::TextureCubeArray: - glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, - static_cast<GLsizei>(params.MipWidth(mip_map)), - static_cast<GLsizei>(params.MipHeight(mip_map)), - static_cast<GLsizei>(params.depth), 0, image_size, - &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage3D( + texture.handle, mip_map, 0, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)), + static_cast<GLsizei>(params.MipHeight(mip_map)), static_cast<GLsizei>(params.depth), + tuple.internal_format, image_size, &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::TextureCubemap: { - GLsizei layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map)); + const auto layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map)); for (std::size_t face = 0; face < params.depth; ++face) { - glCompressedTexImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), - mip_map, tuple.internal_format, - static_cast<GLsizei>(params.MipWidth(mip_map)), - static_cast<GLsizei>(params.MipHeight(mip_map)), 0, - layer_size, &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage3D( + texture.handle, mip_map, 0, 0, static_cast<GLint>(face), + static_cast<GLsizei>(params.MipWidth(mip_map)), + static_cast<GLsizei>(params.MipHeight(mip_map)), 1, tuple.internal_format, + layer_size, &gl_buffer[mip_map][buffer_offset]); buffer_offset += layer_size; } break; @@ -816,46 +788,43 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", static_cast<u32>(params.target)); UNREACHABLE(); - glCompressedTexImage2D(GL_TEXTURE_2D, mip_map, tuple.internal_format, - static_cast<GLsizei>(params.MipWidth(mip_map)), - static_cast<GLsizei>(params.MipHeight(mip_map)), 0, - static_cast<GLsizei>(params.size_in_bytes_gl), - &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage2D( + texture.handle, mip_map, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)), + static_cast<GLsizei>(params.MipHeight(mip_map)), tuple.internal_format, + static_cast<GLsizei>(params.size_in_bytes_gl), &gl_buffer[mip_map][buffer_offset]); } } else { - switch (params.target) { case SurfaceTarget::Texture1D: - glTexSubImage1D(SurfaceTargetToGL(params.target), mip_map, x0, - static_cast<GLsizei>(rect.GetWidth()), tuple.format, tuple.type, - &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage1D(texture.handle, mip_map, x0, static_cast<GLsizei>(rect.GetWidth()), + tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture2D: - glTexSubImage2D(SurfaceTargetToGL(params.target), mip_map, x0, y0, - static_cast<GLsizei>(rect.GetWidth()), - static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, - &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage2D(texture.handle, mip_map, x0, y0, + static_cast<GLsizei>(rect.GetWidth()), + static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, + &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture3D: - glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, - static_cast<GLsizei>(rect.GetWidth()), - static_cast<GLsizei>(rect.GetHeight()), params.MipDepth(mip_map), - tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage3D(texture.handle, mip_map, x0, y0, 0, + static_cast<GLsizei>(rect.GetWidth()), + static_cast<GLsizei>(rect.GetHeight()), params.MipDepth(mip_map), + tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture2DArray: case SurfaceTarget::TextureCubeArray: - glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, - static_cast<GLsizei>(rect.GetWidth()), - static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format, - tuple.type, &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage3D(texture.handle, mip_map, x0, y0, 0, + static_cast<GLsizei>(rect.GetWidth()), + static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format, + tuple.type, &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::TextureCubemap: { std::size_t start = buffer_offset; for (std::size_t face = 0; face < params.depth; ++face) { - glTexSubImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), mip_map, - x0, y0, static_cast<GLsizei>(rect.GetWidth()), - static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, - &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage3D(texture.handle, mip_map, x0, y0, static_cast<GLint>(face), + static_cast<GLsizei>(rect.GetWidth()), + static_cast<GLsizei>(rect.GetHeight()), 1, tuple.format, + tuple.type, &gl_buffer[mip_map][buffer_offset]); buffer_offset += params.LayerSizeGL(mip_map); } break; @@ -864,9 +833,10 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", static_cast<u32>(params.target)); UNREACHABLE(); - glTexSubImage2D(GL_TEXTURE_2D, mip_map, x0, y0, static_cast<GLsizei>(rect.GetWidth()), - static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, - &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage2D(texture.handle, mip_map, x0, y0, + static_cast<GLsizei>(rect.GetWidth()), + static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, + &gl_buffer[mip_map][buffer_offset]); } } @@ -876,29 +846,18 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, void CachedSurface::EnsureTextureView() { if (texture_view.handle != 0) return; - // Compressed texture are not being created with immutable storage - UNIMPLEMENTED_IF(gl_is_compressed); const GLenum target{TargetLayer()}; const GLuint num_layers{target == GL_TEXTURE_CUBE_MAP_ARRAY ? 6u : 1u}; constexpr GLuint min_layer = 0; constexpr GLuint min_level = 0; - texture_view.Create(); - glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, min_level, - params.max_mip_level, min_layer, num_layers); - - OpenGLState cur_state = OpenGLState::GetCurState(); - const auto& old_tex = cur_state.texture_units[0]; - SCOPE_EXIT({ - cur_state.texture_units[0] = old_tex; - cur_state.Apply(); - }); - cur_state.texture_units[0].texture = texture_view.handle; - cur_state.texture_units[0].target = target; - cur_state.Apply(); - - ApplyTextureDefaults(target, params.max_mip_level); + glGenTextures(1, &texture_view.handle); + glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, 0, + params.max_mip_level, 0, 1); + ApplyTextureDefaults(texture_view.handle, params.max_mip_level); + glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA, + reinterpret_cast<const GLint*>(swizzle.data())); } MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); @@ -909,6 +868,25 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle UploadGLMipmapTexture(i, read_fb_handle, draw_fb_handle); } +void CachedSurface::UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x, + Tegra::Texture::SwizzleSource swizzle_y, + Tegra::Texture::SwizzleSource swizzle_z, + Tegra::Texture::SwizzleSource swizzle_w) { + const GLenum new_x = MaxwellToGL::SwizzleSource(swizzle_x); + const GLenum new_y = MaxwellToGL::SwizzleSource(swizzle_y); + const GLenum new_z = MaxwellToGL::SwizzleSource(swizzle_z); + const GLenum new_w = MaxwellToGL::SwizzleSource(swizzle_w); + if (swizzle[0] == new_x && swizzle[1] == new_y && swizzle[2] == new_z && swizzle[3] == new_w) { + return; + } + swizzle = {new_x, new_y, new_z, new_w}; + const auto swizzle_data = reinterpret_cast<const GLint*>(swizzle.data()); + glTextureParameteriv(texture.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data); + if (texture_view.handle != 0) { + glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data); + } +} + RasterizerCacheOpenGL::RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer) : RasterizerCache{rasterizer} { read_framebuffer.Create(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 8d7d6722c..490b8252e 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -382,6 +382,11 @@ public: // Upload data in gl_buffer to this surface's texture void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle); + void UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x, + Tegra::Texture::SwizzleSource swizzle_y, + Tegra::Texture::SwizzleSource swizzle_z, + Tegra::Texture::SwizzleSource swizzle_w); + private: void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle); @@ -393,8 +398,8 @@ private: SurfaceParams params{}; GLenum gl_target{}; GLenum gl_internal_format{}; - bool gl_is_compressed{}; std::size_t cached_size_in_bytes{}; + std::array<GLenum, 4> swizzle{GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; }; class RasterizerCacheOpenGL final : public RasterizerCache<Surface> { diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index 1da744158..4170cbd3c 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp @@ -15,12 +15,12 @@ MICROPROFILE_DEFINE(OpenGL_ResourceDeletion, "OpenGL", "Resource Deletion", MP_R namespace OpenGL { -void OGLTexture::Create() { +void OGLTexture::Create(GLenum target) { if (handle != 0) return; MICROPROFILE_SCOPE(OpenGL_ResourceCreation); - glGenTextures(1, &handle); + glCreateTextures(target, 1, &handle); } void OGLTexture::Release() { diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index e33f1e973..df76cbc4b 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h @@ -28,7 +28,7 @@ public: } /// Creates a new internal OpenGL resource and stores the handle - void Create(); + void Create(GLenum target); /// Deletes the internal OpenGL resource void Release(); diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index b7ba59350..81af803bc 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -462,29 +462,35 @@ void OpenGLState::ApplyPolygonOffset() const { } void OpenGLState::ApplyTextures() const { + bool has_delta{}; + std::size_t first{}; + std::size_t last{}; + std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures; + for (std::size_t i = 0; i < std::size(texture_units); ++i) { const auto& texture_unit = texture_units[i]; const auto& cur_state_texture_unit = cur_state.texture_units[i]; + textures[i] = texture_unit.texture; - if (texture_unit.texture != cur_state_texture_unit.texture) { - glActiveTexture(TextureUnits::MaxwellTexture(static_cast<int>(i)).Enum()); - glBindTexture(texture_unit.target, texture_unit.texture); - } - // Update the texture swizzle - if (texture_unit.swizzle.r != cur_state_texture_unit.swizzle.r || - texture_unit.swizzle.g != cur_state_texture_unit.swizzle.g || - texture_unit.swizzle.b != cur_state_texture_unit.swizzle.b || - texture_unit.swizzle.a != cur_state_texture_unit.swizzle.a) { - std::array<GLint, 4> mask = {texture_unit.swizzle.r, texture_unit.swizzle.g, - texture_unit.swizzle.b, texture_unit.swizzle.a}; - glTexParameteriv(texture_unit.target, GL_TEXTURE_SWIZZLE_RGBA, mask.data()); + if (textures[i] != cur_state_texture_unit.texture) { + if (!has_delta) { + first = i; + has_delta = true; + } + last = i; } } + + if (has_delta) { + glBindTextures(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1), + textures.data()); + } } void OpenGLState::ApplySamplers() const { bool has_delta{}; - std::size_t first{}, last{}; + std::size_t first{}; + std::size_t last{}; std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers; for (std::size_t i = 0; i < std::size(samplers); ++i) { samplers[i] = texture_units[i].sampler; diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index a5a7c0920..9e1eda5b1 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -126,26 +126,14 @@ public: struct TextureUnit { GLuint texture; // GL_TEXTURE_BINDING_2D GLuint sampler; // GL_SAMPLER_BINDING - GLenum target; - struct { - GLint r; // GL_TEXTURE_SWIZZLE_R - GLint g; // GL_TEXTURE_SWIZZLE_G - GLint b; // GL_TEXTURE_SWIZZLE_B - GLint a; // GL_TEXTURE_SWIZZLE_A - } swizzle; void Unbind() { texture = 0; - swizzle.r = GL_RED; - swizzle.g = GL_GREEN; - swizzle.b = GL_BLUE; - swizzle.a = GL_ALPHA; } void Reset() { Unbind(); sampler = 0; - target = GL_TEXTURE_2D; } }; std::array<TextureUnit, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_units; diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index e37b65b38..5b09c38ea 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -171,10 +171,6 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf Memory::GetPointer(framebuffer_addr), gl_framebuffer_data.data(), true); - state.texture_units[0].texture = screen_info.texture.resource.handle; - state.Apply(); - - glActiveTexture(GL_TEXTURE0); glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride)); // Update existing texture @@ -182,14 +178,11 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf // they differ from the LCD resolution. // TODO: Applications could theoretically crash yuzu here by specifying too large // framebuffer sizes. We should make sure that this cannot happen. - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer.width, framebuffer.height, - screen_info.texture.gl_format, screen_info.texture.gl_type, - gl_framebuffer_data.data()); + glTextureSubImage2D(screen_info.texture.resource.handle, 0, 0, 0, framebuffer.width, + framebuffer.height, screen_info.texture.gl_format, + screen_info.texture.gl_type, gl_framebuffer_data.data()); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - - state.texture_units[0].texture = 0; - state.Apply(); } } @@ -199,17 +192,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf */ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, const TextureInfo& texture) { - state.texture_units[0].texture = texture.resource.handle; - state.Apply(); - - glActiveTexture(GL_TEXTURE0); - u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r}; - - // Update existing texture - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); - - state.texture_units[0].texture = 0; - state.Apply(); + const u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r}; + glClearTexImage(texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); } /** @@ -249,26 +233,13 @@ void RendererOpenGL::InitOpenGLObjects() { sizeof(ScreenRectVertex)); // Allocate textures for the screen - screen_info.texture.resource.Create(); + screen_info.texture.resource.Create(GL_TEXTURE_2D); - // Allocation of storage is deferred until the first frame, when we - // know the framebuffer size. - - state.texture_units[0].texture = screen_info.texture.resource.handle; - state.Apply(); - - glActiveTexture(GL_TEXTURE0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + const GLuint texture = screen_info.texture.resource.handle; + glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1); screen_info.display_texture = screen_info.texture.resource.handle; - state.texture_units[0].texture = 0; - state.Apply(); - // Clear screen to black LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); } @@ -284,20 +255,19 @@ void RendererOpenGL::CreateRasterizer() { void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, const Tegra::FramebufferConfig& framebuffer) { - texture.width = framebuffer.width; texture.height = framebuffer.height; GLint internal_format; switch (framebuffer.pixel_format) { case Tegra::FramebufferConfig::PixelFormat::ABGR8: - internal_format = GL_RGBA; + internal_format = GL_RGBA8; texture.gl_format = GL_RGBA; texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; gl_framebuffer_data.resize(texture.width * texture.height * 4); break; default: - internal_format = GL_RGBA; + internal_format = GL_RGBA8; texture.gl_format = GL_RGBA; texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; gl_framebuffer_data.resize(texture.width * texture.height * 4); @@ -306,15 +276,9 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, UNREACHABLE(); } - state.texture_units[0].texture = texture.resource.handle; - state.Apply(); - - glActiveTexture(GL_TEXTURE0); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0, - texture.gl_format, texture.gl_type, nullptr); - - state.texture_units[0].texture = 0; - state.Apply(); + texture.resource.Release(); + texture.resource.Create(GL_TEXTURE_2D); + glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height); } void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, float y, float w, @@ -356,7 +320,6 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, }}; state.texture_units[0].texture = screen_info.display_texture; - state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; // Workaround brigthness problems in SMO by enabling sRGB in the final output // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987 state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed(); |